]> WPIA git - gigi.git/commitdiff
ADD: prevent session stealing with the secure server.
authorFelix Dörre <felix@dogcraft.de>
Tue, 11 Nov 2014 15:44:33 +0000 (16:44 +0100)
committerJanis Streib <janis@dogcraft.de>
Wed, 31 Dec 2014 01:36:09 +0000 (02:36 +0100)
src/org/cacert/gigi/Gigi.java
src/org/cacert/gigi/pages/LoginPage.java
tests/org/cacert/gigi/TestCrossDomainAccess.java
tests/org/cacert/gigi/TestSeparateSessionScope.java

index 692eb3ed597feb437ad034f19287660e7b40ff73..cf75bf58335fbcc8c3b502f213d133442ae6d49b 100644 (file)
@@ -3,6 +3,7 @@ package org.cacert.gigi;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.security.KeyStore;
+import java.security.cert.X509Certificate;
 import java.util.Calendar;
 import java.util.HashMap;
 import java.util.LinkedList;
@@ -59,6 +60,8 @@ public class Gigi extends HttpServlet {
 
     public static final String LOGGEDIN = "loggedin";
 
+    public static final String CERT_SERIAL = "org.cacert.gigi.serial";
+
     public static final String USER = "user";
 
     private static final long serialVersionUID = -6386785421902852904L;
@@ -227,6 +230,16 @@ public class Gigi extends HttpServlet {
             return;
         }
         HttpSession hs = req.getSession();
+        String clientSerial = (String) hs.getAttribute(CERT_SERIAL);
+        if (clientSerial != null) {
+            X509Certificate[] cert = (X509Certificate[]) req.getAttribute("javax.servlet.request.X509Certificate");
+            if (cert == null || cert[0] == null || !cert[0].getSerialNumber().toString(16).toUpperCase().equals(clientSerial)) {
+                hs.invalidate();
+                resp.sendError(403, "Certificate mismatch.");
+                return;
+            }
+
+        }
         if (req.getParameter("lang") != null) {
             Locale l = Language.getLocaleFromString(req.getParameter("lang"));
             Language lu = Language.getInstance(l);
index 8e920d092c0ea0fb9fcfbc08ff0d4b142738640e..7f34f071bb72581aae38ab9299abecf621f28d0c 100644 (file)
@@ -115,6 +115,7 @@ public class LoginPage extends Page {
         GigiResultSet rs = ps.executeQuery();
         if (rs.next()) {
             loginSession(req, User.getById(rs.getInt(1)));
+            req.getSession().setAttribute(CERT_SERIAL, serial);
         }
         rs.close();
     }
index 28c0b20a7b207294d16a4372d785f5c6fcf5ecc9..26dc35fb312206c99d6c1adb41687ec7c435415a 100644 (file)
@@ -8,15 +8,8 @@ import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.security.GeneralSecurityException;
-import java.security.KeyPair;
-import java.security.PrivateKey;
-import java.security.cert.X509Certificate;
 import java.sql.SQLException;
 
-import org.cacert.gigi.dbObjects.Certificate;
-import org.cacert.gigi.dbObjects.Certificate.CSRType;
-import org.cacert.gigi.dbObjects.CertificateProfile;
-import org.cacert.gigi.dbObjects.User;
 import org.cacert.gigi.testUtils.IOUtils;
 import org.cacert.gigi.testUtils.ManagedTest;
 import org.cacert.gigi.util.ServerConstants;
@@ -46,17 +39,7 @@ public class TestCrossDomainAccess extends ManagedTest {
 
     @Test
     public void testCorrectOriginHeaderFromHttpsToSecure() throws MalformedURLException, IOException, GeneralSecurityException, SQLException, InterruptedException, GigiApiException {
-        String email = createUniqueName() + "@b.ce";
-        int id = createVerifiedUser("Kurti", "Hansel", email, TEST_PASSWORD);
-        KeyPair kp = generateKeypair();
-        String key1 = generatePEMCSR(kp, "CN=" + email);
-        Certificate c = new Certificate(User.getById(id), Certificate.buildDN("CN", email), "sha256", key1, CSRType.CSR, CertificateProfile.getById(1));
-        final PrivateKey pk = kp.getPrivate();
-        c.issue(null, "2y").waitFor(60000);
-        final X509Certificate ce = c.cert();
-        String cookie = login(pk, ce);
         URLConnection con = new URL("https://" + ServerConstants.getSecureHostNamePort()).openConnection();
-        con.setRequestProperty("Cookie", cookie);
         con.setRequestProperty("Origin", "https://" + ServerConstants.getWwwHostNamePortSecure());
         String contains = IOUtils.readURL(con);
         assertTrue( !contains.contains("No cross domain access allowed."));
index 20dd6ae9de11d557633dc7abdbf2f005ad8b0c5a..ba5579ff02b730b2e3aa183ae4f918f4357011e6 100644 (file)
@@ -6,7 +6,9 @@ import java.io.IOException;
 import java.net.HttpURLConnection;
 import java.net.URL;
 import java.security.GeneralSecurityException;
+import java.security.KeyManagementException;
 import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
 import java.security.PrivateKey;
 import java.security.cert.X509Certificate;
 import java.sql.SQLException;
@@ -16,6 +18,7 @@ import org.cacert.gigi.dbObjects.Certificate.CSRType;
 import org.cacert.gigi.dbObjects.CertificateProfile;
 import org.cacert.gigi.dbObjects.User;
 import org.cacert.gigi.testUtils.ManagedTest;
+import org.cacert.gigi.util.Job;
 import org.junit.Test;
 
 public class TestSeparateSessionScope extends ManagedTest {
@@ -36,16 +39,36 @@ public class TestSeparateSessionScope extends ManagedTest {
         assertTrue(isLoggedin(cookie));
         assertFalse(isLoggedin(scookie));
 
+        checkCertLogin(c, pk, scookie, 200);
+        checkCertLogin(c, pk, cookie, 302);
+    }
+
+    @Test
+    public void testSerialSteal() throws IOException, GeneralSecurityException, SQLException, InterruptedException, GigiApiException {
+        String mail = "thisgo" + createUniqueName() + "@example.com";
+        int user = createAssuranceUser("test", "tugo", mail, TEST_PASSWORD);
+        KeyPair kp = generateKeypair();
+        String csr = generatePEMCSR(kp, "CN=felix@dogcraft.de");
+        Certificate c = new Certificate(User.getById(user), Certificate.buildDN("CN", "testmail@example.com"), "sha256", csr, CSRType.CSR, CertificateProfile.getById(1));
+        Certificate c2 = new Certificate(User.getById(user), Certificate.buildDN("CN", "testmail@example.com"), "sha256", csr, CSRType.CSR, CertificateProfile.getById(1));
+        final PrivateKey pk = kp.getPrivate();
+        Job j1 = c.issue(null, "2y");
+        c2.issue(null, "2y").waitFor(60000);
+        j1.waitFor(60000);
+        final X509Certificate ce = c.cert();
+        String scookie = login(pk, ce);
+
+        checkCertLogin(c, pk, scookie, 200);
+        checkCertLogin(c2, pk, scookie, 403);
+        checkCertLogin(c, pk, scookie, 302);
+
+    }
+
+    private void checkCertLogin(Certificate c2, final PrivateKey pk, String scookie, int expected) throws IOException, NoSuchAlgorithmException, KeyManagementException, GeneralSecurityException {
         URL u = new URL("https://" + getServerName().replaceAll("^www", "secure") + SECURE_REFERENCE);
         HttpURLConnection huc = (HttpURLConnection) u.openConnection();
-        authenticateClientCert(pk, ce, huc);
+        authenticateClientCert(pk, c2.cert(), huc);
         huc.setRequestProperty("Cookie", scookie);
-        assertEquals(200, huc.getResponseCode());
-
-        HttpURLConnection huc2 = (HttpURLConnection) u.openConnection();
-        authenticateClientCert(pk, ce, huc2);
-        huc2.setRequestProperty("Cookie", cookie);
-        assertEquals(302, huc2.getResponseCode());
-
+        assertEquals(expected, huc.getResponseCode());
     }
 }