Package com.eviware.soapui.security.assertion

Source Code of com.eviware.soapui.security.assertion.CrossSiteScriptAssertion$CrossSiteScripSeparateHTMLConfigDialog

/*
*  soapUI, copyright (C) 2004-2011 eviware.com
*
*  soapUI is free software; you can redistribute it and/or modify it under the
*  terms of version 2.1 of the GNU Lesser General Public License as published by
*  the Free Software Foundation.
*
*  soapUI 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 Lesser General Public License for more details at gnu.org.
*/
package com.eviware.soapui.security.assertion;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JScrollPane;

import org.apache.xmlbeans.XmlObject;

import com.eviware.soapui.SoapUI;
import com.eviware.soapui.config.CrossSiteScriptingScanConfig;
import com.eviware.soapui.config.HttpRequestConfig;
import com.eviware.soapui.config.TestAssertionConfig;
import com.eviware.soapui.config.TestStepConfig;
import com.eviware.soapui.impl.support.HttpUtils;
import com.eviware.soapui.impl.wsdl.panels.teststeps.support.AbstractGroovyEditorModel;
import com.eviware.soapui.impl.wsdl.support.HelpUrls;
import com.eviware.soapui.impl.wsdl.testcase.WsdlTestCase;
import com.eviware.soapui.impl.wsdl.teststeps.HttpTestRequestStep;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlMessageAssertion;
import com.eviware.soapui.impl.wsdl.teststeps.WsdlTestStep;
import com.eviware.soapui.impl.wsdl.teststeps.assertions.AbstractTestAssertionFactory;
import com.eviware.soapui.impl.wsdl.teststeps.registry.HttpRequestStepFactory;
import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepFactory;
import com.eviware.soapui.impl.wsdl.teststeps.registry.WsdlTestStepRegistry;
import com.eviware.soapui.model.ModelItem;
import com.eviware.soapui.model.iface.MessageExchange;
import com.eviware.soapui.model.iface.SubmitContext;
import com.eviware.soapui.model.testsuite.Assertable;
import com.eviware.soapui.model.testsuite.AssertionError;
import com.eviware.soapui.model.testsuite.AssertionException;
import com.eviware.soapui.model.testsuite.ResponseAssertion;
import com.eviware.soapui.model.testsuite.TestCaseRunner;
import com.eviware.soapui.model.testsuite.TestStep;
import com.eviware.soapui.security.SecurityTestRunContext;
import com.eviware.soapui.security.SecurityTestRunner;
import com.eviware.soapui.security.SecurityTestRunnerImpl;
import com.eviware.soapui.security.scan.CrossSiteScriptingScan;
import com.eviware.soapui.support.SecurityScanUtil;
import com.eviware.soapui.support.UISupport;
import com.eviware.soapui.support.components.GroovyEditorComponent;
import com.eviware.soapui.support.scripting.SoapUIScriptEngine;
import com.eviware.soapui.support.scripting.SoapUIScriptEngineRegistry;
import com.eviware.soapui.support.xml.XmlObjectConfigurationBuilder;
import com.eviware.soapui.support.xml.XmlObjectConfigurationReader;
import com.eviware.x.form.XFormDialog;
import com.eviware.x.form.XFormField;
import com.eviware.x.form.XFormFieldListener;
import com.eviware.x.form.support.ADialogBuilder;
import com.eviware.x.form.support.AField;
import com.eviware.x.form.support.AField.AFieldType;
import com.eviware.x.form.support.AForm;

public class CrossSiteScriptAssertion extends WsdlMessageAssertion implements ResponseAssertion
{
  public static final String ID = "CrosSiteScript";
  public static final String LABEL = "Cross Site Scripting Detection";
  public static final String GROOVY_SCRIPT = "groovyScript";
  public static final String CHECK_RESPONSE = "checkResponse";
  public static final String CHECK_SEPARATE_HTML = "checkSeparateHTML";

  private XFormDialog dialog;
  private String script;
  private GroovyEditorModel groovyEditorModel;
  private SoapUIScriptEngine scriptEngine;

  MessageExchange messageExchange;
  SubmitContext context;

