/** * WS-Attacker - A Modular Web Services Penetration Testing Framework Copyright * (C) 2010 Christian Mainka * * 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.gui; import com.eviware.soapui.impl.wsdl.WsdlInterface; import com.eviware.soapui.impl.wsdl.WsdlOperation; import com.eviware.soapui.impl.wsdl.WsdlProject; import com.eviware.soapui.impl.wsdl.WsdlRequest; import com.eviware.soapui.model.iface.Request.SubmitException; import com.eviware.soapui.support.SoapUIException; import java.io.File; import java.io.IOException; import java.util.Iterator; import org.apache.log4j.Logger; import wsattacker.gui.component.target.WsdlLoaderGUI_NB; import wsattacker.main.Preferences; import wsattacker.main.composition.ControllerInterface; import wsattacker.main.composition.plugin.AbstractPlugin; import wsattacker.main.composition.plugin.option.AbstractOption; import wsattacker.main.plugin.PluginManager; import wsattacker.main.plugin.result.Result; import wsattacker.main.testsuite.CurrentRequest; import wsattacker.main.testsuite.TestSuite; public class GuiController implements ControllerInterface { private static final GuiController c = new GuiController(); // singleton PluginManager pluginManager; TestSuite testSuite; Preferences prefs; Logger LOG = Logger.getLogger( GuiController.class ); GuiView guiView; private boolean abortAttacks; Thread runThread; PluginRunner runner; // singleton private GuiController() { abortAttacks = false; // get allPlugins this.pluginManager = PluginManager.getInstance(); reloadPlugins(); // preferences this.prefs = Preferences.getInstance(); // create a new test suite this.testSuite = TestSuite.getInstance(); // no thread this.runThread = new Thread(); // create gui this.guiView = new GuiView( this ); Thread viewThread = new Thread( this.guiView ); viewThread.start(); } // singleton public static GuiController getInstance() { return c; } // ============================================== // Interface Methods: // Plugins // ============================================== @Override public PluginManager getPluginManager() { // return this.allPlugins.getPlugins(); return this.pluginManager; } @Override public void reloadPlugins() { LOG.info( "Adding Libraries from \"lib\" folder" ); getPluginManager().loadAvailablePlugins( new File( "lib" ) ); LOG.info( "Reloading Plugins" ); getPluginManager().loadAvailablePlugins( new File( "plugins" ) ); } @Override public void setPluginActive( int index, boolean active ) { AbstractPlugin plugin = getPluginManager().getByIndex( index ); setPluginActive( plugin, active ); } @Override public void setPluginActive( String pluginName, boolean active ) { AbstractPlugin plugin = getPluginManager().getByName( pluginName ); setPluginActive( plugin, active ); } private void setPluginActive( AbstractPlugin plugin, boolean active ) { if ( plugin != null ) { if ( getPluginManager().isActive( plugin ) != active ) { LOG.info( String.format( ( active ? "(+) A" : "(-) Dea" ) + "ctivating Plugin %s", plugin.getName() ) ); getPluginManager().setActive( plugin, active ); } } else { LOG.warn( String.format( "(!) Could not activate Plugin" ) ); } } @Override public void setAllPluginActive( boolean active ) { LOG.info( ( active ? "(+) A" : "(-) Dea" ) + "ctivating all Plugins" ); getPluginManager().setAllActive( active ); } @Override public void setOptionValue( AbstractPlugin plugin, String optionName, String optionValue ) { AbstractOption option = plugin.getPluginOptions().getByName( optionName ); if ( option == null ) { throw new NullPointerException( "Option is null" ); } if ( option.isValid( optionValue ) ) { LOG.debug( String.format( "Set PluginOption for '%s': {%s=%s}", plugin.getName(), optionName, optionValue ) ); option.parseValue( optionValue ); } LOG.debug( String.format( "Value {%s=%s} for Plugin '%s' is INVALID!", optionName, optionValue, plugin.getName() ) ); } @Override public void startActivePlugins() { if ( runThread.isAlive() ) { LOG.fatal( "You can't start Attacks. Another process is running." ); return; } runner = new PluginRunner( testSuite ); runThread = new Thread( runner ); runThread.setName( "Run Plugins" ); guiView.getAttackOverview().enableStartButton( false ); guiView.getAttackOverview().enableStopButton( true ); guiView.getAttackOverview().enableCleanButton( false ); guiView.getAttackOverview().enableSaveButton( false ); // SoapUI.getThreadPool().execute(runThread); runThread.start(); } public void stopActivePlugins() { Thread stopThread = new Thread( new PluginStopper() ); stopThread.run(); runThread.setName( "Run Plugins" ); } class PluginStopper implements Runnable { @SuppressWarnings( "deprecation" ) @Override public void run() { if ( runThread.isAlive() && runThread.getName().equals( "Run Plugins" ) ) { abortAttacks = true; LOG.info( "Stopping all active plugins" ); AbstractPlugin active = runner.getActive(); LOG.warn( "Gently aborting plugin '" + active.getName() + "' (Waiting for 3 sec)" ); active.abortAttack(); try { Thread.sleep( 3000 ); } catch ( InterruptedException e ) { } // wait for 3 seconds // know force to kill the thread if its still running. if ( runThread.isAlive() && runThread.getName().equals( "Run Plugins" ) ) { LOG.warn( "Force to kill thread, since plugin is still running." ); runThread.stop(); } active.stopAttack(); Iterator<AbstractPlugin> it = getPluginManager().getActivePluginIterator(); while ( it.hasNext() ) { AbstractPlugin otherPlugin = it.next(); if ( otherPlugin.isReady() ) { otherPlugin.stopAttack(); } } setEnabledTabs( true, 0, 1, 2 ); abortAttacks = false; } guiView.getAttackOverview().enableStartButton( false ); guiView.getAttackOverview().enableStopButton( false ); guiView.getAttackOverview().enableCleanButton( true ); guiView.getAttackOverview().enableSaveButton( true ); } } @Override public void cleanPlugins() { boolean noError = true; Iterator<AbstractPlugin> it = getPluginManager().iterator(); AbstractPlugin plugin; while ( it.hasNext() ) { plugin = it.next(); plugin.clean(); if ( plugin.isFinished() || plugin.isRunning() ) { LOG.error( "Plugin " + plugin.getName() + " could not be cleaned, Status is still " + plugin.getState() ); noError |= false; } if ( plugin.getCurrentPoints() != 0 ) { LOG.error( "Plugin " + plugin.getName() + "could not be cleaned, it has still " + plugin.getCurrentPoints() + " Points" ); noError |= false; } } Result.getGlobalResult().clear(); if ( noError ) { LOG.info( "All Plugins successfully cleaned" ); } guiView.getAttackOverview().enableStartButton( true ); guiView.getAttackOverview().enableStopButton( false ); guiView.getAttackOverview().enableCleanButton( false ); guiView.getAttackOverview().enableSaveButton( false ); } class PluginRunner implements Runnable { TestSuite testSuite; AbstractPlugin active; public PluginRunner( TestSuite testSuite ) { this.testSuite = testSuite; this.active = null; } public void run() { AbstractPlugin plugin; Iterator<AbstractPlugin> it; // Check if everything is allright if ( testSuite.getCurrentRequest().getWsdlRequest() == null ) { LOG.warn( "You have to load a WSDL first" ); return; } if ( testSuite.getCurrentRequest().getWsdlResponse() == null ) { LOG.warn( "You must submit a test request first." ); return; } if ( getPluginManager().countActivePlugins() < 1 ) { LOG.warn( "You must enable at least one Plugin" ); return; } it = getPluginManager().getActivePluginIterator(); while ( it.hasNext() ) { plugin = it.next(); if ( !plugin.isReady() ) { LOG.warn( "Not all Plugins are Ready" ); return; } } // start attack LOG.info( "Starting all active Plugins..." ); setEnabledTabs( false, 0, 1, 2 ); it = getPluginManager().getActivePluginIterator(); while ( it.hasNext() && !abortAttacks ) { plugin = it.next(); active = plugin; LOG.info( "Starting plugin '" + plugin.getName() + "'" ); plugin.startAttack(); LOG.info( "Plugin finished: " + plugin.getCurrentPoints() + "/" + plugin.getMaxPoints() ); } active = null; setEnabledTabs( true, 0, 1, 2 ); guiView.getAttackOverview().enableStartButton( false ); guiView.getAttackOverview().enableStopButton( false ); guiView.getAttackOverview().enableCleanButton( true ); guiView.getAttackOverview().enableSaveButton( true ); } public AbstractPlugin getActive() { return active; } } @Override public void savePluginConfiguration( File file ) { try { getPluginManager().savePlugins( file ); } catch ( IOException e ) { LOG.error( "IO Exception : " + e.getMessage() ); } catch ( Exception e ) { LOG.error( "Unknown Error:" + e.getMessage() ); } } @Override public void loadPluginConfiguration( File file ) { try { getPluginManager().loadPlugins( file ); } catch ( IOException e ) { LOG.error( "IO Exception : " + e.getMessage() ); } catch ( ClassNotFoundException e ) { LOG.error( "Could not find all Plugin Classes" ); } catch ( Exception e ) { LOG.error( "Unknown Error:" + e.getMessage() ); } LOG.info( "Successfully loaded Configuration" ); } // ============================================== // Interface Methods: // WsdlProject // ============================================== @Override public TestSuite getTestSuite() { return this.testSuite; } @Override public void setWsdl( String uri ) { if ( runThread.isAlive() ) { LOG.fatal( "You can't start Attacks. Another process is running." ); return; } LOG.info( "Trying to load WSDL from '" + uri + "'" ); Runnable runner = new WsdlLoadRunner( uri ); runThread = new Thread( runner ); runThread.setName( "Load WSDL" ); runThread.start(); // SoapUI.getThreadPool().execute(runThread); } class WsdlLoadRunner implements Runnable { String uri; public WsdlLoadRunner( String uri ) { this.uri = uri; } @Override public void run() { WsdlLoaderGUI_NB wsdlGui = guiView.getWsdlLoader(); // disable fields wsdlGui.getUriField().setEnabled( false ); wsdlGui.getLoadButton().setEnabled( false ); wsdlGui.getServiceComboBox().setEnabled( false ); wsdlGui.getOperationComboBox().setEnabled( false ); wsdlGui.getNewRequestButtom().setEnabled( false ); wsdlGui.updateUI(); try { testSuite.loadWsdl( uri ); // re-enable fields wsdlGui.getServiceComboBox().setEnabled( true ); wsdlGui.getOperationComboBox().setEnabled( true ); wsdlGui.getNewRequestButtom().setEnabled( true ); } catch ( SoapUIException e ) { LOG.error( "SoapUIException while loading WSDL: " + e.getMessage() ); } catch ( UnsupportedOperationException e ) { LOG.error( "UnsupportedOperationException while loading WSDL: " + e.getMessage() ); } catch ( Exception e ) { LOG.error( "Wsdl File could not be loaded: " + e.getMessage() ); } finally { // re-enable fields wsdlGui.getUriField().setEnabled( true ); wsdlGui.getLoadButton().setEnabled( true ); } } } @Override public boolean setCurrentService( String serviceName ) { WsdlProject project = testSuite.getProject(); if ( ( project != null ) && ( project.getInterfaceByName( serviceName ) != null ) ) { WsdlInterface service = (WsdlInterface) project.getInterfaceByName( serviceName ); setCurrentService( service ); return true; } else { LOG.warn( "No such service available" ); return false; } } @Override public boolean setCurrentService( int index ) { WsdlProject project = testSuite.getProject(); if ( ( project != null ) && ( index >= 0 ) && ( index < project.getInterfaceCount() ) ) { WsdlInterface service = (WsdlInterface) project.getInterfaceAt( index ); setCurrentService( service ); return true; } else { LOG.warn( "No such service available" ); return false; } } private void setCurrentService( WsdlInterface service ) { this.testSuite.getCurrentInterface().setWsdlInterface( service ); LOG.info( "Set current service to '" + service.getName() + "'" ); } @Override public boolean setCurrentOperation( String operationString ) { WsdlOperation operation = testSuite.getCurrentInterface().getWsdlInterface().getOperationByName( operationString ); return setCurrentOperation( operation ); } @Override public boolean setCurrentOperation( int index ) { WsdlOperation operation = testSuite.getCurrentInterface().getWsdlInterface().getOperationAt( index ); return setCurrentOperation( operation ); } private boolean setCurrentOperation( WsdlOperation operation ) { if ( operation == null ) { LOG.warn( "Unset current operatoin (null)" ); return false; } this.testSuite.getCurrentOperation().setWsdlOperation( operation ); LOG.info( "Set current operation to '" + operation.getName() + "'" ); return true; } @Override public void resetRequestContent() { WsdlRequest request = testSuite.getCurrentRequest().getWsdlRequest(); if ( request != null ) { LOG.info( "Resetting content for basic Request" ); request.setRequestContent( request.getOperation().createRequest( prefs.isCreateOptionalElements() ) ); } } @Override public void setRequestContent( String content ) { LOG.trace( "Setting request content to:\n" + content ); WsdlRequest request = testSuite.getCurrentRequest().getWsdlRequest(); if ( request != null ) { request.setRequestContent( content ); } else { LOG.warn( "There is no current Request" ); } } @Override public void doTestRequest() { if ( runThread.isAlive() ) { LOG.fatal( "You can't do a Test Request. Another process is running." ); } WsdlRequest request = testSuite.getCurrentRequest().getWsdlRequest(); if ( request == null ) { LOG.warn( "You have to load a WSDL first" ); return; } LOG.info( "Doing a Test Request" ); Runnable runner = new TestRequest( testSuite.getCurrentRequest() ); runThread = new Thread( runner ); runThread.setName( "Test Request" ); runThread.start(); // SoapUI.getThreadPool().execute(runThread); } class TestRequest implements Runnable { final CurrentRequest request; public TestRequest( CurrentRequest request ) { this.request = request; } @Override public void run() { LOG.info( "Submitting Request..." ); try { request.submitRequest(); } catch ( NullPointerException e ) { String error = "Error while doing Test Request" + e.getMessage(); LOG.error( error ); return; } catch ( SubmitException e ) { String error = "Error while doing Test Request. " + e.getMessage(); LOG.error( error ); return; } catch ( Exception e ) { LOG.error( "Unknown Error:" + e.getMessage() ); return; } String responseContent = request.getWsdlResponse().getContentAsString(); if ( responseContent == null ) { LOG.warn( "Got an empty response. Bad request?" ); } else { LOG.info( "Successfully received Response" ); } } } // ============================================== // Help Methods: // ============================================== private void setEnabledTabs( boolean enabled, int... tabindex ) { for ( int i : tabindex ) { guiView.getMainWindows().getTabs().setEnabledAt( i, enabled ); } } // Additional Getter public GuiView getGuiView() { return guiView; } }