diff --git a/INSTALL b/INSTALL
index a5e51cb0..8dd50899 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,44 +1,36 @@
-/*
- * $Source: /cvsroot/owasp/webscarab/INSTALL,v $
- * Copyright (c) 2002 owasp.org.
- * This file is part of WebScarab.
- * WebScarab is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * WebScarab is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * The valid license text for this file can be retrieved with
- * the call: java -cp owasp.jar org.owasp.webscarab.LICENSE
- *
- * If you are not able to view the LICENSE that way, which should
- * always be possible within a valid and working WebScarab release,
- * please write to the Free Software Foundation, Inc.,
- * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
+INSTALL for OWASP WebScarab
+===========================
+
+=== 1. Requirements
This is the WebScarab OpenSource project, hosted at
-http://www.owasp.org/webscarab.
+https://www.owasp.org/index.php/Category:OWASP_WebScarab_Project
All source code and development stuff is done under
-http://sourceforge.net/projects/owasp
+https://github.com/OWASP/OWASP-WebScarab
-Prior to building WebScarab, you should download the various
-libraries that it depends on. You can see the list in the ant build.xml
-file, in this directory. If you got this file by checking out the source
-from the WebScarab CVS repository, you should have the required libraries
-already.
+Required tools are:
+* Apache Maven 3.0.4+ for building
+* NetBeans 7.3 for development (for the Swing forms)
-WebScarab uses the Apache Ant build tool. In order to build WebScarab, you
-should use a reasonably recent version of Ant.
-There are two Ant build tasks that depend on external tools, IzPack and
-ProGuard. You are only likely to need these tools if you plan to build
-redistributable images of WebScarab. i.e. an installer, or the self-contained
-jar. There should be no problem running the common build tasks if you do not
-have these external tools.
+=== 2. Maven
+
+Building WebScarab can be done via the Apache Maven build tool.
+Simply do:
+ mvn clean install
+will get you the one-jar JAR under the target directory.
+
+The WebScarab installer can be built via:
+ mvn clean install -Pinstaller
-// end of $Source: /cvsroot/owasp/webscarab/INSTALL,v $
+
+=== 3. Ant
+
+WebScarab can also be built via the Apache Ant build tool.
+Prior to building WebScarab via Ant, you should download the various
+libraries that it depends on. You can make Apache Maven to download the
+various required libraries via:
+ mvn package -Pant
+
+WebScarab uses the Apache Ant build tool. In order to build WebScarab, you
+should use a reasonably recent version of Ant.
diff --git a/izpack/install.xml b/izpack/install.xml
index e8ca9e16..e2cf505a 100644
--- a/izpack/install.xml
+++ b/izpack/install.xml
@@ -7,6 +7,10 @@
WebScarab
${project.version}
1.6
+ https://www.owasp.org/index.php/Category:OWASP_WebScarab_Project
+
+ true
+
@@ -37,6 +41,7 @@
-
+
+
diff --git a/izpack/shortcutSpec.xml b/izpack/shortcutSpec.xml
index e0d958ff..cfb44d21 100644
--- a/izpack/shortcutSpec.xml
+++ b/izpack/shortcutSpec.xml
@@ -25,7 +25,7 @@
startMenu="no"
startup="no"
target="java"
- commandLine="-jar "$INSTALL_PATH/Uninstaller/uninstaller.jar""
+ commandLine="-jar "$INSTALL_PATH/Uninstaller/WebScarab-${project.version}-uninstaller.jar""
type="Application"
encoding="UTF-8"
description="WebScarab uninstaller">
diff --git a/lib/bcpkix-jdk15on-148.jar b/lib/bcpkix-jdk15on-148.jar
deleted file mode 100644
index 167eecfa..00000000
Binary files a/lib/bcpkix-jdk15on-148.jar and /dev/null differ
diff --git a/lib/bcprov-jdk15on-148.jar b/lib/bcprov-jdk15on-148.jar
deleted file mode 100644
index 3fcb136d..00000000
Binary files a/lib/bcprov-jdk15on-148.jar and /dev/null differ
diff --git a/lib/bsf-2.3.0.jar b/lib/bsf-2.3.0.jar
deleted file mode 100644
index caa4dea7..00000000
Binary files a/lib/bsf-2.3.0.jar and /dev/null differ
diff --git a/lib/bsh-2.0b1.jar b/lib/bsh-2.0b1.jar
deleted file mode 100644
index c005694c..00000000
Binary files a/lib/bsh-2.0b1.jar and /dev/null differ
diff --git a/lib/chardet.jar b/lib/chardet.jar
deleted file mode 100644
index c362d03c..00000000
Binary files a/lib/chardet.jar and /dev/null differ
diff --git a/lib/commons-logging-1.0.4.jar b/lib/commons-logging-1.0.4.jar
deleted file mode 100644
index b73a80fa..00000000
Binary files a/lib/commons-logging-1.0.4.jar and /dev/null differ
diff --git a/lib/concurrent.jar b/lib/concurrent.jar
deleted file mode 100644
index 49b2cd4e..00000000
Binary files a/lib/concurrent.jar and /dev/null differ
diff --git a/lib/flex-messaging-common.jar b/lib/flex-messaging-common.jar
deleted file mode 100644
index 381cdeba..00000000
Binary files a/lib/flex-messaging-common.jar and /dev/null differ
diff --git a/lib/flex-messaging-core.jar b/lib/flex-messaging-core.jar
deleted file mode 100644
index 4fdf6e29..00000000
Binary files a/lib/flex-messaging-core.jar and /dev/null differ
diff --git a/lib/flex-messaging-remoting.jar b/lib/flex-messaging-remoting.jar
deleted file mode 100644
index d809e51e..00000000
Binary files a/lib/flex-messaging-remoting.jar and /dev/null differ
diff --git a/lib/htmlparser.jar b/lib/htmlparser.jar
deleted file mode 100644
index 385dd877..00000000
Binary files a/lib/htmlparser.jar and /dev/null differ
diff --git a/lib/jcifs-1.3.14.jar b/lib/jcifs-1.3.14.jar
deleted file mode 100644
index c3d7f4e9..00000000
Binary files a/lib/jcifs-1.3.14.jar and /dev/null differ
diff --git a/lib/jcommon-1.0.16.jar b/lib/jcommon-1.0.16.jar
deleted file mode 100644
index 4cd68074..00000000
Binary files a/lib/jcommon-1.0.16.jar and /dev/null differ
diff --git a/lib/jfreechart-1.0.13.jar b/lib/jfreechart-1.0.13.jar
deleted file mode 100644
index 83c69931..00000000
Binary files a/lib/jfreechart-1.0.13.jar and /dev/null differ
diff --git a/lib/jhall-2.0_02.jar b/lib/jhall-2.0_02.jar
deleted file mode 100644
index 6b894bc2..00000000
Binary files a/lib/jhall-2.0_02.jar and /dev/null differ
diff --git a/lib/joda-time-2.1.jar b/lib/joda-time-2.1.jar
deleted file mode 100644
index b2aca95b..00000000
Binary files a/lib/joda-time-2.1.jar and /dev/null differ
diff --git a/lib/openid4java-0.9.7.jar b/lib/openid4java-0.9.7.jar
deleted file mode 100644
index c9590d04..00000000
Binary files a/lib/openid4java-0.9.7.jar and /dev/null differ
diff --git a/lib/tagsoup-1.0rc2.jar b/lib/tagsoup-1.0rc2.jar
deleted file mode 100755
index 6e3f76e0..00000000
Binary files a/lib/tagsoup-1.0rc2.jar and /dev/null differ
diff --git a/lib/xalan-2.7.1.jar b/lib/xalan-2.7.1.jar
deleted file mode 100644
index f3da5a17..00000000
Binary files a/lib/xalan-2.7.1.jar and /dev/null differ
diff --git a/lib/xmlsec-1.4.3.jar b/lib/xmlsec-1.4.3.jar
deleted file mode 100644
index f4ae4033..00000000
Binary files a/lib/xmlsec-1.4.3.jar and /dev/null differ
diff --git a/pom.xml b/pom.xml
index 522cc5f6..b5393dc7 100644
--- a/pom.xml
+++ b/pom.xml
@@ -74,6 +74,15 @@
+
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+ 2.4
+
+
+
@@ -85,6 +94,14 @@
${project.build.directory}/staging
true
+
+ ${project.build.directory}
+ false
+ ${basedir}
+
+ webscarab_logo.gif
+
+
@@ -109,8 +126,37 @@
+
+ ant
+
+
+
+ org.apache.maven.plugins
+ maven-dependency-plugin
+ 2.7
+
+
+ copy-lib
+ package
+
+ copy-dependencies
+
+
+ ${basedir}/lib
+
+
+
+
+
+
+
+
+ org.codehaus.groovy
+ groovy-jsr223
+ 2.0.0
+
org.apache.santuario
xmlsec
@@ -131,6 +177,11 @@
flex-messaging-common
1.0
+
+ amf
+ flex-messaging-remoting
+ 1.0
+
org.samba.jcifs
jcifs
@@ -211,6 +262,11 @@
commons-codec
1.5
+
+ commons-io
+ commons-io
+ 2.4
+
junit
junit
@@ -248,7 +304,7 @@
dstovall.org
- http://dstovall.org/maven2/
+ http://onejar-maven-plugin.googlecode.com/svn/mavenrepo
diff --git a/src/org/owasp/webscarab/WebScarab.java b/src/org/owasp/webscarab/WebScarab.java
index d1d3cd8d..9c6cae83 100644
--- a/src/org/owasp/webscarab/WebScarab.java
+++ b/src/org/owasp/webscarab/WebScarab.java
@@ -141,9 +141,12 @@ public void run() {
frame.toFront();
frame.requestFocus();
splash.close();
- if (session != null && session.isDirectory())
- ui.loadSession(session);
- }
+ if (session != null && session.isDirectory())
+ ui.loadSession(session);
+ else
+ ui.createTemporarySession();
+
+ }
});
ui.run();
} catch (Exception e) {
diff --git a/src/org/owasp/webscarab/httpclient/AbstractCertificateRepository.java b/src/org/owasp/webscarab/httpclient/AbstractCertificateRepository.java
index 0a04af7c..f032ed97 100644
--- a/src/org/owasp/webscarab/httpclient/AbstractCertificateRepository.java
+++ b/src/org/owasp/webscarab/httpclient/AbstractCertificateRepository.java
@@ -30,24 +30,28 @@ public abstract class AbstractCertificateRepository implements CertificateReposi
protected Logger _logger = Logger.getLogger(getClass().getName());
private String _defaultKey = null;
- private Map _aliasPasswords = new HashMap();
- protected List _keyStores = new ArrayList();
- protected Map _keyStoreDescriptions = new HashMap();
+ private Map> _aliasPasswords = new HashMap>();
+ protected List _keyStores = new ArrayList();
+ protected Map _keyStoreDescriptions = new HashMap();
+ @Override
public int getKeyStoreCount() {
return _keyStores.size();
}
+ @Override
public String getKeyStoreDescription(int keystoreIndex) {
- return (String) _keyStoreDescriptions.get(_keyStores.get(keystoreIndex));
+ return _keyStoreDescriptions.get(_keyStores.get(keystoreIndex));
}
+ @Override
public int getAliasCount(int keystoreIndex) {
- return getAliases((KeyStore) _keyStores.get(keystoreIndex)).length;
+ return getAliases(_keyStores.get(keystoreIndex)).length;
}
+ @Override
public String getAliasAt(int keystoreIndex, int aliasIndex) {
- return getAliases((KeyStore) _keyStores.get(keystoreIndex))[aliasIndex];
+ return getAliases(_keyStores.get(keystoreIndex))[aliasIndex];
}
private String[] getAliases(KeyStore ks) {
@@ -66,9 +70,10 @@ private String[] getAliases(KeyStore ks) {
return (String[]) aliases.toArray(new String[0]);
}
+ @Override
public Certificate getCertificate(int keystoreIndex, int aliasIndex) {
try {
- KeyStore ks = (KeyStore) _keyStores.get(keystoreIndex);
+ KeyStore ks = _keyStores.get(keystoreIndex);
String alias = getAliasAt(keystoreIndex, aliasIndex);
return ks.getCertificate(alias);
} catch (Exception e) {
@@ -76,6 +81,7 @@ public Certificate getCertificate(int keystoreIndex, int aliasIndex) {
}
}
+ @Override
public String getFingerPrint(Certificate cert) throws KeyStoreException {
if (!(cert instanceof X509Certificate)) {
return null;
@@ -96,6 +102,7 @@ public String getFingerPrint(Certificate cert) throws KeyStoreException {
return buff.toString().toUpperCase() + " " + dn;
}
+ @Override
public boolean isProviderAvailable(String type) {
try {
if (type.equals("PKCS11")) {
@@ -107,8 +114,13 @@ public boolean isProviderAvailable(String type) {
return true;
}
+ @Override
public boolean isKeyUnlocked(int keystoreIndex, int aliasIndex) {
KeyStore ks = (KeyStore) _keyStores.get(keystoreIndex);
+ if (ks.getType().equals("PKCS11")) {
+ // we use the callback mechanism here
+ return true;
+ }
String alias = getAliasAt(keystoreIndex, aliasIndex);
Map pwmap = (Map) _aliasPasswords.get(ks);
@@ -118,6 +130,7 @@ public boolean isKeyUnlocked(int keystoreIndex, int aliasIndex) {
return pwmap.containsKey(alias);
}
+ @Override
public void setDefaultKey(String fingerprint) {
_defaultKey = fingerprint;
}
@@ -136,7 +149,8 @@ private int addKeyStore(KeyStore ks, String description) {
return index;
}
- public int initPKCS11(String name, String library, int slotListIndex, String kspassword) {
+ @Override
+ public int initPKCS11(String name, String library, int slotListIndex) {
try {
if (!isProviderAvailable("PKCS11")) {
return -1;
@@ -157,7 +171,7 @@ public int initPKCS11(String name, String library, int slotListIndex, String ksp
// init the key store
KeyStore ks = KeyStore.getInstance("PKCS11");
- ks.load(null, kspassword == null ? null : kspassword.toCharArray());
+ ks.load(new Pkcs11LoadStoreParameter());
return addKeyStore(ks, name);
} catch (Exception e) {
System.err.println("Error instantiating the PKCS11 provider");
@@ -166,6 +180,7 @@ public int initPKCS11(String name, String library, int slotListIndex, String ksp
}
}
+ @Override
public int loadPKCS12Certificate(String filename, String ksPassword)
throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException {
// Open the file
diff --git a/src/org/owasp/webscarab/httpclient/AliasKeyManager.java b/src/org/owasp/webscarab/httpclient/AliasKeyManager.java
index 96baf427..ef9718f0 100644
--- a/src/org/owasp/webscarab/httpclient/AliasKeyManager.java
+++ b/src/org/owasp/webscarab/httpclient/AliasKeyManager.java
@@ -35,7 +35,7 @@ public class AliasKeyManager implements X509KeyManager {
/**
* Creates a new instance of AliasKeyManager
* @param ks The KeyStore that contains the keypair to use
- * @param password the password for the key (not the keystore)
+ * @param password the optional password for the key (not the keystore)
* @param alias the alias of the certificate to use
*/
public AliasKeyManager(KeyStore ks, String alias, String keyPassword) {
@@ -44,14 +44,17 @@ public AliasKeyManager(KeyStore ks, String alias, String keyPassword) {
_keyPassword = keyPassword;
}
+ @Override
public String chooseClientAlias(String[] str, Principal[] principal, Socket socket) {
return _alias;
}
+ @Override
public String chooseServerAlias(String str, Principal[] principal, Socket socket) {
return _alias;
}
+ @Override
public X509Certificate[] getCertificateChain(String alias) {
try {
Certificate[] certs = _ks.getCertificateChain(alias);
@@ -67,13 +70,21 @@ public X509Certificate[] getCertificateChain(String alias) {
}
}
+ @Override
public String[] getClientAliases(String str, Principal[] principal) {
return new String[] { _alias };
}
+ @Override
public PrivateKey getPrivateKey(String alias) {
try {
- return (PrivateKey) _ks.getKey(alias, _keyPassword.toCharArray());
+ char [] password;
+ if (_keyPassword == null) {
+ password = null;
+ } else {
+ password = _keyPassword.toCharArray();
+ }
+ return (PrivateKey) _ks.getKey(alias, password);
} catch (KeyStoreException kse) {
kse.printStackTrace();
return null;
@@ -86,6 +97,7 @@ public PrivateKey getPrivateKey(String alias) {
}
}
+ @Override
public String[] getServerAliases(String str, Principal[] principal) {
return new String[] { _alias };
}
diff --git a/src/org/owasp/webscarab/httpclient/CertificateRepository.java b/src/org/owasp/webscarab/httpclient/CertificateRepository.java
index 8c0a43ea..324a0ea9 100644
--- a/src/org/owasp/webscarab/httpclient/CertificateRepository.java
+++ b/src/org/owasp/webscarab/httpclient/CertificateRepository.java
@@ -30,7 +30,7 @@ int loadPKCS12Certificate(String filename, String ksPassword)
String getKeyStoreDescription(int keystoreIndex);
- int initPKCS11(String name, String library, int slotListIndex, String kspassword);
+ int initPKCS11(String name, String library, int slotListIndex);
int getKeyStoreCount();
diff --git a/src/org/owasp/webscarab/httpclient/Pkcs11LoadStoreParameter.java b/src/org/owasp/webscarab/httpclient/Pkcs11LoadStoreParameter.java
new file mode 100644
index 00000000..d9cde16e
--- /dev/null
+++ b/src/org/owasp/webscarab/httpclient/Pkcs11LoadStoreParameter.java
@@ -0,0 +1,16 @@
+package org.owasp.webscarab.httpclient;
+
+import java.security.KeyStore;
+import org.owasp.webscarab.ui.swing.PasswordCallbackHandler;
+
+/**
+ *
+ * @author Frank Cornelis
+ */
+public class Pkcs11LoadStoreParameter implements KeyStore.LoadStoreParameter {
+
+ @Override
+ public KeyStore.ProtectionParameter getProtectionParameter() {
+ return new KeyStore.CallbackHandlerProtection(new PasswordCallbackHandler());
+ }
+}
diff --git a/src/org/owasp/webscarab/httpclient/SSLContextManager.java b/src/org/owasp/webscarab/httpclient/SSLContextManager.java
index 1734b60d..a4c53a13 100644
--- a/src/org/owasp/webscarab/httpclient/SSLContextManager.java
+++ b/src/org/owasp/webscarab/httpclient/SSLContextManager.java
@@ -52,7 +52,7 @@ public SSLContextManager() {
}
try {
if (System.getProperty("os.name").toLowerCase().indexOf("win") >= 0) {
- initPKCS11("P11-CAPI", "lib/p11-capi.dll", 0, "");
+ initPKCS11("P11-CAPI", "lib/p11-capi.dll", 0);
}
} catch (Exception e) {
e.printStackTrace();
diff --git a/src/org/owasp/webscarab/httpclient/URLFetcher.java b/src/org/owasp/webscarab/httpclient/URLFetcher.java
index b9b903ac..c064dc3f 100644
--- a/src/org/owasp/webscarab/httpclient/URLFetcher.java
+++ b/src/org/owasp/webscarab/httpclient/URLFetcher.java
@@ -55,7 +55,10 @@
import javax.net.ssl.SSLContext;
import java.util.logging.Logger;
+import javax.net.ssl.HandshakeCompletedEvent;
+import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLPeerUnverifiedException;
+import javax.net.ssl.SSLSession;
import jcifs.ntlmssp.NtlmFlags;
import jcifs.ntlmssp.NtlmMessage;
import jcifs.ntlmssp.Type1Message;
@@ -73,7 +76,7 @@
/** Creates a new instance of URLFetcher
* @author rdawes
*/
-public class URLFetcher implements HTTPClient {
+public class URLFetcher implements HTTPClient, HandshakeCompletedListener {
// These represent the SSL classes required to connect to the server.
private String _keyFingerprint = null;
@@ -459,6 +462,7 @@ private void connect(HttpUrl url, boolean enableSNI) throws IOException {
SSLSocket sslsocket = (SSLSocket) factory.createSocket(_socket, hostname, _socket.getPort(), true);
sslsocket.setEnabledProtocols(new String[] {"TLSv1"});
sslsocket.setUseClientMode(true);
+ sslsocket.addHandshakeCompletedListener(this);
_socket = sslsocket;
_socket.setSoTimeout(_timeout);
} catch (IOException ioe) {
@@ -616,4 +620,14 @@ private String attemptNegotiation(String challenge, String credentials) {
return authMethod + " " + Base64.encode(message.toByteArray());
}
+ @Override
+ public void handshakeCompleted(HandshakeCompletedEvent event) {
+ _logger.fine("handshake completed: " + _host);
+ String cipherSuite = event.getCipherSuite();
+ _logger.fine("cipher suite: " + cipherSuite);
+ SSLSession sslSession = event.getSession();
+ String protocol = sslSession.getProtocol();
+ _logger.fine("protocol: " + protocol);
+ _logger.fine("local principal: " + sslSession.getLocalPrincipal());
+ }
}
diff --git a/src/org/owasp/webscarab/plugin/fuzz/FuzzerModel.java b/src/org/owasp/webscarab/plugin/fuzz/FuzzerModel.java
index 00f67521..30de0d01 100644
--- a/src/org/owasp/webscarab/plugin/fuzz/FuzzerModel.java
+++ b/src/org/owasp/webscarab/plugin/fuzz/FuzzerModel.java
@@ -73,6 +73,10 @@ public FuzzerModel(FrameworkModel model) {
_model = model;
_conversationModel = new FuzzConversationModel(model);
}
+
+ public ConversationModel getTemplateConversationModel() {
+ return _model.getConversationModel();
+ }
public ConversationModel getConversationModel() {
return _conversationModel;
diff --git a/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.form b/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.form
index d5ba2666..baf1157f 100644
--- a/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.form
+++ b/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.form
@@ -1,6 +1,6 @@
-
+
-
diff --git a/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.java b/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.java
index a220bd49..963bab3c 100644
--- a/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.java
+++ b/src/org/owasp/webscarab/plugin/fuzz/swing/FuzzerPanel.java
@@ -40,6 +40,7 @@
package org.owasp.webscarab.plugin.fuzz.swing;
import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.beans.PropertyChangeEvent;
@@ -52,12 +53,14 @@
import javax.swing.AbstractAction;
import javax.swing.Action;
+import javax.swing.ComboBoxModel;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.DefaultListModel;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
+import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
@@ -76,11 +79,14 @@
import org.owasp.webscarab.plugin.fuzz.FuzzerModel;
import org.owasp.webscarab.plugin.fuzz.Parameter;
import org.owasp.webscarab.ui.swing.ColumnWidthTracker;
+import org.owasp.webscarab.ui.swing.ConversationListModel;
+import org.owasp.webscarab.ui.swing.ConversationRenderer;
import org.owasp.webscarab.ui.swing.ConversationTableModel;
import org.owasp.webscarab.ui.swing.DateRenderer;
import org.owasp.webscarab.ui.swing.ShowConversationAction;
import org.owasp.webscarab.ui.swing.SwingPluginUI;
import org.owasp.webscarab.util.swing.ColumnDataModel;
+import org.owasp.webscarab.util.swing.ListComboBoxModel;
/**
*
@@ -119,6 +125,18 @@ public FuzzerPanel(Fuzzer fuzzer) {
_model.addPropertyChangeListener(listener);
_model.addModelListener(listener);
_fuzzFactory.addPropertyChangeListener(listener);
+
+ ListModel conversationList = new ConversationListModel(_model.getTemplateConversationModel());
+ ComboBoxModel requestModel = new ListComboBoxModel(conversationList);
+ requestComboBox.setModel(requestModel);
+ requestComboBox.setRenderer(new ConversationRenderer(_model.getTemplateConversationModel()));
+
+ requestComboBox.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ requestComboBoxActionPerformed(e);
+ }
+ });
+
}
private void configureTables() {
@@ -239,7 +257,7 @@ private void updateFields(PropertyChangeEvent evt) {
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
- // //GEN-BEGIN:initComponents
+ // //GEN-BEGIN:initComponents
private void initComponents() {
java.awt.GridBagConstraints gridBagConstraints;
@@ -296,10 +314,13 @@ private void initComponents() {
jScrollPane5 = new javax.swing.JScrollPane();
conversationTable = new javax.swing.JTable();
statusLabel = new javax.swing.JLabel();
+ previousRequestPanel = new javax.swing.JPanel();
+ jLabel12 = new javax.swing.JLabel();
+ requestComboBox = new javax.swing.JComboBox();
+ fuzzDialog.setTitle("Fuzz Sources");
fuzzDialog.getContentPane().setLayout(new java.awt.GridBagLayout());
- fuzzDialog.setTitle("Fuzz Sources");
jPanel4.setLayout(new java.awt.GridBagLayout());
jLabel8.setText("Fuzz Sources");
@@ -313,6 +334,7 @@ private void initComponents() {
jScrollPane3.setMaximumSize(new java.awt.Dimension(100, 32767));
jScrollPane3.setMinimumSize(new java.awt.Dimension(100, 50));
jScrollPane3.setPreferredSize(new java.awt.Dimension(100, 131));
+
nameList.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
jScrollPane3.setViewportView(nameList);
@@ -372,14 +394,12 @@ private void initComponents() {
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
fuzzDialog.getContentPane().add(jLabel11, gridBagConstraints);
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
fuzzDialog.getContentPane().add(descriptionTextField, gridBagConstraints);
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 4;
@@ -387,7 +407,6 @@ private void initComponents() {
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
gridBagConstraints.insets = new java.awt.Insets(2, 2, 2, 2);
fuzzDialog.getContentPane().add(regexTextField, gridBagConstraints);
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 5;
@@ -402,7 +421,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
browseButtonActionPerformed(evt);
}
});
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 5;
@@ -417,7 +435,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
addButtonActionPerformed(evt);
}
});
-
jPanel3.add(addButton);
deleteButton.setText("Remove");
@@ -426,7 +443,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteButtonActionPerformed(evt);
}
});
-
jPanel3.add(deleteButton);
closeButton.setText("Close");
@@ -435,7 +451,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
closeButtonActionPerformed(evt);
}
});
-
jPanel3.add(closeButton);
gridBagConstraints = new java.awt.GridBagConstraints();
@@ -473,7 +488,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
methodTextFieldActionPerformed(evt);
}
});
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
gridBagConstraints.gridy = 1;
@@ -496,7 +510,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
urlTextFieldActionPerformed(evt);
}
});
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
gridBagConstraints.gridy = 1;
@@ -522,7 +535,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
versionTextFieldActionPerformed(evt);
}
});
-
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 2;
gridBagConstraints.gridy = 1;
@@ -537,10 +549,10 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
fuzzPanel.add(requestPanel, gridBagConstraints);
- headerPanel.setLayout(new java.awt.GridBagLayout());
-
headerPanel.setMinimumSize(new java.awt.Dimension(22, 50));
headerPanel.setPreferredSize(new java.awt.Dimension(527, 100));
+ headerPanel.setLayout(new java.awt.GridBagLayout());
+
headerTable.setModel(new javax.swing.table.DefaultTableModel(
new Object [][] {
@@ -565,7 +577,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
addHeaderButtonActionPerformed(evt);
}
});
-
jPanel1.add(addHeaderButton);
deleteHeaderButton.setText("Delete");
@@ -574,7 +585,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteHeaderButtonActionPerformed(evt);
}
});
-
jPanel1.add(deleteHeaderButton);
headerPanel.add(jPanel1, new java.awt.GridBagConstraints());
@@ -622,7 +632,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
addParameterButtonActionPerformed(evt);
}
});
-
jPanel2.add(addParameterButton);
deleteParameterButton.setText("Delete");
@@ -631,7 +640,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
deleteParameterButtonActionPerformed(evt);
}
});
-
jPanel2.add(deleteParameterButton);
parameterPanel.add(jPanel2, new java.awt.GridBagConstraints());
@@ -676,7 +684,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
sourcesButtonActionPerformed(evt);
}
});
-
actionPanel.add(sourcesButton);
startButton.setText("Start");
@@ -685,7 +692,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
startButtonActionPerformed(evt);
}
});
-
actionPanel.add(startButton);
stopButton.setText("Stop");
@@ -694,7 +700,6 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
stopButtonActionPerformed(evt);
}
});
-
actionPanel.add(stopButton);
gridBagConstraints = new java.awt.GridBagConstraints();
@@ -703,6 +708,8 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
fuzzPanel.add(actionPanel, gridBagConstraints);
gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weightx = 1.0;
gridBagConstraints.weighty = 1.0;
@@ -724,7 +731,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
+ gridBagConstraints.gridy = 2;
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
gridBagConstraints.weighty = 0.5;
add(jScrollPane5, gridBagConstraints);
@@ -734,13 +741,28 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
statusLabel.setPreferredSize(new java.awt.Dimension(150, 15));
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridy = 3;
gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
add(statusLabel, gridBagConstraints);
- }
- // //GEN-END:initComponents
+ previousRequestPanel.setLayout(new java.awt.BorderLayout());
+
+ jLabel12.setText("Previous Requests : ");
+ jLabel12.setMinimumSize(new java.awt.Dimension(135, 15));
+ previousRequestPanel.add(jLabel12, java.awt.BorderLayout.WEST);
+
+ requestComboBox.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ requestComboBoxActionPerformed(evt);
+ }
+ });
+ previousRequestPanel.add(requestComboBox, java.awt.BorderLayout.CENTER);
+
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
+ add(previousRequestPanel, gridBagConstraints);
+ }// //GEN-END:initComponents
private void closeButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_closeButtonActionPerformed
fuzzDialog.setVisible(false);
@@ -864,6 +886,14 @@ private void addHeaderButtonActionPerformed(java.awt.event.ActionEvent evt) {//G
}
_model.addFuzzHeader(row, new NamedValue("Header", "Value"));
}//GEN-LAST:event_addHeaderButtonActionPerformed
+
+ private void requestComboBoxActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_requestComboBoxActionPerformed
+ Object o = requestComboBox.getSelectedItem();
+ if (o instanceof ConversationID) {
+ ConversationID id = (ConversationID) o;
+ _fuzzer.loadTemplateFromConversation(id);
+ }
+ }//GEN-LAST:event_requestComboBoxActionPerformed
public Action[] getConversationActions() {
return new Action[] { new FuzzConversationAction() };
@@ -911,6 +941,7 @@ public ColumnDataModel[] getUrlColumns() {
private javax.swing.JLabel jLabel1;
private javax.swing.JLabel jLabel10;
private javax.swing.JLabel jLabel11;
+ private javax.swing.JLabel jLabel12;
private javax.swing.JLabel jLabel2;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
@@ -932,7 +963,9 @@ public ColumnDataModel[] getUrlColumns() {
private javax.swing.JList nameList;
private javax.swing.JTable paramTable;
private javax.swing.JPanel parameterPanel;
+ private javax.swing.JPanel previousRequestPanel;
private javax.swing.JTextField regexTextField;
+ private javax.swing.JComboBox requestComboBox;
private javax.swing.JPanel requestPanel;
private javax.swing.JButton sourcesButton;
private javax.swing.JButton startButton;
diff --git a/src/org/owasp/webscarab/plugin/saml/Saml.java b/src/org/owasp/webscarab/plugin/saml/Saml.java
index 68ca3421..1b487492 100644
--- a/src/org/owasp/webscarab/plugin/saml/Saml.java
+++ b/src/org/owasp/webscarab/plugin/saml/Saml.java
@@ -1,41 +1,41 @@
-/***********************************************************************
+/**
+ * *********************************************************************
*
* $CVSHeader$
*
- * This file is part of WebScarab, an Open Web Application Security
- * Project utility. For details, please see http://www.owasp.org/
+ * This file is part of WebScarab, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
*
- * Copyright (c) 2010 FedICT
- * Copyright (c) 2010 Frank Cornelis
+ * Copyright (c) 2010 FedICT Copyright (c) 2010 Frank Cornelis
+ *
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Getting Source
- * ==============
+ * Getting Source ==============
*
- * Source for this application is maintained at Sourceforge.net, a
- * repository for free software projects.
+ * Source for this application is maintained at Sourceforge.net, a repository
+ * for free software projects.
*
* For details, please see http://www.sourceforge.net/projects/owasp
*
*/
-
package org.owasp.webscarab.plugin.saml;
import java.util.logging.Logger;
import org.owasp.webscarab.model.ConversationID;
+import org.owasp.webscarab.model.HttpUrl;
import org.owasp.webscarab.model.NamedValue;
import org.owasp.webscarab.model.Request;
import org.owasp.webscarab.model.Response;
@@ -45,9 +45,8 @@
import org.owasp.webscarab.plugin.Plugin;
/**
- * WebScarab SAML plugin.
- * This plugin allows you to analyse SAML Messages.
- *
+ * WebScarab SAML plugin. This plugin allows you to analyse SAML Messages.
+ *
* @author Frank Cornelis
*/
public class Saml implements Plugin {
@@ -93,6 +92,23 @@ public void analyse(ConversationID id, Request request, Response response,
}
}
}
+ } else if (method.equals("GET")) {
+ HttpUrl url = request.getURL();
+ String query = url.getQuery();
+ if (null != query) {
+ NamedValue[] values = NamedValue.splitNamedValues(query, "&", "=");
+ for (int i = 0; i < values.length; i++) {
+ String name = values[i].getName();
+ String value = values[i].getValue();
+ if ("SAMLResponse".equals(name)) {
+ this._model.setSAMLResponse(id, value, true);
+ } else if ("SAMLRequest".equals(name)) {
+ this._model.setSAMLRequest(id, value, true);
+ } else if ("RelayState".equals(name)) {
+ this._model.setRelayState(id, value);
+ }
+ }
+ }
}
}
diff --git a/src/org/owasp/webscarab/plugin/saml/SamlCertificateRepository.java b/src/org/owasp/webscarab/plugin/saml/SamlCertificateRepository.java
index 53db9caa..110d66b0 100644
--- a/src/org/owasp/webscarab/plugin/saml/SamlCertificateRepository.java
+++ b/src/org/owasp/webscarab/plugin/saml/SamlCertificateRepository.java
@@ -38,6 +38,7 @@
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
+import java.security.PrivateKey;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableEntryException;
@@ -56,6 +57,8 @@ public class SamlCertificateRepository extends AbstractCertificateRepository {
private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
+ private PrivateKey privateKey;
+
@Override
public void unlockKey(int keystoreIndex, int aliasIndex, String keyPassword) throws KeyStoreException, KeyManagementException {
String fingerprint = getFingerPrint(getCertificate(keystoreIndex, aliasIndex));
@@ -64,7 +67,8 @@ public void unlockKey(int keystoreIndex, int aliasIndex, String keyPassword) thr
KeyStore keyStore = (KeyStore) this._keyStores.get(keystoreIndex);
String alias = getAliasAt(keystoreIndex, aliasIndex);
try {
- PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore.getEntry(alias, null);
+ PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) keyStore.getEntry(alias, new KeyStore.PasswordProtection(keyPassword.toCharArray()));
+ this.privateKey = privateKeyEntry.getPrivateKey();
this.propertyChangeSupport.firePropertyChange(SELECTED_KEY_ENTRY, null, privateKeyEntry);
} catch (NoSuchAlgorithmException ex) {
Logger.getLogger(SamlCertificateRepository.class.getName()).log(Level.SEVERE, null, ex);
@@ -80,4 +84,8 @@ public void addPropertyChangeListener(PropertyChangeListener listener) {
public void removePropertyChangeListener(PropertyChangeListener listener) {
this.propertyChangeSupport.removePropertyChangeListener(listener);
}
+
+ public PrivateKey getPrivateKey() {
+ return this.privateKey;
+ }
}
diff --git a/src/org/owasp/webscarab/plugin/saml/SamlHTTPClient.java b/src/org/owasp/webscarab/plugin/saml/SamlHTTPClient.java
index dd514f91..b282996b 100644
--- a/src/org/owasp/webscarab/plugin/saml/SamlHTTPClient.java
+++ b/src/org/owasp/webscarab/plugin/saml/SamlHTTPClient.java
@@ -55,6 +55,8 @@
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
+import org.apache.xml.security.encryption.XMLCipher;
+import org.apache.xml.security.encryption.XMLEncryptionException;
import org.apache.xml.security.exceptions.Base64DecodingException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
@@ -151,6 +153,12 @@ private void changeSamlResponse(Request request) {
samlProxyHeader += "replayed;";
}
+ if (this.samlProxyConfig.doDecryptAssertionAttack()) {
+ String newSamlResponse = decryptAssertion(namedValues[idx].getValue());
+ namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
+ samlProxyHeader += "decrypt assertion;";
+ }
+
if (this.samlProxyConfig.doSignWrapAttack()) {
String newSamlResponse = signatureWrapping(namedValues[idx].getValue());
namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
@@ -178,6 +186,11 @@ private void changeSamlResponse(Request request) {
samlProxyHeader += "removed assertion signature;";
}
+ if (this.samlProxyConfig.doSignAssertionAttack()) {
+ String newSamlResponse = signAssertionMessage(namedValues[idx].getValue());
+ namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
+ samlProxyHeader += "sign assertion;";
+ }
if (this.samlProxyConfig.doSignSamlMessage()) {
String newSamlResponse = signSamlMessage(namedValues[idx].getValue());
namedValues[idx] = new NamedValue(namedValues[idx].getName(), newSamlResponse);
@@ -476,6 +489,41 @@ private String injectPublicDoctype(String samlResponse) throws Base64DecodingExc
return newSamlResponse;
}
+ private String signAssertionMessage(String samlResponse) throws IOException, TransformerConfigurationException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerException, XMLSecurityException {
+ Document document = parseDocument(samlResponse);
+ Element assertionSignatureElement = SamlModel.findAssertionSignatureElement(document);
+ if (null == assertionSignatureElement) {
+ return samlResponse;
+ }
+ Element assertionElement = (Element) assertionSignatureElement.getParentNode();
+ Node beforeNode = assertionSignatureElement.getNextSibling();
+ assertionElement.removeChild(assertionSignatureElement);
+ XMLSignature xmlSignature = new XMLSignature(document, null, XMLSignature.ALGO_ID_SIGNATURE_RSA_SHA1);
+ assertionElement.insertBefore(xmlSignature.getElement(), beforeNode);
+
+ String assertionId = assertionElement.getAttribute("ID");
+ Transforms transforms = new Transforms(document);
+ transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
+ transforms.addTransform(Transforms.TRANSFORM_C14N_EXCL_OMIT_COMMENTS);
+ xmlSignature.addDocument("#" + assertionId, transforms, Constants.ALGO_ID_DIGEST_SHA1);
+
+ KeyStore.PrivateKeyEntry privateKeyEntry = this.samlProxyConfig.getPrivateKeyEntry();
+
+ KeyInfo keyInfo = xmlSignature.getKeyInfo();
+ X509Data x509Data = new X509Data(document);
+ Certificate[] certificateChain = privateKeyEntry.getCertificateChain();
+ for (int certIdx = 0; certIdx < certificateChain.length; certIdx++) {
+ Certificate certificate = certificateChain[certIdx];
+ x509Data.addCertificate((X509Certificate) certificate);
+ }
+ keyInfo.add(x509Data);
+
+ PrivateKey privateKey = privateKeyEntry.getPrivateKey();
+ xmlSignature.sign(privateKey);
+
+ return outputDocument(document);
+ }
+
private String signSamlMessage(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerConfigurationException, TransformerException, XMLSecurityException {
Document document = parseDocument(samlResponse);
Element protocolSignatureElement = SamlModel.findProtocolSignatureElement(document);
@@ -551,6 +599,15 @@ private String signatureWrapping(String samlResponse) throws IOException, Parser
String newIdValue = "renamed-" + oldIdValue;
idAttr.setValue(newIdValue);
}
+ if (this.samlProxyConfig.doRenameLastAssertionId()) {
+ Attr idAttr = importedParentElement.getAttributeNode("ID"); // SAML 2
+ if (null == idAttr) {
+ idAttr = importedParentElement.getAttributeNode("AssertionID"); // SAML 1.1
+ }
+ String oldIdValue = idAttr.getValue();
+ String newIdValue = "renamed-" + oldIdValue;
+ idAttr.setValue(newIdValue);
+ }
}
break;
case SAMLP_EXTENSIONS: {
@@ -567,6 +624,17 @@ private String signatureWrapping(String samlResponse) throws IOException, Parser
Element importedSamlResponseElement = (Element) document.importNode(samlResponseElement, true);
samlpExtensionsElement.appendChild(importedSamlResponseElement);
samlResponseElement.appendChild(samlpExtensionsElement);
+ if (this.samlProxyConfig.doRenameAssertionId()) {
+ NodeList saml2AssertionNodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion");
+ Element assertionElement = (Element) saml2AssertionNodeList.item(0);
+ Attr idAttr = assertionElement.getAttributeNode("ID"); // SAML 2
+ if (null == idAttr) {
+ idAttr = assertionElement.getAttributeNode("AssertionID"); // SAML 1.1
+ }
+ String oldIdValue = idAttr.getValue();
+ String newIdValue = "renamed-" + oldIdValue;
+ idAttr.setValue(newIdValue);
+ }
}
break;
case ASSERTION: {
@@ -652,4 +720,34 @@ private List findAssertionSignatures(Document document) {
return assertionSignatures;
}
+
+ private String decryptAssertion(String samlResponse) throws IOException, ParserConfigurationException, SAXException, Base64DecodingException, TransformerException, XMLEncryptionException, Exception {
+ Document document = parseDocument(samlResponse);
+
+ NodeList encryptedAssertionNodeList = document.getElementsByTagNameNS(
+ "urn:oasis:names:tc:SAML:2.0:assertion", "EncryptedAssertion");
+ if (encryptedAssertionNodeList.getLength() == 0) {
+ return samlResponse;
+ }
+
+ Element encryptedAssertionElement = (Element) encryptedAssertionNodeList.item(0);
+ Element encryptedDataElement = (Element) encryptedAssertionElement.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedData").item(0);
+ if (null == encryptedDataElement) {
+ return samlResponse;
+ }
+ XMLCipher xmlCipher = XMLCipher.getInstance(XMLCipher.AES_128);
+ xmlCipher.init(XMLCipher.DECRYPT_MODE, null);
+ xmlCipher.setKEK(this.samlProxyConfig.getDecryptionPrivateKeyEntry().getPrivateKey());
+ document = xmlCipher.doFinal(document, encryptedDataElement);
+
+ // remove the EncryptedAssertion container
+ encryptedAssertionNodeList = document.getElementsByTagNameNS(
+ "urn:oasis:names:tc:SAML:2.0:assertion", "EncryptedAssertion");
+ encryptedAssertionElement = (Element) encryptedAssertionNodeList.item(0);
+ Element assertionElement = (Element) encryptedAssertionElement.getFirstChild();
+ encryptedAssertionElement.getParentNode().appendChild(assertionElement);
+ encryptedAssertionElement.getParentNode().removeChild(encryptedAssertionElement);
+
+ return outputDocument(document);
+ }
}
diff --git a/src/org/owasp/webscarab/plugin/saml/SamlModel.java b/src/org/owasp/webscarab/plugin/saml/SamlModel.java
index fdd4d728..644fdd7d 100644
--- a/src/org/owasp/webscarab/plugin/saml/SamlModel.java
+++ b/src/org/owasp/webscarab/plugin/saml/SamlModel.java
@@ -1,32 +1,32 @@
-/***********************************************************************
+/**
+ * *********************************************************************
*
* $CVSHeader$
*
- * This file is part of WebScarab, an Open Web Application Security
- * Project utility. For details, please see http://www.owasp.org/
+ * This file is part of WebScarab, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
*
- * Copyright (c) 2010 FedICT
- * Copyright (c) 2010 Frank Cornelis
+ * Copyright (c) 2010 FedICT Copyright (c) 2010 Frank Cornelis
+ *
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Getting Source
- * ==============
+ * Getting Source ==============
*
- * Source for this application is maintained at Sourceforge.net, a
- * repository for free software projects.
+ * Source for this application is maintained at Sourceforge.net, a repository
+ * for free software projects.
*
* For details, please see http://www.sourceforge.net/projects/owasp
*
@@ -35,20 +35,33 @@
import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.StringWriter;
import java.net.MalformedURLException;
+import java.security.PrivateKey;
+import java.security.Key;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerConfigurationException;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.IOUtils;
import org.apache.xml.security.Init;
import org.apache.xml.security.encryption.XMLCipher;
-import org.apache.xml.security.exceptions.Base64DecodingException;
+import org.apache.xml.security.encryption.XMLEncryptionException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.keys.KeyInfo;
import org.apache.xml.security.keys.content.X509Data;
@@ -57,7 +70,6 @@
import org.apache.xml.security.signature.Manifest;
import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.signature.XMLSignatureException;
-import org.apache.xml.security.utils.Base64;
import org.bouncycastle.util.encoders.Hex;
import org.htmlparser.tags.FormTag;
import org.htmlparser.util.NodeIterator;
@@ -85,7 +97,7 @@
* @author Frank Cornelis
*/
public class SamlModel extends AbstractPluginModel {
-
+
private Logger _logger = Logger.getLogger(getClass().getName());
private final FrameworkModel model;
private final ConversationModel samlConversationModel;
@@ -95,7 +107,6 @@ public class SamlModel extends AbstractPluginModel {
public SamlModel(FrameworkModel model) {
this.model = model;
this.samlConversationModel = new FilteredConversationModel(model, model.getConversationModel()) {
-
@Override
public boolean shouldFilter(ConversationID id) {
return !isSAMLMessage(id);
@@ -116,16 +127,23 @@ public boolean shouldFilter(ConversationID id) {
Init.init();
}
+ public void setSAMLResponse(ConversationID id, String encodedSamlResponse) {
+ setSAMLResponse(id, encodedSamlResponse, false);
+ }
+
/**
* Mark this conversation message as being a SAML Response.
*
* @param id
* @param encodedSamlResponse
*/
- public void setSAMLResponse(ConversationID id, String encodedSamlResponse) {
+ public void setSAMLResponse(ConversationID id, String encodedSamlResponse, boolean deflate) {
this.model.setConversationProperty(id, "SAML-TYPE", "Response");
this.model.setConversationProperty(id, "SAML-MESSAGE",
encodedSamlResponse);
+ if (deflate) {
+ this.model.setConversationProperty(id, "SAML-DEFLATE", Boolean.TRUE.toString());
+ }
}
public void setRelayState(ConversationID id, String relayState) {
@@ -202,23 +220,31 @@ public boolean isOverSSL(ConversationID id) {
public String getDecodedSAMLMessage(ConversationID id) {
String encodedSAMLMessage = getEncodedSAMLMessage(id);
- String decodedSAMLMessage = getDecodedSAMLMessage(encodedSAMLMessage);
+ String decodedSAMLMessage = getDecodedSAMLMessage(encodedSAMLMessage, id);
return decodedSAMLMessage;
}
- public String getDecodedSAMLMessage(String encodedSamlMessage) {
+ public String getDecodedSAMLMessage(String encodedSamlMessage, ConversationID id) {
/*
* Cannot use org.owasp.webscarab.util.Encoding here as SAML tickets not
* always come with line-breaks.
*/
- String decodedSamlMessage;
- try {
- decodedSamlMessage = new String(Base64.decode(encodedSamlMessage));
- } catch (Base64DecodingException ex) {
- decodedSamlMessage = "[ERROR WHILE DECODING THE BASE64 ENCODED SAML MESSAGE]";
+ String deflate = this.model.getConversationProperty(id, "SAML-DEFLATE");
+ if (null != deflate) {
+ _logger.fine("inflating SAML message");
+ byte[] deflated = Base64.decodeBase64(encodedSamlMessage);
+ try {
+ Inflater inflater = new Inflater(true);
+ InflaterInputStream inflaterInputStream = new InflaterInputStream(new ByteArrayInputStream(deflated), inflater);
+ return new String(IOUtils.toByteArray(inflaterInputStream));
+ } catch (IOException ex) {
+ return "[ERROR INFLATING SAML MESSAGE]: " + ex.getMessage();
+ }
}
+ String decodedSamlMessage = new String(Base64.decodeBase64(encodedSamlMessage));
+
return decodedSamlMessage;
}
public static final int SAML_VERSION_2 = 2;
@@ -231,7 +257,7 @@ private Document getSAMLDocument(ConversationID id) {
}
String encodedSamlMessage = getEncodedSAMLMessage(id);
- String decodedSamlMessage = getDecodedSAMLMessage(encodedSamlMessage);
+ String decodedSamlMessage = getDecodedSAMLMessage(encodedSamlMessage, id);
ByteArrayInputStream inputStream = new ByteArrayInputStream(decodedSamlMessage.getBytes());
try {
@@ -304,7 +330,7 @@ public static Element findProtocolSignatureElement(Document document) {
}
return null;
}
-
+
public static Element findAssertionSignatureElement(Document document) {
NodeList assertionNodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:2.0:assertion", "Assertion");
if (0 == assertionNodeList.getLength()) {
@@ -332,7 +358,6 @@ public static Element findAssertionSignatureElement(Document document) {
return null;
}
-
public List verifySAMLProtocolSignature(ConversationID id) throws SamlSignatureException {
Document document = getSAMLDocument(id);
if (null == document) {
@@ -410,9 +435,16 @@ public String getSAMLType(ConversationID conversationId) {
return samlType;
}
- public void setSAMLRequest(ConversationID id, String encodedSamlRequest) {
+ public void setSAMLRequest(ConversationID id, String encodedSamlRequest, boolean deflate) {
this.model.setConversationProperty(id, "SAML-TYPE", "Request");
this.model.setConversationProperty(id, "SAML-MESSAGE", encodedSamlRequest);
+ if (deflate) {
+ this.model.setConversationProperty(id, "SAML-DEFLATE", Boolean.TRUE.toString());
+ }
+ }
+
+ public void setSAMLRequest(ConversationID id, String encodedSamlRequest) {
+ setSAMLRequest(id, encodedSamlRequest, false);
}
private boolean hasDestinationIndicationSaml2Response(Element responseElement) {
@@ -673,7 +705,7 @@ public List getDecryptedAttributes(ConversationID id, String hexKey) throws Exce
* We create a new DOM tree as XMLCipher will change the tree.
*/
String encodedSamlMessage = getEncodedSAMLMessage(id);
- String decodedSamlMessage = getDecodedSAMLMessage(encodedSamlMessage);
+ String decodedSamlMessage = getDecodedSAMLMessage(encodedSamlMessage, id);
ByteArrayInputStream inputStream = new ByteArrayInputStream(decodedSamlMessage.getBytes());
Document document = this.builder.parse(inputStream);
@@ -709,4 +741,52 @@ public List getDecryptedAttributes(ConversationID id, String hexKey) throws Exce
return samlAttributes;
}
+
+ public byte[] getEncryptedAssertion(ConversationID id) {
+ Document samlDocument = getSAMLDocument(id);
+ NodeList encryptedAssertionNodeList = samlDocument.getElementsByTagNameNS(
+ "urn:oasis:names:tc:SAML:2.0:assertion", "EncryptedAssertion");
+ if (encryptedAssertionNodeList.getLength() == 0) {
+ return null;
+ }
+ Element encryptedAssertionElement = (Element) encryptedAssertionNodeList.item(0);
+ try {
+ return toString(encryptedAssertionElement).getBytes();
+ } catch (TransformerException ex) {
+ return null;
+ }
+ }
+
+ private String toString(Node node) throws TransformerConfigurationException, TransformerException {
+ TransformerFactory transformerFactory = TransformerFactory.newInstance();
+ Transformer transformer = transformerFactory.newTransformer();
+ StringWriter stringWriter = new StringWriter();
+ transformer.transform(new DOMSource(node), new StreamResult(stringWriter));
+ return stringWriter.toString();
+ }
+
+ public byte[] getDecryptedAssertion(ConversationID id, PrivateKey privateKey) throws ParserConfigurationException, SAXException, IOException, TransformerException, XMLEncryptionException, Exception {
+ byte[] encryptedAssertion = getEncryptedAssertion(id);
+ if (null == encryptedAssertion) {
+ return null;
+ }
+ if (null == privateKey) {
+ return "null private key".getBytes();
+ }
+ DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
+ Document document = documentBuilder.parse(new ByteArrayInputStream(encryptedAssertion));
+
+ Element encryptedDataElement = (Element) document.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "EncryptedData").item(0);
+ if (null == encryptedDataElement) {
+ return "missing encrypted data element".getBytes();
+ }
+ XMLCipher xmlCipher = XMLCipher.getInstance(XMLCipher.AES_128);
+ xmlCipher.init(XMLCipher.DECRYPT_MODE, null);
+ xmlCipher.setKEK(privateKey);
+ document = xmlCipher.doFinal(document, encryptedDataElement);
+
+ return toString(document).getBytes();
+ }
}
diff --git a/src/org/owasp/webscarab/plugin/saml/SamlProxy.java b/src/org/owasp/webscarab/plugin/saml/SamlProxy.java
index 168e8759..681dfc01 100644
--- a/src/org/owasp/webscarab/plugin/saml/SamlProxy.java
+++ b/src/org/owasp/webscarab/plugin/saml/SamlProxy.java
@@ -1,32 +1,32 @@
-/***********************************************************************
+/**
+ * *********************************************************************
*
* $CVSHeader$
*
- * This file is part of WebScarab, an Open Web Application Security
- * Project utility. For details, please see http://www.owasp.org/
+ * This file is part of WebScarab, an Open Web Application Security Project
+ * utility. For details, please see http://www.owasp.org/
*
- * Copyright (c) 2010 FedICT
- * Copyright (c) 2010 Frank Cornelis
+ * Copyright (c) 2010 FedICT Copyright (c) 2010 Frank Cornelis
+ *
*
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License as published by the Free Software
+ * Foundation; either version 2 of the License, or (at your option) any later
+ * version.
*
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ * details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
+ * Place - Suite 330, Boston, MA 02111-1307, USA.
*
- * Getting Source
- * ==============
+ * Getting Source ==============
*
- * Source for this application is maintained at Sourceforge.net, a
- * repository for free software projects.
+ * Source for this application is maintained at Sourceforge.net, a repository
+ * for free software projects.
*
* For details, please see http://www.sourceforge.net/projects/owasp
*
@@ -35,6 +35,7 @@
import java.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
+import java.security.cert.X509Certificate;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,9 +46,9 @@
import org.owasp.webscarab.plugin.proxy.ProxyPlugin;
/**
- * WebScarab SAML Proxy plugin.
- * This plugin allows to modify the SAML Messages so simulate certain attacks.
- *
+ * WebScarab SAML Proxy plugin. This plugin allows to modify the SAML Messages
+ * so simulate certain attacks.
+ *
* @author Frank Cornelis
*/
public class SamlProxy extends ProxyPlugin implements SamlProxyConfig {
@@ -79,7 +80,10 @@ public class SamlProxy extends ProxyPlugin implements SamlProxyConfig {
private boolean renameAssertionId;
private boolean renameLastAssertionId;
private boolean removeAssertionSignature;
-
+ private boolean signAssertionAttack;
+ private boolean decryptAssertionAttack;
+ private KeyStore.PrivateKeyEntry decryptionPrivateKeyEntry;
+
private EventListenerList _listenerList = new EventListenerList();
private SamlModel samlModel;
@@ -216,8 +220,9 @@ public boolean doSomething() {
private void updateAttackState() {
this.attack = this.corruptSignature | this.injectAttribute | this.injectRemoteReference
- | this.injectSubject | this.removeSignature | this.replay | this.injectPublicDoctype |
- this.injectRelayState | this.signSamlMessage | this.signWrapAttack | this.removeAssertionSignature;
+ | this.injectSubject | this.removeSignature | this.replay | this.injectPublicDoctype
+ | this.injectRelayState | this.signSamlMessage | this.signWrapAttack | this.removeAssertionSignature
+ | this.signAssertionAttack | this.decryptAssertionAttack;
}
public void setInjectPublicDoctype(boolean injectPublicDoctype) {
@@ -272,7 +277,7 @@ public boolean doSignSamlMessage() {
public PrivateKeyEntry getPrivateKeyEntry() {
return this.privateKeyEntry;
}
-
+
public void setPrivateKeyEntry(PrivateKeyEntry privateKeyEntry) {
this.privateKeyEntry = privateKeyEntry;
}
@@ -377,4 +382,33 @@ public void setAttributeOccurences(Occurences occurences) {
public Occurences getAttributeOccurences() {
return this.attributeOccurences;
}
+
+ public void setSignAssertionAttack(boolean signAssertionAttack) {
+ this.signAssertionAttack = signAssertionAttack;
+ updateAttackState();
+ }
+
+ @Override
+ public boolean doSignAssertionAttack() {
+ return this.signAssertionAttack;
+ }
+
+ public void setDecryptAssertionAttack(boolean decryptAssertionAttack) {
+ this.decryptAssertionAttack = decryptAssertionAttack;
+ updateAttackState();
+ }
+
+ @Override
+ public boolean doDecryptAssertionAttack() {
+ return this.decryptAssertionAttack;
+ }
+
+ public void setDecryptionPrivateKeyEntry(PrivateKeyEntry decryptionPrivateKeyEntry) {
+ this.decryptionPrivateKeyEntry = decryptionPrivateKeyEntry;
+ }
+
+ @Override
+ public PrivateKeyEntry getDecryptionPrivateKeyEntry() {
+ return this.decryptionPrivateKeyEntry;
+ }
}
diff --git a/src/org/owasp/webscarab/plugin/saml/SamlProxyConfig.java b/src/org/owasp/webscarab/plugin/saml/SamlProxyConfig.java
index 3072c6e2..a3281b01 100644
--- a/src/org/owasp/webscarab/plugin/saml/SamlProxyConfig.java
+++ b/src/org/owasp/webscarab/plugin/saml/SamlProxyConfig.java
@@ -35,6 +35,7 @@
package org.owasp.webscarab.plugin.saml;
import java.security.KeyStore.PrivateKeyEntry;
+import java.security.cert.X509Certificate;
import java.util.List;
import org.owasp.webscarab.model.NamedValue;
@@ -78,7 +79,7 @@ public interface SamlProxyConfig {
boolean doSignSamlMessage();
- public PrivateKeyEntry getPrivateKeyEntry();
+ PrivateKeyEntry getPrivateKeyEntry();
boolean doSignWrapAttack();
@@ -95,4 +96,10 @@ public interface SamlProxyConfig {
boolean doRemoveAssertionSignature();
Occurences getAttributeOccurences();
+
+ boolean doSignAssertionAttack();
+
+ boolean doDecryptAssertionAttack();
+
+ PrivateKeyEntry getDecryptionPrivateKeyEntry();
}
diff --git a/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.form b/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.form
index 50c86dac..a4fb45aa 100644
--- a/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.form
+++ b/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.form
@@ -298,6 +298,98 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -636,12 +728,7 @@
-
-
-
-
-
-
+
@@ -826,7 +913,7 @@
-
+
@@ -839,18 +926,31 @@
-
+
-
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1534,6 +1634,100 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.java b/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.java
index 7503667f..27bde277 100644
--- a/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.java
+++ b/src/org/owasp/webscarab/plugin/saml/swing/SamlPanel.java
@@ -100,6 +100,10 @@ public class SamlPanel extends javax.swing.JPanel implements SwingPluginUI, Saml
private final AttributesTableModel encryptedAttributesTableModel;
private final SamlCertificateRepository samlCertificateRepository;
private final CertificateManager certificateManager;
+ private final CertificateManager assertionCertificateManager;
+ private final SamlCertificateRepository assertionCertificateRepository;
+ private final CertificateManager decryptionCertificateManager;
+ private final SamlCertificateRepository decryptionCertificateRepository;
/**
* Creates new form SamlPanel
@@ -157,6 +161,38 @@ public void propertyChange(PropertyChangeEvent event) {
});
this.certificateManager = new CertificateManager(this.samlCertificateRepository);
+ this.assertionCertificateRepository = new SamlCertificateRepository();
+ this.assertionCertificateRepository.addPropertyChangeListener(new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ String propertyName = event.getPropertyName();
+ if (propertyName.equals(SamlCertificateRepository.SELECTED_KEY)) {
+ String fingerprint = (String) event.getNewValue();
+ SamlPanel.this.assertionDecryptionKeyTextField.setText(fingerprint);
+ SamlPanel.this.decryptAssertionButton.setEnabled(true);
+ }
+ }
+ });
+ this.assertionCertificateManager = new CertificateManager(this.assertionCertificateRepository);
+
+ this.decryptionCertificateRepository = new SamlCertificateRepository();
+ this.decryptionCertificateRepository.addPropertyChangeListener(new PropertyChangeListener() {
+
+ @Override
+ public void propertyChange(PropertyChangeEvent event) {
+ String propertyName = event.getPropertyName();
+ if (propertyName.equals(SamlCertificateRepository.SELECTED_KEY)) {
+ String fingerprint = (String) event.getNewValue();
+ SamlPanel.this.decryptionKeyTextField.setText(fingerprint);
+ } else if (propertyName.equals(SamlCertificateRepository.SELECTED_KEY_ENTRY)) {
+ PrivateKeyEntry privateKeyEntry = (PrivateKeyEntry) event.getNewValue();
+ SamlPanel.this.saml.getSamlProxy().setDecryptionPrivateKeyEntry(privateKeyEntry);
+ }
+ }
+ });
+ this.decryptionCertificateManager = new CertificateManager(this.decryptionCertificateRepository);
+
addTableListeners();
addTreeListeners();
resetDisplay();
@@ -239,7 +275,7 @@ public void mouseClicked(MouseEvent e) {
}
}
});
-
+
this.injectAttributesTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
@Override
public void valueChanged(ListSelectionEvent e) {
@@ -251,7 +287,7 @@ public void valueChanged(ListSelectionEvent e) {
}
}
});
-
+
this.injectAttributesTableModel.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
@@ -287,13 +323,17 @@ private void resetDisplay() {
this.attributesTableModel.resetAttributes();
this.encryptedAttributesTableModel.resetAttributes();
+
+ this.encryptedAssertionXMLPanel.setBytes(null, null);
+ this.decryptedAssertionXMLPanel.setBytes(null, null);
+ this.decryptedAssertionTextPanel.setText(null, "");
}
private void displaySaml(ConversationID id) {
resetDisplay();
String encodedSamlMessage = this.samlModel.getEncodedSAMLMessage(id);
this.rawPanel.setText(null, encodedSamlMessage);
- String decodedSamlMessage = this.samlModel.getDecodedSAMLMessage(encodedSamlMessage);
+ String decodedSamlMessage = this.samlModel.getDecodedSAMLMessage(encodedSamlMessage, id);
this.textPanel.setText(null, decodedSamlMessage);
this.xmlPanel.setBytes("text/xml", decodedSamlMessage.getBytes());
String relayState = this.samlModel.getRelayState(id);
@@ -338,6 +378,8 @@ private void displaySaml(ConversationID id) {
} else {
this.decryptButton.setEnabled(false);
}
+
+ this.encryptedAssertionXMLPanel.setBytes("text/xml", this.samlModel.getEncryptedAssertion(id));
}
private void displaySignature(ConversationID id) {
@@ -395,6 +437,16 @@ private void initComponents() {
decryptButton = new javax.swing.JButton();
jScrollPane4 = new javax.swing.JScrollPane();
encryptedAttributesTable = new javax.swing.JTable();
+ encryptedAssertionPanel = new javax.swing.JPanel();
+ jPanel38 = new javax.swing.JPanel();
+ jLabel16 = new javax.swing.JLabel();
+ assertionDecryptionKeyTextField = new javax.swing.JTextField();
+ selectAssertionDecryptionKeyButton = new javax.swing.JButton();
+ decryptAssertionButton = new javax.swing.JButton();
+ jTabbedPane4 = new javax.swing.JTabbedPane();
+ encryptedAssertionXMLPanel = new org.owasp.webscarab.ui.swing.editors.XMLPanel();
+ decryptedAssertionXMLPanel = new org.owasp.webscarab.ui.swing.editors.XMLPanel();
+ decryptedAssertionTextPanel = new org.owasp.webscarab.ui.swing.editors.TextPanel();
htmlFormPanel = new javax.swing.JPanel();
jPanel5 = new javax.swing.JPanel();
jLabel7 = new javax.swing.JLabel();
@@ -428,7 +480,7 @@ private void initComponents() {
jPanel8 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
samlTable = new javax.swing.JTable();
- jPanel6 = new javax.swing.JPanel();
+ signatureAttacksPanel = new javax.swing.JPanel();
jPanel10 = new javax.swing.JPanel();
jPanel7 = new javax.swing.JPanel();
jPanel11 = new javax.swing.JPanel();
@@ -446,6 +498,7 @@ private void initComponents() {
jLabel21 = new javax.swing.JLabel();
selectKeyButton = new javax.swing.JButton();
keyTextField = new javax.swing.JTextField();
+ signAssertionCheckBox = new javax.swing.JCheckBox();
jPanel30 = new javax.swing.JPanel();
jPanel32 = new javax.swing.JPanel();
signWrapAttackCheckBox = new javax.swing.JCheckBox();
@@ -502,6 +555,14 @@ private void initComponents() {
samlReplayCheckBox = new javax.swing.JCheckBox();
jLabel1 = new javax.swing.JLabel();
samlReplayLabel = new javax.swing.JLabel();
+ jPanel39 = new javax.swing.JPanel();
+ jPanel40 = new javax.swing.JPanel();
+ jPanel41 = new javax.swing.JPanel();
+ jPanel42 = new javax.swing.JPanel();
+ decryptAssertionCheckBox = new javax.swing.JCheckBox();
+ jLabel24 = new javax.swing.JLabel();
+ decryptionKeyTextField = new javax.swing.JTextField();
+ decryptionSelectKeyButton = new javax.swing.JButton();
setLayout(new java.awt.BorderLayout());
@@ -604,6 +665,44 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
jTabbedPane1.addTab("Encrypted Attributes", encryptedAttributesPanel);
+ encryptedAssertionPanel.setLayout(new java.awt.BorderLayout());
+
+ jPanel38.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
+
+ jLabel16.setText("Key:");
+ jPanel38.add(jLabel16);
+
+ assertionDecryptionKeyTextField.setEditable(false);
+ assertionDecryptionKeyTextField.setColumns(30);
+ jPanel38.add(assertionDecryptionKeyTextField);
+
+ selectAssertionDecryptionKeyButton.setText("Select key...");
+ selectAssertionDecryptionKeyButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ selectAssertionDecryptionKeyButtonActionPerformed(evt);
+ }
+ });
+ jPanel38.add(selectAssertionDecryptionKeyButton);
+
+ decryptAssertionButton.setText("Decrypt Assertion");
+ decryptAssertionButton.setEnabled(false);
+ decryptAssertionButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ decryptAssertionButtonActionPerformed(evt);
+ }
+ });
+ jPanel38.add(decryptAssertionButton);
+
+ encryptedAssertionPanel.add(jPanel38, java.awt.BorderLayout.PAGE_START);
+
+ jTabbedPane4.addTab("XML", encryptedAssertionXMLPanel);
+ jTabbedPane4.addTab("Decrypted Assertion XML", decryptedAssertionXMLPanel);
+ jTabbedPane4.addTab("Decrypted Assertion", decryptedAssertionTextPanel);
+
+ encryptedAssertionPanel.add(jTabbedPane4, java.awt.BorderLayout.CENTER);
+
+ jTabbedPane1.addTab("Encrypted Assertion", encryptedAssertionPanel);
+
htmlFormPanel.setLayout(new java.awt.BorderLayout());
jPanel5.setLayout(new javax.swing.BoxLayout(jPanel5, javax.swing.BoxLayout.LINE_AXIS));
@@ -776,8 +875,7 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
jTabbedPane3.addTab("SAML Browser POST Profile Messages", jPanel8);
- jPanel6.setBorder(null);
- jPanel6.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
+ signatureAttacksPanel.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
jPanel10.setLayout(new java.awt.GridBagLayout());
@@ -894,7 +992,7 @@ public void itemStateChanged(java.awt.event.ItemEvent evt) {
jLabel21.setText("Key: ");
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 0;
- gridBagConstraints.gridy = 1;
+ gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
jPanel28.add(jLabel21, gridBagConstraints);
@@ -906,17 +1004,32 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
});
gridBagConstraints = new java.awt.GridBagConstraints();
gridBagConstraints.gridx = 1;
- gridBagConstraints.gridy = 2;
+ gridBagConstraints.gridy = 3;
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
jPanel28.add(selectKeyButton, gridBagConstraints);
- keyTextField.setColumns(20);
keyTextField.setEditable(false);
+ keyTextField.setColumns(20);
gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 2;
gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
jPanel28.add(keyTextField, gridBagConstraints);
+ signAssertionCheckBox.setText("Resign SAML assertion");
+ signAssertionCheckBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ signAssertionCheckBoxItemStateChanged(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
+ jPanel28.add(signAssertionCheckBox, gridBagConstraints);
+
jPanel27.add(jPanel28);
gridBagConstraints = new java.awt.GridBagConstraints();
@@ -925,9 +1038,9 @@ public void actionPerformed(java.awt.event.ActionEvent evt) {
gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
jPanel10.add(jPanel27, gridBagConstraints);
- jPanel6.add(jPanel10);
+ signatureAttacksPanel.add(jPanel10);
- jTabbedPane3.addTab("Signature Attacks", jPanel6);
+ jTabbedPane3.addTab("Signature Attacks", signatureAttacksPanel);
jPanel30.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
@@ -1384,6 +1497,62 @@ public void itemStateChanged(java.awt.event.ItemEvent evt) {
jTabbedPane3.addTab("Replay Attacks", jPanel21);
+ jPanel39.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
+
+ jPanel40.setBorder(javax.swing.BorderFactory.createTitledBorder("SAML Assertion Decryption Attack"));
+ jPanel40.setLayout(new java.awt.GridBagLayout());
+
+ jPanel41.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));
+
+ jPanel42.setLayout(new java.awt.GridBagLayout());
+
+ decryptAssertionCheckBox.setText("Decrypt encrypted assertion");
+ decryptAssertionCheckBox.addItemListener(new java.awt.event.ItemListener() {
+ public void itemStateChanged(java.awt.event.ItemEvent evt) {
+ decryptAssertionCheckBoxItemStateChanged(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridwidth = java.awt.GridBagConstraints.REMAINDER;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
+ jPanel42.add(decryptAssertionCheckBox, gridBagConstraints);
+
+ jLabel24.setText("Key:");
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 0;
+ gridBagConstraints.gridy = 1;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_START;
+ gridBagConstraints.insets = new java.awt.Insets(0, 0, 0, 5);
+ jPanel42.add(jLabel24, gridBagConstraints);
+
+ decryptionKeyTextField.setEditable(false);
+ decryptionKeyTextField.setColumns(20);
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 1;
+ jPanel42.add(decryptionKeyTextField, gridBagConstraints);
+
+ decryptionSelectKeyButton.setText("Select Key...");
+ decryptionSelectKeyButton.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ decryptionSelectKeyButtonActionPerformed(evt);
+ }
+ });
+ gridBagConstraints = new java.awt.GridBagConstraints();
+ gridBagConstraints.gridx = 1;
+ gridBagConstraints.gridy = 2;
+ gridBagConstraints.anchor = java.awt.GridBagConstraints.LINE_END;
+ gridBagConstraints.insets = new java.awt.Insets(5, 0, 0, 0);
+ jPanel42.add(decryptionSelectKeyButton, gridBagConstraints);
+
+ jPanel41.add(jPanel42);
+
+ jPanel40.add(jPanel41, new java.awt.GridBagConstraints());
+
+ jPanel39.add(jPanel40);
+
+ jTabbedPane3.addTab("Encryption Attacks", jPanel39);
+
jPanel1.add(jTabbedPane3, java.awt.BorderLayout.PAGE_START);
jSplitPane1.setLeftComponent(jPanel1);
@@ -1659,6 +1828,38 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
}
}//GEN-LAST:event_lastAttributeRadioButtonItemStateChanged
+ private void signAssertionCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_signAssertionCheckBoxItemStateChanged
+ SamlProxy samlProxy = this.saml.getSamlProxy();
+ boolean signAssertionAttack = evt.getStateChange() == ItemEvent.SELECTED;
+ samlProxy.setSignAssertionAttack(signAssertionAttack);
+ }//GEN-LAST:event_signAssertionCheckBoxItemStateChanged
+
+ private void selectAssertionDecryptionKeyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_selectAssertionDecryptionKeyButtonActionPerformed
+ this.assertionCertificateManager.setVisible(true);
+ }//GEN-LAST:event_selectAssertionDecryptionKeyButtonActionPerformed
+
+ private void decryptAssertionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_decryptAssertionButtonActionPerformed
+ ConversationID id = (ConversationID) this.showConversationAction.getValue("CONVERSATION");
+ try {
+ byte[] decryptedAssertion = this.samlModel.getDecryptedAssertion(id,
+ this.assertionCertificateRepository.getPrivateKey());
+ this.decryptedAssertionXMLPanel.setBytes("text/xml", decryptedAssertion);
+ this.decryptedAssertionTextPanel.setText(null, new String(decryptedAssertion));
+ } catch (Exception ex) {
+ this.decryptedAssertionXMLPanel.setBytes("text/xml", ("" + ex.getMessage() + "").getBytes());
+ }
+ }//GEN-LAST:event_decryptAssertionButtonActionPerformed
+
+ private void decryptionSelectKeyButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_decryptionSelectKeyButtonActionPerformed
+ this.decryptionCertificateManager.setVisible(true);
+ }//GEN-LAST:event_decryptionSelectKeyButtonActionPerformed
+
+ private void decryptAssertionCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_decryptAssertionCheckBoxItemStateChanged
+ SamlProxy samlProxy = this.saml.getSamlProxy();
+ boolean signAssertionAttack = evt.getStateChange() == ItemEvent.SELECTED;
+ samlProxy.setDecryptAssertionAttack(signAssertionAttack);
+ }//GEN-LAST:event_decryptAssertionCheckBoxItemStateChanged
+
// Variables declaration - do not modify//GEN-BEGIN:variables
private javax.swing.JPanel aboutPanel;
private javax.swing.JButton addInjectAttributeButton;
@@ -1666,6 +1867,7 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private javax.swing.JRadioButton allSubjectRadioButton;
private javax.swing.JPanel analysisDataPanel;
private javax.swing.JPanel analysisPanel;
+ private javax.swing.JTextField assertionDecryptionKeyTextField;
private javax.swing.JRadioButton assertionSignatureRadioButton;
private javax.swing.JCheckBox assertionsDigestedCheckBox;
private javax.swing.ButtonGroup attributeButtonGroup;
@@ -1676,11 +1878,19 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private org.owasp.webscarab.ui.swing.editors.TextPanel certDetailTextPanel;
private javax.swing.JTree certPathTree;
private javax.swing.JCheckBox corruptSignatureCheckBox;
+ private javax.swing.JButton decryptAssertionButton;
+ private javax.swing.JCheckBox decryptAssertionCheckBox;
private javax.swing.JButton decryptButton;
+ private org.owasp.webscarab.ui.swing.editors.TextPanel decryptedAssertionTextPanel;
+ private org.owasp.webscarab.ui.swing.editors.XMLPanel decryptedAssertionXMLPanel;
+ private javax.swing.JTextField decryptionKeyTextField;
+ private javax.swing.JButton decryptionSelectKeyButton;
private javax.swing.JCheckBox destinationIndicationCheckBox;
private javax.swing.JRadioButton dsObjectWrapperRadioButton;
private javax.swing.JTextField dtdUriTextField;
private javax.swing.JRadioButton duplicateAssertionRadioButton;
+ private javax.swing.JPanel encryptedAssertionPanel;
+ private org.owasp.webscarab.ui.swing.editors.XMLPanel encryptedAssertionXMLPanel;
private javax.swing.JPanel encryptedAttributesPanel;
private javax.swing.JTable encryptedAttributesTable;
private javax.swing.JRadioButton firstAttributeRadioButton;
@@ -1705,6 +1915,7 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private javax.swing.JLabel jLabel13;
private javax.swing.JLabel jLabel14;
private javax.swing.JLabel jLabel15;
+ private javax.swing.JLabel jLabel16;
private javax.swing.JLabel jLabel17;
private javax.swing.JLabel jLabel18;
private javax.swing.JLabel jLabel19;
@@ -1713,6 +1924,7 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private javax.swing.JLabel jLabel21;
private javax.swing.JLabel jLabel22;
private javax.swing.JLabel jLabel23;
+ private javax.swing.JLabel jLabel24;
private javax.swing.JLabel jLabel3;
private javax.swing.JLabel jLabel4;
private javax.swing.JLabel jLabel5;
@@ -1751,9 +1963,13 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private javax.swing.JPanel jPanel35;
private javax.swing.JPanel jPanel36;
private javax.swing.JPanel jPanel37;
+ private javax.swing.JPanel jPanel38;
+ private javax.swing.JPanel jPanel39;
private javax.swing.JPanel jPanel4;
+ private javax.swing.JPanel jPanel40;
+ private javax.swing.JPanel jPanel41;
+ private javax.swing.JPanel jPanel42;
private javax.swing.JPanel jPanel5;
- private javax.swing.JPanel jPanel6;
private javax.swing.JPanel jPanel7;
private javax.swing.JPanel jPanel8;
private javax.swing.JPanel jPanel9;
@@ -1767,6 +1983,7 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private javax.swing.JTabbedPane jTabbedPane1;
private javax.swing.JTabbedPane jTabbedPane2;
private javax.swing.JTabbedPane jTabbedPane3;
+ private javax.swing.JTabbedPane jTabbedPane4;
private javax.swing.JTextField keyTextField;
private javax.swing.JRadioButton lastAttributeRadioButton;
private javax.swing.JRadioButton lastSubjectRadioButton;
@@ -1786,9 +2003,12 @@ private void lastAttributeRadioButtonItemStateChanged(java.awt.event.ItemEvent e
private javax.swing.JTable samlTable;
private javax.swing.JLabel samlVersionLabel;
private javax.swing.JRadioButton samlpExtWrapperRadioButton;
+ private javax.swing.JButton selectAssertionDecryptionKeyButton;
private javax.swing.JButton selectKeyButton;
+ private javax.swing.JCheckBox signAssertionCheckBox;
private javax.swing.JCheckBox signCheckBox;
private javax.swing.JCheckBox signWrapAttackCheckBox;
+ private javax.swing.JPanel signatureAttacksPanel;
private javax.swing.ButtonGroup signatureButtonGroup;
private javax.swing.JPanel signaturePanel;
private javax.swing.JLabel signatureValidityLabel;
diff --git a/src/org/owasp/webscarab/ui/swing/CertificateManager.form b/src/org/owasp/webscarab/ui/swing/CertificateManager.form
index fbaab27a..3889bf5a 100644
--- a/src/org/owasp/webscarab/ui/swing/CertificateManager.form
+++ b/src/org/owasp/webscarab/ui/swing/CertificateManager.form
@@ -1,4 +1,4 @@
-
+