  private boolean checkResponse;
  private boolean checkSeparateHTML;

  public CrossSiteScriptAssertion( TestAssertionConfig assertionConfig, Assertable assertable )
  {
    super( assertionConfig, assertable, false, true, false, true );
    groovyEditorModel = new GroovyEditorModel( this );
    init();
    scriptEngine = SoapUIScriptEngineRegistry.create( this );
  }

  private void init()
  {
    XmlObjectConfigurationReader reader = new XmlObjectConfigurationReader( getConfiguration() );
    script = reader.readString( GROOVY_SCRIPT, "" );
    checkResponse = reader.readBoolean( CHECK_RESPONSE, true );
    checkSeparateHTML = reader.readBoolean( CHECK_SEPARATE_HTML, false );
    groovyEditorModel.setScript( script );
  }

  @Override
  protected String internalAssertResponse( MessageExchange messageExchange, SubmitContext context )
      throws AssertionException
  {
    TestStep testStep = ( TestStep )context.getProperty( CrossSiteScriptingScan.TEST_STEP );
    testStep = SecurityTestRunnerImpl.cloneTestStepForSecurityScan( ( WsdlTestStep )testStep );
    SecurityTestRunner securityTestRunner = ( SecurityTestRunner )context
        .getProperty( CrossSiteScriptingScan.TEST_CASE_RUNNER );

    List<String> urls = submitScript( messageExchange, context );

    CrossSiteScriptingScanConfig parameterExposureCheckConfig = ( CrossSiteScriptingScanConfig )context
        .getProperty( CrossSiteScriptingScan.PARAMETER_EXPOSURE_SCAN_CONFIG );

    List<AssertionError> assertionErrorList = new ArrayList<AssertionError>();
    boolean throwExceptionCheckResponse = false;

    if( checkResponse )
    {
      throwExceptionCheckResponse = checkResponse( messageExchange, context, parameterExposureCheckConfig,
          assertionErrorList );
    }

    boolean throwExceptionCheckSeparateHTML = false;
    if( checkSeparateHTML )
    {
      throwExceptionCheckSeparateHTML = checkSeparateHTML( messageExchange, context, testStep, securityTestRunner,
          urls, parameterExposureCheckConfig, assertionErrorList );
    }

    if( throwExceptionCheckResponse || throwExceptionCheckSeparateHTML )
    {
      throw new AssertionException( assertionErrorList.toArray( new AssertionError[assertionErrorList.size()] ) );
    }

    return "OK";
  }

  private boolean checkSeparateHTML( MessageExchange messageExchange, SubmitContext context, TestStep testStep,
      SecurityTestRunner securityTestRunner, List<String> urls,
      CrossSiteScriptingScanConfig parameterExposureCheckConfig, List<AssertionError> assertionErrorList )
  {
    boolean throwException = false;
    for( String url : urls )
    {
      HttpTestRequestStep httpRequest = createHttpRequest( ( WsdlTestStep )testStep, url );
      MessageExchange messageExchange2 = ( MessageExchange )httpRequest.run( ( TestCaseRunner )securityTestRunner,
          ( SecurityTestRunContext )context );

      for( String value : parameterExposureCheckConfig.getParameterExposureStringsList() )
      {
        value = context.expand( value );// property expansion support
        String match = SecurityScanUtil.contains( context, new String( messageExchange2.getRawResponseData() ),
            value, false );
        if( match != null )
        {
          String shortValue = value.length() > 25 ? value.substring( 0, 22 ) + "... " : value;
          String message = "XSS content sent in request '" + shortValue + "' is exposed in response on link "
              + url + " . Possibility for XSS script attack in: " + messageExchange.getModelItem().getName();
          assertionErrorList.add( new AssertionError( message ) );
          throwException = true;
        }
      }
    }
    return throwException;
  }

