/***********************************************************************
*
* $CVSHeader$
*
* 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 <info@frankcornelis.be>
*
* 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.
*
* 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
* ==============
*
* 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.security.KeyStore;
import java.security.KeyStore.PrivateKeyEntry;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.event.EventListenerList;
import org.owasp.webscarab.httpclient.HTTPClient;
import org.owasp.webscarab.model.ConversationID;
import org.owasp.webscarab.model.NamedValue;
import org.owasp.webscarab.plugin.proxy.ProxyPlugin;
/**
* 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 {
private Logger _logger = Logger.getLogger(getClass().getName());
private boolean corruptSignature;
private boolean removeSignature;
private boolean replay;
private ConversationID replayId;
private boolean injectRemoteReference;
private String remoteReference;
private boolean injectAttribute;
private List<NamedValue> injectionAttributes;
private Occurences attributeOccurences;
private boolean injectSubject;
private Occurences subjectOccurences;
private String subject;
private boolean injectPublicDoctype;
private String dtdUri;
private boolean attack;
private boolean injectRelayState;
private String relayState;
private boolean signSamlMessage;
private KeyStore.PrivateKeyEntry privateKeyEntry;
private boolean signWrapAttack;
private Wrapper wrapper;
private SignatureType wrapperTargetSignature;
private boolean renameTopId;
private boolean renameAssertionId;
private boolean renameLastAssertionId;
private boolean removeAssertionSignature;
private EventListenerList _listenerList = new EventListenerList();
private SamlModel samlModel;
@Override
public String getPluginName() {
return "SAML Proxy";
}
@Override
public HTTPClient getProxyPlugin(HTTPClient in) {
return new SamlHTTPClient(in, this);
}
public void setCorruptSignature(boolean corruptSignature) {
this.corruptSignature = corruptSignature;
updateAttackState();
}
@Override
public boolean doCorruptSignature() {
return this.corruptSignature;
}
public void setRemoveSignature(boolean removeSignature) {
this.removeSignature = removeSignature;
updateAttackState();
}
@Override
public boolean doRemoveSignature() {
return this.removeSignature;
}
public void setReplaySamlResponse(ConversationID id) {
this.replayId = id;
fireReplayChanged(id);
}
public void setReplay(boolean replay) {
this.replay = replay;
updateAttackState();
}
@Override
public boolean doReplay() {
return this.replay;
}
public void addSamlProxyListener(SamlProxyListener listener) {
_listenerList.add(SamlProxyListener.class, listener);
}
public void removeSamlProxyListener(SamlProxyListener listener) {
_listenerList.remove(SamlProxyListener.class, listener);
}
private void fireReplayChanged(ConversationID replayId) {
// Guaranteed to return a non-null array
Object[] listeners = _listenerList.getListenerList();
// Process the listeners last to first, notifying
// those that are interested in this even)
for (int i = listeners.length - 2; i >= 0; i -= 2) {
if (listeners[i] == SamlProxyListener.class) {
try {
((SamlProxyListener) listeners[i + 1]).replayChanged(replayId);
} catch (Exception e) {
_logger.log(Level.SEVERE, "Unhandled exception: {0}", e);
}
}
}
}
@Override
public String getReplaySamlResponse() {
return this.samlModel.getSAMLMessage(this.replayId);
}
public void init(SamlModel samlModel) {
this.samlModel = samlModel;
}
public void setInjectRemoteReference(boolean injectRemoteReference) {
this.injectRemoteReference = injectRemoteReference;
updateAttackState();
}
@Override
public boolean doInjectRemoteReference() {
return this.injectRemoteReference;
}
public void setRemoteReference(String remoteReference) {
this.remoteReference = remoteReference;
}
@Override
public String getRemoteReference() {
return this.remoteReference;
}
public void setInjectAttribute(boolean injectAttribute) {
this.injectAttribute = injectAttribute;
updateAttackState();
}
@Override
public boolean doInjectAttribute() {
return this.injectAttribute;
}
public void setInjectSubject(boolean injectSubject) {
this.injectSubject = injectSubject;
updateAttackState();
}
public void setInjectionSubject(String injectionSubject) {
this.subject = injectionSubject;
}
@Override
public boolean doInjectSubject() {
return this.injectSubject;
}
@Override
public String getInjectionSubject() {
return this.subject;
}
@Override
public boolean doSomething() {
return this.attack;
}
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;
}
public void setInjectPublicDoctype(boolean injectPublicDoctype) {
this.injectPublicDoctype = injectPublicDoctype;
updateAttackState();
}
public void setDtdUri(String dtdUri) {
this.dtdUri = dtdUri;
}
@Override
public boolean doInjectPublicDoctype() {
return this.injectPublicDoctype;
}
@Override
public String getDtdUri() {
return this.dtdUri;
}
public void setInjectRelayState(boolean injectRelayState) {
this.injectRelayState = injectRelayState;
updateAttackState();
}
public void setRelayState(String relayState) {
this.relayState = relayState;
}
@Override
public boolean doInjectRelayState() {
return this.injectRelayState;
}
@Override
public String getRelayState() {
return this.relayState;
}
public void setSignSamlMessage(boolean signSamlMessage) {
this.signSamlMessage = signSamlMessage;
updateAttackState();
}
@Override
public boolean doSignSamlMessage() {
return this.signSamlMessage;
}
@Override
public PrivateKeyEntry getPrivateKeyEntry() {
return this.privateKeyEntry;
}
public void setPrivateKeyEntry(PrivateKeyEntry privateKeyEntry) {
this.privateKeyEntry = privateKeyEntry;
}
public void setSignWrapAttack(boolean signWrapAttack) {
this.signWrapAttack = signWrapAttack;
updateAttackState();
}
@Override
public boolean doSignWrapAttack() {
return this.signWrapAttack;
}
public void setSubjectOccurences(Occurences occurences) {
this.subjectOccurences = occurences;
}
@Override
public Occurences getSubjectOccurences() {
if (null == this.subjectOccurences) {
return Occurences.ALL;
}
return this.subjectOccurences;
}
public void setRenameTopId(boolean renameTopId) {
this.renameTopId = renameTopId;
}
@Override
public boolean doRenameTopId() {
return this.renameTopId;
}
public void setRemoveAssertionSignature(boolean removeAssertionSignature) {
this.removeAssertionSignature = removeAssertionSignature;
updateAttackState();
}
@Override
public boolean doRemoveAssertionSignature() {
return this.removeAssertionSignature;
}
public void setWrapper(Wrapper wrapper) {
this.wrapper = wrapper;
}
@Override
public Wrapper getWrapper() {
if (null == this.wrapper) {
return Wrapper.DS_OBJECT;
}
return this.wrapper;
}
public void setWrapperTargetSignature(SignatureType signatureType) {
this.wrapperTargetSignature = signatureType;
}
@Override
public SignatureType getWrapperTargetSignature() {
if (null == this.wrapperTargetSignature) {
return SignatureType.PROTOCOL;
}
return this.wrapperTargetSignature;
}
public void setRenameAssertionId(boolean renameAssertionId) {
this.renameAssertionId = renameAssertionId;
}
@Override
public boolean doRenameAssertionId() {
return this.renameAssertionId;
}
public void setInjectionAttributes(List<NamedValue> attributes) {
this.injectionAttributes = attributes;
}
@Override
public List<NamedValue> getInjectionAttributes() {
return this.injectionAttributes;
}
public void setRenameLastAssertionId(boolean renameLastAssertionId) {
this.renameLastAssertionId = renameLastAssertionId;
}
@Override
public boolean doRenameLastAssertionId() {
return this.renameLastAssertionId;
}
public void setAttributeOccurences(Occurences occurences) {
this.attributeOccurences = occurences;
}
@Override
public Occurences getAttributeOccurences() {
return this.attributeOccurences;
}
}