/** * WS-Attacker - A Modular Web Services Penetration Testing Framework Copyright * (C) 2013 Christian Altmeier * * 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.intelligentdos; import java.net.URL; import java.util.List; import javax.swing.ImageIcon; import org.apache.commons.lang3.StringUtils; import org.apache.log4j.Logger; import wsattacker.library.intelligentdos.IntelligentDoSLibrary; import wsattacker.library.intelligentdos.IntelligentDoSLibraryImpl; import wsattacker.library.intelligentdos.common.SuccessfulAttack; import wsattacker.library.intelligentdos.dos.DoSAttack; import wsattacker.library.intelligentdos.helper.CommonParamItem; import wsattacker.library.intelligentdos.position.MatcherPositionIterator; import wsattacker.library.intelligentdos.position.PositionIterator; import wsattacker.library.intelligentdos.success.SimpleSuccessDecider; import wsattacker.library.schemaanalyzer.SchemaAnalyzer; import wsattacker.library.schemaanalyzer.SchemaAnalyzerFactory; import wsattacker.main.composition.plugin.AbstractPlugin; import wsattacker.main.composition.plugin.PluginFunctionInterface; import wsattacker.main.composition.plugin.PluginObserver; import wsattacker.main.composition.testsuite.RequestResponsePair; import wsattacker.main.plugin.PluginState; import wsattacker.main.plugin.option.OptionSimpleBoolean; import static wsattacker.plugin.dos.dosExtension.abstractPlugin.AbstractDosPlugin.MESSAGE; import wsattacker.plugin.intelligentdos.listener.PersistAttackListener; import wsattacker.plugin.intelligentdos.option.ConfigureAttacksOption; import wsattacker.plugin.intelligentdos.option.SchemaAnalyzerOption; import wsattacker.plugin.intelligentdos.postanalyze.IntelligentDoSPostAnalyzeFunction; import wsattacker.plugin.intelligentdos.requestSender.Http4RequestSenderImpl; import wsattacker.plugin.intelligentdos.ui.DoSStatusFrame; import wsattacker.plugin.intelligentdos.worker.IntelligentDoSWorker; public class IntelligentDoS extends AbstractPlugin implements PluginObserver { /** * */ private static final long serialVersionUID = 1L; private static final Logger logger = Logger.getLogger( IntelligentDoS.class ); private static final String NAME = "Adaptive Intelligent Denial-of-Service"; private static final URL logoPath = IntelligentDoS.class.getResource( "/images/logo_red.png" ); private static final String DESCRIPTION = "<html><p>The Adaptive Intelligent Denial-of-Service (AdIDoS) attack is a composite of various " + "DoS attacks. With these attack a given Web service can be fully-automatically testes for DoS weaknesses. " + "The following DoS attacks can be chosen and configured individually:</p><ul>" + "<li>CoerciveParsing</li>" + "<li>XML Element Count</li>" + "<li>XML Attribute Count</li>" + "<li>XML Entity Expansion</li>" + "<li>XML External Entity</li>" + "<li>Hash Collision</li>" + "<li>XML Overlong Names</li>" + "</ul><p>The common parameters adjust the agressivnes by which the Web service is tested." + "The selected attacks are performed fully-automatically, whereby the attack vectors are adaptively adjusted. " + "The Intelligent Denial-of-Service attack replaces the string $$PAYLOADELEMENT$$ and $$PAYLOADATTR$$ in the SOAP message below " + "successively with the attack payload. " + "The placeholders $$PAYLOADELEMENT$$ and $$PAYLOADATTR$$ can be set to any other position in the SOAP message.</p>" + "</html>"; private static final String AUTHOR = "Christian Altmeier"; private static final String VERSION = "1.0 / 2015-07-10"; private static final String[] CATEGORY = new String[] { "Denial of Service" }; // TODO [CHAL 2014-08-12] configurable? private static final SchemaAnalyzer schemaAnalyzer = SchemaAnalyzerFactory.getInstance( SchemaAnalyzerFactory.WEBSERVICE ); private ConfigureAttacksOption configureLibraryOption; private OptionSimpleBoolean optionSimpleBoolean; private SchemaAnalyzerOption payloadPlaceholders; private transient IntelligentDoSLibrary intelligentDoSLibrary; private transient IntelligentDoSWorker doSWorker; private DoSStatusFrame doSStatusFrame; @Override public void initializePlugin() { setName( NAME ); setDescription( DESCRIPTION ); setAuthor( AUTHOR ); setVersion( VERSION ); setCategory( CATEGORY ); final ImageIcon icon = new ImageIcon( logoPath ); setIcon( icon ); setState( PluginState.Ready ); configureLibraryOption = new ConfigureAttacksOption( IntelligentDoSLibraryImpl.getAllAttacks(), IntelligentDoSLibraryImpl.COMMONPARAMS, IntelligentDoSLibraryImpl.DEFAULT_SERVER_RECOVERY, Http4RequestSenderImpl.TIMEOUT ); getPluginOptions().add( configureLibraryOption ); optionSimpleBoolean = new OptionSimpleBoolean( "Use namespaces?", false, "checked = attributes with namespace, unchecked = attributes without namespace" ); getPluginOptions().add( optionSimpleBoolean ); // set payload position -> Always last option payloadPlaceholders = new SchemaAnalyzerOption( MESSAGE, "set position of payload placeholder", schemaAnalyzer ); getPluginOptions().add( payloadPlaceholders ); } @Override public void clean() { // TODO is this sufficient setState( PluginState.Ready ); } @Override public boolean wasSuccessful() { // successfull only server is vulnerable for one method // note: one point = possible server misconfiguration return getCurrentPoints() > 1; } @Override public void attackImplementationHook( RequestResponsePair original ) { DoSAttack[] dosAttackArray = configureLibraryOption.getAttacks(); final List<CommonParamItem> commonParamList = configureLibraryOption.getCommonParamList(); int serverRecoveryTime = configureLibraryOption.getServerRecoveryTime(); int httpConnectionTimeout = configureLibraryOption.getHttpConnectionTimeout(); if ( optionSimpleBoolean.isOn() ) { for ( DoSAttack doSAttack : dosAttackArray ) { doSAttack.setUseNamespace( optionSimpleBoolean.isOn() ); } } logger.trace( "httpConnectionTimeout: " + httpConnectionTimeout ); Http4RequestSenderImpl.setHttpConnectionTimeout( httpConnectionTimeout ); String xmlMessage = original.getWsdlRequest().getRequestContent(); PositionIterator positionIterator = new MatcherPositionIterator( payloadPlaceholders.getValue() ); intelligentDoSLibrary = IntelligentDoSLibraryImpl.create().withXmlMessage( xmlMessage ).withPositionIterator( positionIterator ).withAttacks( dosAttackArray ).withSuccessDecider( new SimpleSuccessDecider() ).withCommonParams( commonParamList ).withServerRecoveryTime( serverRecoveryTime ).build(); intelligentDoSLibrary.initialize(); doSWorker = new IntelligentDoSWorker( intelligentDoSLibrary ); String property = System.getProperty( "persist.attack.dir" ); if ( StringUtils.isNotEmpty( property ) ) { doSWorker.addListener( new PersistAttackListener( property ) ); } final IntelligentDoSPostAnalyzeFunction function = new IntelligentDoSPostAnalyzeFunction( doSWorker ); // function to analyze the result setPluginFunctions( new PluginFunctionInterface[] { function } ); addPluginObserver( this ); doSStatusFrame = new DoSStatusFrame(); doSStatusFrame.setVisible( true ); doSWorker.addListener( doSStatusFrame ); // This takes a while doSWorker.startAttack( original ); doSStatusFrame.dispose(); List<SuccessfulAttack> successfulAttacks = intelligentDoSLibrary.getSuccessfulAttacks(); int currentPoints = (int) ( ( 100.0 / dosAttackArray.length ) * successfulAttacks.size() * 1.0 ); if ( currentPoints >= getMaxPoints() ) { setCurrentPoints( getMaxPoints() ); } else { setCurrentPoints( currentPoints ); } } @Override public void restoreConfiguration( AbstractPlugin plugin ) { // TODO [CHAL 2014-05-28] check if this is ok // nothing to do } @Override public void currentPointsChanged( AbstractPlugin plugin, int newPoints ) { // not interested } @Override public void pluginStateChanged( AbstractPlugin plugin, PluginState newState, PluginState oldState ) { if ( plugin == this ) { doSWorker.stopAttack(); doSStatusFrame.dispose(); // setState( PluginState.Stopped ); } } }