  private boolean checkResponse( MessageExchange messageExchange, SubmitContext context,
      CrossSiteScriptingScanConfig parameterExposureCheckConfig, List<AssertionError> assertionErrorList )
  {
    boolean throwException = false;
    for( String value : parameterExposureCheckConfig.getParameterExposureStringsList() )
    {
      value = context.expand( value );// property expansion support
      String match = SecurityScanUtil.contains( context, new String( messageExchange.getRawResponseData() ), value,
          false );
      if( match != null )
      {
        String shortValue = value.length() > 25 ? value.substring( 0, 22 ) + "... " : value;
        String message = "Content that is sent in request '" + shortValue
            + "' is exposed in response. Possibility for XSS script attack in: "
            + messageExchange.getModelItem().getName();
        assertionErrorList.add( new AssertionError( message ) );
        throwException = true;
      }
    }
    return throwException;
  }

  private List<String> submitScript( MessageExchange messageExchange, SubmitContext context )
  {
    List<String> urls = new ArrayList<String>();
    scriptEngine.setScript( script );
    scriptEngine.setVariable( "urls", urls );
    scriptEngine.setVariable( "messageExchange", messageExchange );
    this.messageExchange = messageExchange;
    scriptEngine.setVariable( "context", context );
    this.context = context;
    scriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );

