Package com.eviware.soapui.security.assertion

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

/*
* Copyright 2004-2014 SmartBear Software
*
* Licensed under the EUPL, Version 1.1 or - as soon as they will be approved by the European Commission - subsequent
* versions of the EUPL (the "Licence");
* You may not use this work except in compliance with the Licence.
* You may obtain a copy of the Licence at:
*
* http://ec.europa.eu/idabc/eupl
*
* Unless required by applicable law or agreed to in writing, software distributed under the Licence is
* distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the Licence for the specific language governing permissions and limitations
* under the Licence.
*/
package com.eviware.soapui.security.assertion;

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.assertions.AssertionListEntry;
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.TestPropertyHolder;
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;
import org.apache.xmlbeans.XmlObject;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JScrollPane;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.util.ArrayList;
import java.util.List;

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 DESCRIPTION = "Cross Site Scripting....assertion for...";
    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.completeUrlWithHttpIfProtocolIsNotHttpOrHttpsOrPropertyExpansion(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);

    }

    protected String internalAssertProperty(TestPropertyHolder source, String propertyName,
                                            MessageExchange messageExchange, SubmitContext context) throws AssertionException {
        //    return internalAssertResponse( messageExchange, context );
        return null;
    }

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

        }

        @Override
        public String getCategory() {
            return "";
        }

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

        @Override
        public AssertionListEntry getAssertionListEntry() {
            return new AssertionListEntry(CrossSiteScriptAssertion.ID, CrossSiteScriptAssertion.LABEL,
                    CrossSiteScriptAssertion.DESCRIPTION);
        }
    }

    @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();
    }

    @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$Factory

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.