org.zaproxy.zap.extension.ascanrulesBeta.ExpressionLanguageInjectionPlugin.java Source code

Java tutorial

Introduction

Here is the source code for org.zaproxy.zap.extension.ascanrulesBeta.ExpressionLanguageInjectionPlugin.java

Source

/*
 * Zed Attack Proxy (ZAP) and its related class files.
 *
 * ZAP is an HTTP/HTTPS proxy for assessing web application security.
 *
 * Copyright 2014 The ZAP Development Team
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.zaproxy.zap.extension.ascanrulesBeta;

import java.io.IOException;
import java.net.UnknownHostException;
import java.util.Random;
import org.apache.commons.httpclient.InvalidRedirectLocationException;
import org.apache.commons.httpclient.URIException;
import org.apache.log4j.Logger;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.core.scanner.AbstractAppParamPlugin;
import org.parosproxy.paros.core.scanner.Alert;
import org.parosproxy.paros.core.scanner.Category;
import org.parosproxy.paros.network.HttpMessage;

/**
 * CWE-917: Improper Neutralization of Special Elements used in an Expression Language Statement
 * ('Expression Language Injection')
 *
 * <p>http://cwe.mitre.org/data/definitions/917.html
 *
 * @author yhawke (2014)
 */
public class ExpressionLanguageInjectionPlugin extends AbstractAppParamPlugin {

    // Logger object
    private static final Logger log = Logger.getLogger(ExpressionLanguageInjectionPlugin.class);

    private static final int MAX_NUM_TRIES = 1000;
    private static final int DEVIATION_VALUE = 999999;
    private static final int MEAN_VALUE = 100000;

    /**
     * Get the unique identifier of this plugin
     *
     * @return this plugin identifier
     */
    @Override
    public int getId() {
        return 90025;
    }

    /**
     * Get the name of this plugin
     *
     * @return the plugin name
     */
    @Override
    public String getName() {
        return Constant.messages.getString("ascanbeta.elinjection.name");
    }

    /**
     * Give back specific pugin dependancies (none for this)
     *
     * @return the list of plugins that need to be executed before
     */
    @Override
    public String[] getDependency() {
        return new String[] {};
    }

    /**
     * Get the description of the vulnerbaility when found
     *
     * @return the vulnerability description
     */
    @Override
    public String getDescription() {
        return Constant.messages.getString("ascanbeta.elinjection.desc");
    }

    /**
     * Give back the categorization of the vulnerability checked by this plugin (it's an injection
     * category for CODEi)
     *
     * @return a category from the Category enum list
     */
    @Override
    public int getCategory() {
        return Category.INJECTION;
    }

    /**
     * Give back a general solution for the found vulnerability
     *
     * @return the solution that can be put in place
     */
    @Override
    public String getSolution() {
        return Constant.messages.getString("ascanbeta.elinjection.soln");
    }

    @Override
    public String getReference() {
        return Constant.messages.getString("ascanbeta.elinjection.refs");
    }

    /**
     * http://cwe.mitre.org/data/definitions/917.html
     *
     * @return the official CWE id
     */
    @Override
    public int getCweId() {
        return 917;
    }

    /** @return the official WASC id */
    @Override
    public int getWascId() {
        // There's not a real classification for this
        // so we consider the general "Improper Input Handling" class
        // http://projects.webappsec.org/w/page/13246933/Improper%20Input%20Handling
        return 20;
    }

    /**
     * Give back the risk associated to this vulnerability (high)
     *
     * @return the risk according to the Alert enum
     */
    @Override
    public int getRisk() {
        return Alert.RISK_HIGH;
    }

    /** Initialize the plugin according to the overall environment configuration */
    @Override
    public void init() {
        // do nothing
    }

    /**
     * Scan for Expression Language Injection Vulnerabilites
     *
     * @param msg a request only copy of the original message (the response isn't copied)
     * @param paramName the parameter name that need to be exploited
     * @param value the original parameter value
     */
    @Override
    public void scan(HttpMessage msg, String paramName, String value) {

        String originalContent = getBaseMsg().getResponseBody().toString();
        Random rand = new Random();
        String addedString;
        int bignum1;
        int bignum2;
        int tries = 0;

        do {
            bignum1 = MEAN_VALUE + (int) (rand.nextFloat() * (DEVIATION_VALUE - MEAN_VALUE + 1));
            bignum2 = MEAN_VALUE + (int) (rand.nextFloat() * (DEVIATION_VALUE - MEAN_VALUE + 1));
            addedString = String.valueOf(bignum1 + bignum2);
            tries++;

        } while (originalContent.contains(addedString) && (tries < MAX_NUM_TRIES));

        // Build the evil payload ${100146+99273}
        String payload = "${" + bignum1 + "+" + bignum2 + "}";

        try {
            // Set the expression value
            setParameter(msg, paramName, payload);
            try {
                // Send the request and retrieve the response
                sendAndReceive(msg);
            } catch (InvalidRedirectLocationException | URIException | UnknownHostException
                    | IllegalArgumentException ex) {
                if (log.isDebugEnabled())
                    log.debug("Caught " + ex.getClass().getName() + " " + ex.getMessage() + " when accessing: "
                            + msg.getRequestHeader().getURI().toString()
                            + "\n The target may have replied with a poorly formed redirect due to our input.");
                return;
            }
            // Check if the resulting content contains the executed addition
            if (msg.getResponseBody().toString().contains(addedString)) {
                // We Found IT!
                // First do logging
                log.debug("[Expression Langage Injection Found] on parameter [" + paramName + "]  with payload ["
                        + payload + "]");

                // Now create the alert message
                this.bingo(Alert.RISK_HIGH, Alert.CONFIDENCE_MEDIUM, msg.getRequestHeader().getURI().toString(),
                        paramName, payload, null, addedString, msg);
            }

        } catch (IOException ex) {
            // Do not try to internationalise this.. we need an error message in any event..
            // if it's in English, it's still better than not having it at all.
            log.error("Expression Language Injection vulnerability check failed for parameter [" + paramName
                    + "] and payload [" + payload + "] due to an I/O error", ex);
        }
    }
}