    try
    {
      Object result = scriptEngine.run();
      if( result instanceof List )
      {
        urls = ( List<String> )result;
      }
    }
    catch( Exception ex )
    {
      SoapUI.logError( ex );
    }
    finally
    {
      scriptEngine.clearVariables();
    }
    return urls;
  }

  private HttpTestRequestStep createHttpRequest( WsdlTestStep testStep2, String url )
  {
    HttpRequestConfig httpRequest = HttpRequestConfig.Factory.newInstance();
    httpRequest.setEndpoint( HttpUtils.ensureEndpointStartsWithProtocol( url ) );
    httpRequest.setMethod( "GET" );

    TestStepConfig testStepConfig = TestStepConfig.Factory.newInstance();
    testStepConfig.setType( HttpRequestStepFactory.HTTPREQUEST_TYPE );
    testStepConfig.setConfig( httpRequest );
    testStepConfig.setName( "Separate Request" );

    WsdlTestStepFactory factory = WsdlTestStepRegistry.getInstance().getFactory(
        ( HttpRequestStepFactory.HTTPREQUEST_TYPE ) );
    return ( HttpTestRequestStep )factory.buildTestStep( ( WsdlTestCase )testStep2.getTestCase(), testStepConfig,
        false );

  }

  public static class Factory extends AbstractTestAssertionFactory
  {
    public Factory()
    {
      super( CrossSiteScriptAssertion.ID, CrossSiteScriptAssertion.LABEL, CrossSiteScriptAssertion.class,
          CrossSiteScriptingScan.class );

    }

    @Override
    public Class<? extends WsdlMessageAssertion> getAssertionClassType()
    {
      return CrossSiteScriptAssertion.class;
    }
  }

  @Override
  protected String internalAssertRequest( MessageExchange messageExchange, SubmitContext context )
      throws AssertionException
  {
    return null;
  }

  protected XmlObject createConfiguration()
  {
    XmlObjectConfigurationBuilder builder = new XmlObjectConfigurationBuilder();
    builder.add( GROOVY_SCRIPT, script );
    builder.add( CHECK_RESPONSE, checkResponse );
    builder.add( CHECK_SEPARATE_HTML, checkSeparateHTML );
    return builder.finish();
  }

  public boolean configure()
  {
    if( dialog == null )
      buildDialog();

    dialog.show();
    if( dialog.getReturnValue() == XFormDialog.OK_OPTION )
    {
      checkResponse = Boolean.valueOf( dialog.getFormField( CrossSiteScripSeparateHTMLConfigDialog.CHECK_RESPONSE )
          .getValue() );
      checkSeparateHTML = Boolean.valueOf( dialog.getFormField(
          CrossSiteScripSeparateHTMLConfigDialog.CHECK_SEPARATE_HTML ).getValue() );
      setConfiguration( createConfiguration() );
    }
    return true;
  }

  private class GroovyEditorModel extends AbstractGroovyEditorModel
  {
    @Override
    public Action createRunAction()
    {
      return new AbstractAction()
      {
        public void actionPerformed( ActionEvent e )
        {
          Object result = null;
          List<String> urls = new ArrayList<String>();
          scriptEngine.setScript( script );
          scriptEngine.setVariable( "urls", urls );
          scriptEngine.setVariable( "messageExchange", messageExchange );
          scriptEngine.setVariable( "context", context );
          scriptEngine.setVariable( "log", SoapUI.ensureGroovyLog() );

          try
          {
            result = scriptEngine.run();
            if( result instanceof List )
            {
              urls = ( List<String> )result;
            }
            String generatedUrls = "";
            for( String url : urls )
            {
              generatedUrls += "\n" + url;
            }
            UISupport.showInfoMessage( "Generated urls :" + generatedUrls + " \n\nScript result"
                + ( ( result == null ) ? "" : ": " + result + "" ) );
          }
          catch( Exception ex )
          {
            SoapUI.logError( ex );
          }
          finally
          {
            scriptEngine.clearVariables();
          }
        }
      };
    }

    public GroovyEditorModel( ModelItem modelItem )
    {
      super( new String[] { "urls", "log", "context", "messageExchange" }, modelItem, "" );
    }

    public String getScript()
    {
      return script;
    }

    public void setScript( String text )
    {
      script = text;
    }
  }

  protected GroovyEditorComponent buildGroovyPanel()
  {
    return new GroovyEditorComponent( groovyEditorModel, null );
  }

  protected void buildDialog()
  {
    dialog = ADialogBuilder.buildDialog( CrossSiteScripSeparateHTMLConfigDialog.class );
    dialog.setSize( 600, 600 );
    dialog.setBooleanValue( CrossSiteScripSeparateHTMLConfigDialog.CHECK_RESPONSE, checkResponse );
    dialog.setBooleanValue( CrossSiteScripSeparateHTMLConfigDialog.CHECK_SEPARATE_HTML, checkSeparateHTML );
    final GroovyEditorComponent groovyEditorComponent = buildGroovyPanel();
    dialog.getFormField( CrossSiteScripSeparateHTMLConfigDialog.GROOVY ).setProperty( "component",
        new JScrollPane( groovyEditorComponent ) );
    dialog.getFormField( CrossSiteScripSeparateHTMLConfigDialog.GROOVY ).setProperty( "dimension",
        new Dimension( 450, 400 ) );
    dialog.getFormField( CrossSiteScripSeparateHTMLConfigDialog.CHECK_SEPARATE_HTML ).addFormFieldListener(
        new XFormFieldListener()
        {

          @Override
          public void valueChanged( XFormField sourceField, String newValue, String oldValue )
          {
            groovyEditorComponent.setEnabled( new Boolean( newValue ) );
          }

        } );

    groovyEditorComponent.setEnabled( checkSeparateHTML );
  }

  @Override
  public void release()
  {
    if( dialog != null )
      dialog.release();

    super.release();
  }

  // TODO : update help URL
  @AForm( description = "", name = "Cross Site Scripting on Separate HTML", helpUrl = HelpUrls.SECURITY_XSS_ASSERTION_HELP )
  protected interface CrossSiteScripSeparateHTMLConfigDialog
  {
    @AField( description = "Check Imediate Response", name = "###Check Response", type = AFieldType.BOOLEAN )
    public final static String CHECK_RESPONSE = "###Check Response";

    @AField( description = "Check Response from URLs specified in Custom Script", name = "###Check Separate HTML", type = AFieldType.BOOLEAN )
    public final static String CHECK_SEPARATE_HTML = "###Check Separate HTML";

    @AField( description = "", name = "Enter Custom Script that returns a list of URLs to check for Cross Site Scripts ", type = AFieldType.LABEL )
    public final static String LABEL = "Enter Custom Script that returns a list of URLs to check for Cross Site Scripts ";

    @AField( description = "Groovy script", name = "###Groovy url list", type = AFieldType.COMPONENT )
    public final static String GROOVY = "###Groovy url list";
  }
}
TOP

Related Classes of com.eviware.soapui.security.assertion.CrossSiteScriptAssertion$CrossSiteScripSeparateHTMLConfigDialog

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.