Example usage for org.apache.commons.httpclient URI getURI

List of usage examples for org.apache.commons.httpclient URI getURI

Introduction

In this page you can find the example usage for org.apache.commons.httpclient URI getURI.

Prototype

public String getURI() throws URIException 

Source Link

Document

It can be gotten the URI character sequence.

Usage

From source file:com.navercorp.pinpoint.plugin.httpclient3.HttpClient3RequestTrace.java

private static String getHttpUrl(final String host, final int port, final URI uri,
        final HttpConnection httpConnection) throws URIException {
    final Protocol protocol = httpConnection.getProtocol();
    if (protocol == null) {
        return uri.getURI();
    }// w  w  w .ja  va 2 s  . com
    final StringBuilder sb = new StringBuilder();
    final String scheme = protocol.getScheme();
    sb.append(scheme).append("://");
    sb.append(host);
    // if port is default port number.
    if (port != SKIP_DEFAULT_PORT) {
        sb.append(':').append(port);
    }
    sb.append(uri.getURI());
    return sb.toString();
}

From source file:com.baidu.oped.apm.profiler.modifier.connector.httpclient3.interceptor.ExecuteInterceptor.java

@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
    if (isDebug) {
        logger.afterInterceptor(target, args);
    }/*  w  ww  .  j  a  v  a2  s  .c  o m*/

    final Trace trace = traceContext.currentTraceObject();

    if (trace == null) {
        return;
    }

    try {
        HttpMethod httpMethod = getHttpMethod(args);

        if (httpMethod != null) {
            try {
                final URI uri = httpMethod.getURI();
                String uriString = uri.getURI();
                trace.recordAttribute(AnnotationKey.HTTP_URL, uriString);
                trace.recordDestinationId(getEndpoint(uri.getHost(), uri.getPort()));
            } catch (URIException e) {
                logger.error("Fail get URI", e);
            }

            recordRequest(trace, httpMethod, throwable);
        }

        if (result != null) {
            trace.recordAttribute(AnnotationKey.HTTP_STATUS_CODE, result);
        }

        trace.recordApi(descriptor);
        trace.recordException(throwable);
        trace.markAfterTime();
    } finally {
        trace.traceBlockEnd();
    }
}

From source file:com.navercorp.pinpoint.plugin.httpclient3.interceptor.ExecuteInterceptor.java

@Override
public void after(Object target, Object[] args, Object result, Throwable throwable) {
    if (isDebug) {
        logger.afterInterceptor(target, args);
    }/*from  www.  j a v a 2 s  . c  om*/

    final Trace trace = traceContext.currentTraceObject();
    if (trace == null) {
        return;
    }

    try {
        HttpMethod httpMethod = getHttpMethod(args);
        if (httpMethod != null) {
            try {
                final URI uri = httpMethod.getURI();
                String uriString = uri.getURI();
                trace.recordAttribute(AnnotationKey.HTTP_URL, uriString);
                trace.recordDestinationId(getEndpoint(uri.getHost(), uri.getPort()));
            } catch (URIException e) {
                logger.error("Fail get URI", e);
            }

            recordRequest(trace, httpMethod, throwable);
        }

        if (result != null) {
            trace.recordAttribute(AnnotationKey.HTTP_STATUS_CODE, result);
        }

        trace.recordApi(descriptor);
        trace.recordException(throwable);
        trace.markAfterTime();
    } finally {
        trace.traceBlockEnd();
    }
}

From source file:com.navercorp.pinpoint.plugin.httpclient3.HttpClient3RequestTrace.java

@Override
public String getUrl() {
    try {// www .  j  a  v  a  2  s .  co  m
        final URI uri = this.httpMethod.getURI();
        // if uri have schema or not found HttpConnection argument.
        if (uri.isAbsoluteURI() || this.httpConnection == null) {
            return uri.getURI();
        }
        final String host = this.httpConnection.getHost();
        final int port = getPort(this.httpConnection);
        return getHttpUrl(host, port, uri, this.httpConnection);
    } catch (Exception e) {
        if (isDebug) {
            logger.debug("Failed to get url. httpMethod={}", this.httpMethod, e);
        }
    }
    return null;
}

From source file:de.kimminich.agile.demos.lecture4.TestSQLInjection.java

/**
 * scans for SQL Injection vulnerabilities
 *///  w  w w .jav  a  2  s  .c om
@Override
public void scan(HttpMessage msg, String param, String origParamValue) {
    //Note: the "value" we are passed here is escaped. we need to unescape it before handling it.
    //as soon as we find a single SQL injection on the url, skip out. Do not look for SQL injection on a subsequent parameter on the same URL
    //for performance reasons.
    boolean sqlInjectionFoundForUrl = false;
    String sqlInjectionAttack = null;
    HttpMessage refreshedmessage = null;
    String mResBodyNormalUnstripped = null;
    String mResBodyNormalStripped = null;

    try {

        //reinitialise the count for each type of request, for each parameter.  We will be sticking to limits defined in the attach strength logic
        int countErrorBasedRequests = 0;
        int countExpressionBasedRequests = 0;
        int countBooleanBasedRequests = 0;
        int countUnionBasedRequests = 0;
        int countOrderByBasedRequests = 0;
        int countStackedBasedRequests = 0; //TODO: use in the stacked based queries implementation

        //Check 1: Check for Error Based SQL Injection (actual error messages).
        //for each SQL metacharacter combination to try
        for (int sqlErrorStringIndex = 0; sqlErrorStringIndex < SQL_CHECK_ERR.length && !sqlInjectionFoundForUrl
                && doErrorBased && countErrorBasedRequests < doErrorMaxRequests; sqlErrorStringIndex++) {

            //work through the attack using each of the following strings as a prefix: the empty string, and the original value
            //Note: this doubles the amount of work done by the scanner, but is necessary in some cases
            String[] prefixStrings;
            if (origParamValue != null) {
                prefixStrings = new String[] { "", TestSQLInjection.getURLDecode(origParamValue) };
            } else {
                prefixStrings = new String[] { "" };
            }
            for (int prefixIndex = 0; prefixIndex < prefixStrings.length; prefixIndex++) {

                //new message for each value we attack with
                HttpMessage msg1 = getNewMsg();
                String sqlErrValue = prefixStrings[prefixIndex] + SQL_CHECK_ERR[sqlErrorStringIndex];
                setParameter(msg1, param, sqlErrValue);

                //System.out.println("Attacking [" + msg + "], parameter [" + param + "] with value ["+ sqlErrValue + "]");

                //send the message with the modified parameters
                sendAndReceive(msg1);
                countErrorBasedRequests++;

                //now check the results against each pattern in turn, to try to identify a database, or even better: a specific database.
                //Note: do NOT check the HTTP error code just yet, as the result could come back with one of various codes.
                Iterator<String> errorPatternIterator = SQL_ERROR_TO_DBMS.keySet().iterator();

                while (errorPatternIterator.hasNext() && !sqlInjectionFoundForUrl) {
                    String errorPatternKey = errorPatternIterator.next();
                    String errorPatternRDBMS = SQL_ERROR_TO_DBMS.get(errorPatternKey);

                    //Note: must escape the strings, in case they contain strings like "[Microsoft], which would be interpreted as regular character class regexps"
                    Pattern errorPattern = Pattern.compile("\\Q" + errorPatternKey + "\\E", PATTERN_PARAM);

                    //if the "error message" occurs in the result of sending the modified query, but did NOT occur in the original result of the original query
                    //then we may may have a SQL Injection vulnerability
                    StringBuilder sb = new StringBuilder();
                    if (!matchBodyPattern(getBaseMsg(), errorPattern, null)
                            && matchBodyPattern(msg1, errorPattern, sb)) {
                        //Likely a SQL Injection. Raise it
                        String extraInfo = Constant.messages.getString(
                                "ascanrules.sqlinjection.alert.errorbased.extrainfo", errorPatternRDBMS,
                                errorPatternKey);
                        //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                        sqlInjectionAttack = sqlErrValue;
                        bingo(Alert.RISK_HIGH, Alert.WARNING, getName() + " - " + errorPatternRDBMS,
                                getDescription(), null, param, sqlInjectionAttack, extraInfo, getSolution(),
                                msg1);

                        //log it, as the RDBMS may be useful to know later (in subsequent checks, when we need to determine RDBMS specific behaviour, for instance)
                        getKb().add(getBaseMsg().getRequestHeader().getURI(), "sql/" + errorPatternRDBMS,
                                Boolean.TRUE);

                        sqlInjectionFoundForUrl = true;
                        continue;
                    }
                } //end of the loop to check for RDBMS specific error messages

            } //for each of the SQL_CHECK_ERR values (SQL metacharacters)
        }

        //###############################
        //Check 4
        //New!  I haven't seen this technique documented anywhere else, but it's dead simple. Let me explain.
        //See if the parameter value can simply be changed to one that *evaluates* to be the same value,
        //if evaluated on a database
        //the simple check is to see if parameter "1" gives the same results as for param "2-1", and different results for param "2-2"
        //for now, we try this for integer values only.
        //###############################
        //Since the previous checks are attempting SQL injection, and may have actually succeeded in modifying the database (ask me how I know?!)
        //then we cannot rely on the database contents being the same as when the original query was last run (could be hours ago)
        //so to work around this, simply re-run the query again now at this point.
        //Note that we are not counting this request in our max number of requests to be issued
        refreshedmessage = getNewMsg();
        sendAndReceive(refreshedmessage);

        //String mResBodyNormal = getBaseMsg().getResponseBody().toString();
        mResBodyNormalUnstripped = refreshedmessage.getResponseBody().toString();
        mResBodyNormalStripped = this.stripOff(mResBodyNormalUnstripped, origParamValue);

        if (!sqlInjectionFoundForUrl && doExpressionBased
                && countExpressionBasedRequests < doExpressionMaxRequests) {

            //first figure out the type of the parameter..
            try {
                //is it an integer type?
                int paramAsInt = new Integer(TestSQLInjection.getURLDecode(origParamValue));
                if (this.debugEnabled)
                    log.debug("The parameter value [" + TestSQLInjection.getURLDecode(origParamValue)
                            + "] is of type Integer");

                //get a value 2 sizes bigger
                int paramPlusTwo = paramAsInt + 2;
                String modifiedParamValue = String.valueOf(paramPlusTwo) + "-2";

                //and prepare a request to set the parameter value to a string value like "3-2", if the original parameter value was "1"
                //those of you still paying attention will note that if handled as expressions (such as by a database), these represent the same value.
                HttpMessage msg4 = getNewMsg();
                setParameter(msg4, param, modifiedParamValue);

                sendAndReceive(msg4);
                countExpressionBasedRequests++;

                String modifiedExpressionOutputUnstripped = msg4.getResponseBody().toString();
                String modifiedExpressionOutputStripped = this.stripOff(modifiedExpressionOutputUnstripped,
                        modifiedParamValue);

                //set up two little arrays to ease the work of checking the unstripped output, and then the stripped output
                String normalBodyOutput[] = { mResBodyNormalUnstripped, mResBodyNormalStripped };
                String expressionBodyOutput[] = { modifiedExpressionOutputUnstripped,
                        modifiedExpressionOutputStripped };
                boolean strippedOutput[] = { false, true };

                for (int booleanStrippedUnstrippedIndex = 0; booleanStrippedUnstrippedIndex < 2; booleanStrippedUnstrippedIndex++) {
                    //if the results of the modified request match the original query, we may be onto something.
                    if (expressionBodyOutput[booleanStrippedUnstrippedIndex]
                            .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) == 0) {
                        if (this.debugEnabled)
                            log.debug("Check 4, "
                                    + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                            : "UNSTRIPPED")
                                    + " html output for modified expression parameter [" + modifiedParamValue
                                    + "] matched (refreshed) original results for "
                                    + refreshedmessage.getRequestHeader().getURI());
                        //confirm that a different parameter value generates different output, to minimise false positives

                        //get a value 3 sizes bigger this time
                        int paramPlusFour = paramAsInt + 3;
                        String modifiedParamValueConfirm = String.valueOf(paramPlusFour) + "-2";

                        //and prepare a request to set the parameter value to a string value like "4-2", if the original parameter value was "1"
                        //Note that the two values are NOT equivalent, and the param value is different to the original
                        HttpMessage msg4Confirm = getNewMsg();
                        setParameter(msg4Confirm, param, modifiedParamValueConfirm);

                        sendAndReceive(msg4Confirm);
                        countExpressionBasedRequests++;

                        String confirmExpressionOutputUnstripped = msg4Confirm.getResponseBody().toString();
                        String confirmExpressionOutputStripped = this
                                .stripOff(confirmExpressionOutputUnstripped, modifiedParamValueConfirm);

                        //set up two little arrays to ease the work of checking the unstripped output or the stripped output
                        String confirmExpressionBodyOutput[] = { confirmExpressionOutputUnstripped,
                                confirmExpressionOutputStripped };

                        if (confirmExpressionBodyOutput[booleanStrippedUnstrippedIndex]
                                .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) {
                            //the confirm query did not return the same results.  This means that arbitrary queries are not all producing the same page output.
                            //this means the fact we earier reproduced the original page output with a modified parameter was not a coincidence

                            //Likely a SQL Injection. Raise it
                            String extraInfo = null;
                            if (strippedOutput[booleanStrippedUnstrippedIndex])
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.expressionbased.extrainfo",
                                        modifiedParamValue, "");
                            else
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.expressionbased.extrainfo",
                                        modifiedParamValue, "NOT ");

                            //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                            sqlInjectionAttack = modifiedParamValue;
                            bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                    param, sqlInjectionAttack, extraInfo, getSolution(), msg4);

                            sqlInjectionFoundForUrl = true;
                        }
                    }
                }
            } catch (Exception e) {

                if (this.debugEnabled)
                    log.debug("The parameter value [" + TestSQLInjection.getURLDecode(origParamValue)
                            + "] is NOT of type Integer");
                //TODO: implement a similar check for string types?  This probably need to be RDBMS specific (ie, it should not live in this scanner)
            }
        }

        //Check 2: boolean based checks.
        //the check goes like so:
        // append " and 1 = 1" to the param.  Send the query.  Check the results. Hopefully they match the original results from the unmodified query,
        // *suggesting* (but not yet definitely) that we have successfully modified the query, (hopefully not gotten an error message),
        // and have gotten the same results back, which is what you would expect if you added the constraint " and 1 = 1" to most (but not every) SQL query.
        // So was it a fluke that we got the same results back from the modified query? Perhaps the original query returned 0 rows, so adding any number of
        // constraints would change nothing?  It is still a possibility!
        // check to see if we can change the original parameter again to *restrict* the scope of the query using an AND with an always false condition (AND_ERR)
        // (decreasing the results back to nothing), or to *broaden* the scope of the query using an OR with an always true condition (AND_OR)
        // (increasing the results).
        // If we can successfully alter the results to our requirements, by one means or another, we have found a SQL Injection vulnerability.
        //Some additional complications: assume there are 2 HTML parameters: username and password, and the SQL constructed is like so:
        // select * from username where user = "$user" and password = "$password"
        // and lets assume we successfully know the type of the user field, via SQL_OR_TRUE value '" OR "1"="1' (single quotes not part of the value)
        // we still have the problem that the actual SQL executed would look like so:
        // select * from username where user = "" OR "1"="1" and password = "whateveritis"
        // Since the password field is still taken into account (by virtue of the AND condition on the password column), and we only inject one parameter at a time,
        // we are still not in control.
        // the solution is simple: add an end-of-line comment to the field added in (in this example: the user field), so that the SQL becomes:
        // select * from username where user = "" OR "1"="1" -- and password = "whateveritis"
        // the result is that any additional constraints are commented out, and the last condition to have any effect is the one whose
        // HTTP param we are manipulating.
        // Note also that because this comment only needs to be added to the "SQL_OR_TRUE" and not to the equivalent SQL_AND_FALSE, because of the nature of the OR
        // and AND conditions in SQL.
        // Corollary: If a particular RDBMS does not offer the ability to comment out the remainder of a line, we will not attempt to comment out anything in the query
        //            and we will simply hope that the *last* constraint in the SQL query is constructed from a HTTP parameter under our control.

        if (this.debugEnabled)
            log.debug("Doing Check 2, since check 1 did not match for "
                    + getBaseMsg().getRequestHeader().getURI());

        //Since the previous checks are attempting SQL injection, and may have actually succeeded in modifying the database (ask me how I know?!)
        //then we cannot rely on the database contents being the same as when the original query was last run (could be hours ago)
        //so to work around this, simply re-run the query again now at this point.
        //Note that we are not counting this request in our max number of requests to be issued
        refreshedmessage = getNewMsg();
        sendAndReceive(refreshedmessage);

        //String mResBodyNormal = getBaseMsg().getResponseBody().toString();
        mResBodyNormalUnstripped = refreshedmessage.getResponseBody().toString();
        mResBodyNormalStripped = this.stripOff(mResBodyNormalUnstripped, origParamValue);

        //boolean booleanBasedSqlInjectionFoundForParam = false;

        //try each of the AND syntax values in turn.
        //Which one is successful will depend on the column type of the table/view column into which we are injecting the SQL.
        for (int i = 0; i < SQL_LOGIC_AND_TRUE.length && !sqlInjectionFoundForUrl && doBooleanBased
                && countBooleanBasedRequests < doBooleanMaxRequests; i++) {
            //needs a new message for each type of AND to be issued
            HttpMessage msg2 = getNewMsg();
            String sqlBooleanAndTrueValue = TestSQLInjection.getURLDecode(origParamValue)
                    + SQL_LOGIC_AND_TRUE[i];
            String sqlBooleanAndFalseValue = TestSQLInjection.getURLDecode(origParamValue)
                    + SQL_LOGIC_AND_FALSE[i];

            setParameter(msg2, param, sqlBooleanAndTrueValue);

            //send the AND with an additional TRUE statement tacked onto the end. Hopefully it will return the same results as the original (to find a vulnerability)
            sendAndReceive(msg2);
            countBooleanBasedRequests++;

            //String resBodyAND = msg2.getResponseBody().toString();
            String resBodyANDTrueUnstripped = msg2.getResponseBody().toString();
            String resBodyANDTrueStripped = this.stripOff(resBodyANDTrueUnstripped, sqlBooleanAndTrueValue);

            //set up two little arrays to ease the work of checking the unstripped output, and then the stripped output
            String normalBodyOutput[] = { mResBodyNormalUnstripped, mResBodyNormalStripped };
            String andTrueBodyOutput[] = { resBodyANDTrueUnstripped, resBodyANDTrueStripped };
            boolean strippedOutput[] = { false, true };

            for (int booleanStrippedUnstrippedIndex = 0; booleanStrippedUnstrippedIndex < 2; booleanStrippedUnstrippedIndex++) {
                //if the results of the "AND 1=1" match the original query (using either the stipped or unstripped versions), we may be onto something.
                if (andTrueBodyOutput[booleanStrippedUnstrippedIndex]
                        .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) == 0) {
                    if (this.debugEnabled)
                        log.debug("Check 2, "
                                + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for AND TRUE condition [" + sqlBooleanAndTrueValue
                                + "] matched (refreshed) original results for "
                                + refreshedmessage.getRequestHeader().getURI());
                    //so they match. Was it a fluke? See if we get the same result by tacking on "AND 1 = 2" to the original
                    HttpMessage msg2_and_false = getNewMsg();

                    setParameter(msg2_and_false, param, sqlBooleanAndFalseValue);

                    sendAndReceive(msg2_and_false);
                    countBooleanBasedRequests++;

                    //String resBodyANDFalse = stripOff(msg2_and_false.getResponseBody().toString(), SQL_LOGIC_AND_FALSE[i]);
                    //String resBodyANDFalse = msg2_and_false.getResponseBody().toString();
                    String resBodyANDFalseUnstripped = msg2_and_false.getResponseBody().toString();
                    String resBodyANDFalseStripped = this.stripOff(resBodyANDFalseUnstripped,
                            sqlBooleanAndFalseValue);

                    String andFalseBodyOutput[] = { resBodyANDFalseUnstripped, resBodyANDFalseStripped };

                    //which AND False output should we compare? the stripped or the unstripped version?
                    //depends on which one we used to get to here.. use the same as that..

                    // build an always false AND query.  Result should be different to prove the SQL works.
                    if (andFalseBodyOutput[booleanStrippedUnstrippedIndex]
                            .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) {
                        if (this.debugEnabled)
                            log.debug("Check 2, "
                                    + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                            : "UNSTRIPPED")
                                    + " html output for AND FALSE condition [" + sqlBooleanAndFalseValue
                                    + "] differed from (refreshed) original results for "
                                    + refreshedmessage.getRequestHeader().getURI());

                        //it's different (suggesting that the "AND 1 = 2" appended on gave different results because it restricted the data set to nothing
                        //Likely a SQL Injection. Raise it
                        String extraInfo = null;
                        if (strippedOutput[booleanStrippedUnstrippedIndex])
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                    sqlBooleanAndTrueValue, sqlBooleanAndFalseValue, "");
                        else
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                    sqlBooleanAndTrueValue, sqlBooleanAndFalseValue, "NOT ");
                        extraInfo = extraInfo + "\n" + Constant.messages
                                .getString("ascanrules.sqlinjection.alert.booleanbased.extrainfo.dataexists");

                        //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                        sqlInjectionAttack = sqlBooleanAndTrueValue;
                        bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                param, sqlInjectionAttack, extraInfo, getSolution(), msg2);

                        sqlInjectionFoundForUrl = true;

                        continue; //to the next entry in SQL_AND
                    } else {
                        //the results of the always false condition are the same as for the original unmodified parameter
                        //this could be because there was *no* data returned for the original unmodified parameter
                        //so consider the effect of adding comments to both the always true condition, and the always false condition
                        //the first value to try..
                        String orValue = TestSQLInjection.getURLDecode(origParamValue) + SQL_LOGIC_OR_TRUE[i];

                        //this is where that comment comes in handy: if the RDBMS supports one-line comments, add one in to attempt to ensure that the
                        //condition becomes one that is effectively always true, returning ALL data (or as much as possible), allowing us to pinpoint the SQL Injection
                        if (this.debugEnabled)
                            log.debug("Check 2 , "
                                    + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                            : "UNSTRIPPED")
                                    + " html output for AND FALSE condition [" + sqlBooleanAndFalseValue
                                    + "] SAME as (refreshed) original results for "
                                    + refreshedmessage.getRequestHeader().getURI()
                                    + " ### (forcing OR TRUE check) ");
                        HttpMessage msg2_or_true = getNewMsg();
                        setParameter(msg2_or_true, param, orValue);
                        sendAndReceive(msg2_or_true);
                        countBooleanBasedRequests++;

                        //String resBodyORTrue = stripOff(msg2_or_true.getResponseBody().toString(), orValue);
                        //String resBodyORTrue = msg2_or_true.getResponseBody().toString();
                        String resBodyORTrueUnstripped = msg2_or_true.getResponseBody().toString();
                        String resBodyORTrueStripped = this.stripOff(resBodyORTrueUnstripped, orValue);

                        String orTrueBodyOutput[] = { resBodyORTrueUnstripped, resBodyORTrueStripped };

                        int compareOrToOriginal = orTrueBodyOutput[booleanStrippedUnstrippedIndex]
                                .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]);
                        if (compareOrToOriginal != 0) {

                            if (this.debugEnabled)
                                log.debug("Check 2, "
                                        + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED"
                                                : "UNSTRIPPED")
                                        + " html output for OR TRUE condition [" + orValue
                                        + "] different to (refreshed) original results for "
                                        + refreshedmessage.getRequestHeader().getURI());

                            //it's different (suggesting that the "OR 1 = 1" appended on gave different results because it broadened the data set from nothing to something
                            //Likely a SQL Injection. Raise it
                            String extraInfo = null;
                            if (strippedOutput[booleanStrippedUnstrippedIndex])
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                        sqlBooleanAndTrueValue, orValue, "");
                            else
                                extraInfo = Constant.messages.getString(
                                        "ascanrules.sqlinjection.alert.booleanbased.extrainfo",
                                        sqlBooleanAndTrueValue, orValue, "NOT ");
                            extraInfo = extraInfo + "\n" + Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.booleanbased.extrainfo.datanotexists");

                            //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                            sqlInjectionAttack = orValue;
                            bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                    param, sqlInjectionAttack, extraInfo, getSolution(), msg2);

                            sqlInjectionFoundForUrl = true;
                            //booleanBasedSqlInjectionFoundForParam = true;  //causes us to skip past the other entries in SQL_AND.  Only one will expose a vuln for a given param, since the database column is of only 1 type

                            continue;
                        }
                    }
                } //if the results of the "AND 1=1" match the original query, we may be onto something.
                else {
                    //andTrueBodyOutput[booleanStrippedUnstrippedIndex].compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex])
                    //the results of the "AND 1=1" do NOT match the original query, for whatever reason (no sql injection, or the web page is not stable)
                    if (this.debugEnabled) {
                        log.debug("Check 2, "
                                + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for AND condition [" + sqlBooleanAndTrueValue
                                + "] does NOT match the (refreshed) original results for "
                                + refreshedmessage.getRequestHeader().getURI());
                        Patch diffpatch = DiffUtils.diff(
                                new LinkedList<String>(Arrays
                                        .asList(normalBodyOutput[booleanStrippedUnstrippedIndex].split("\\n"))),
                                new LinkedList<String>(Arrays.asList(
                                        andTrueBodyOutput[booleanStrippedUnstrippedIndex].split("\\n"))));

                        //int numberofDifferences = diffpatch.getDeltas().size();

                        //and convert the list of patches to a String, joining using a newline
                        StringBuilder tempDiff = new StringBuilder(250);
                        for (Delta delta : diffpatch.getDeltas()) {
                            String changeType = null;
                            if (delta.getType() == Delta.TYPE.CHANGE)
                                changeType = "Changed Text";
                            else if (delta.getType() == Delta.TYPE.DELETE)
                                changeType = "Deleted Text";
                            else if (delta.getType() == Delta.TYPE.INSERT)
                                changeType = "Inserted text";
                            else
                                changeType = "Unknown change type [" + delta.getType() + "]";

                            tempDiff.append("\n(" + changeType + ")\n"); //blank line before
                            tempDiff.append("Output for Unmodified parameter: " + delta.getOriginal() + "\n");
                            tempDiff.append("Output for   modified parameter: " + delta.getRevised() + "\n");
                        }
                        log.debug("DIFFS: " + tempDiff);
                    }
                }

            } //end of boolean logic output index (unstripped + stripped)
        }
        //end of check 2

        //Check 3: UNION based
        //for each SQL UNION combination to try
        for (int sqlUnionStringIndex = 0; sqlUnionStringIndex < SQL_UNION_APPENDAGES.length
                && !sqlInjectionFoundForUrl && doUnionBased
                && countUnionBasedRequests < doUnionMaxRequests; sqlUnionStringIndex++) {

            //new message for each value we attack with
            HttpMessage msg3 = getNewMsg();
            String sqlUnionValue = origParamValue + SQL_UNION_APPENDAGES[sqlUnionStringIndex];
            setParameter(msg3, param, sqlUnionValue);
            //send the message with the modified parameters
            sendAndReceive(msg3);
            countUnionBasedRequests++;

            //now check the results.. look first for UNION specific error messages in the output that were not there in the original output
            //and failing that, look for generic RDBMS specific error messages
            //TODO: maybe also try looking at a differentiation based approach?? Prone to false positives though.
            Iterator<String> errorPatternUnionIterator = SQL_UNION_ERROR_TO_DBMS.keySet().iterator();

            while (errorPatternUnionIterator.hasNext() && !sqlInjectionFoundForUrl) {
                String errorPatternKey = errorPatternUnionIterator.next();
                String errorPatternRDBMS = SQL_UNION_ERROR_TO_DBMS.get(errorPatternKey);

                //Note: must escape the strings, in case they contain strings like "[Microsoft], which would be interpreted as regular character class regexps"
                Pattern errorPattern = Pattern.compile("\\Q" + errorPatternKey + "\\E", PATTERN_PARAM);

                //if the "error message" occurs in the result of sending the modified query, but did NOT occur in the original result of the original query
                //then we may may have a SQL Injection vulnerability
                StringBuilder sb = new StringBuilder();
                String sqlUnionBodyUnstripped = msg3.getResponseBody().toString();
                String sqlUnionBodyStripped = this.stripOff(sqlUnionBodyUnstripped, sqlUnionValue);

                Matcher matcherOrig = errorPattern.matcher(mResBodyNormalStripped);
                Matcher matcherSQLUnion = errorPattern.matcher(sqlUnionBodyStripped);
                boolean patternInOrig = matcherOrig.find();
                boolean patternInSQLUnion = matcherSQLUnion.find();

                //if (! matchBodyPattern(getBaseMsg(), errorPattern, null) && matchBodyPattern(msg3, errorPattern, sb)) {
                if (!patternInOrig && patternInSQLUnion) {
                    //Likely a UNION Based SQL Injection (by error message). Raise it
                    String extraInfo = Constant.messages.getString(
                            "ascanrules.sqlinjection.alert.unionbased.extrainfo", errorPatternRDBMS,
                            errorPatternKey);

                    //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                    sqlInjectionAttack = sqlUnionValue;
                    bingo(Alert.RISK_HIGH, Alert.WARNING, getName() + " - " + errorPatternRDBMS,
                            getDescription(), refreshedmessage.getRequestHeader().getURI().getURI(), //url
                            param, sqlInjectionAttack, extraInfo, getSolution(), msg3);

                    //log it, as the RDBMS may be useful to know later (in subsequent checks, when we need to determine RDBMS specific behaviour, for instance)
                    getKb().add(refreshedmessage.getRequestHeader().getURI(), "sql/" + errorPatternRDBMS,
                            Boolean.TRUE);

                    sqlInjectionFoundForUrl = true;
                    continue;
                }
            } //end of the loop to check for RDBMS specific UNION error messages
        } ////for each SQL UNION combination to try
          //end of check 3

        //###############################

        //check for columns used in the "order by" clause of a SQL statement. earlier tests will likely not catch these

        //append on " ASC -- " to the end of the original parameter. Grab the results.
        //if the results are different to the original (unmodified parameter) results, then bale
        //if the results are the same as for the original parameter value, then the parameter *might* be influencing the order by
        //   try again for "DESC": append on " DESC -- " to the end of the original parameter. Grab the results.
        //   if the results are the same as the original (unmodified parameter) results, then bale
        //   (the results are not under our control, or there is no difference in the ordering, for some reason: 0 or 1 rows only, or ordering
        //   by the first column alone is not sufficient to change the ordering of the data.)
        //   if the results were different to the original (unmodified parameter) results, then
        //      SQL injection!!

        //Since the previous checks are attempting SQL injection, and may have actually succeeded in modifying the database (ask me how I know?!)
        //then we cannot rely on the database contents being the same as when the original query was last run (could be hours ago)
        //so to work around this, simply re-run the query again now at this point.
        //Note that we are not counting this request in our max number of requests to be issued
        refreshedmessage = getNewMsg();
        sendAndReceive(refreshedmessage);

        //String mResBodyNormal = getBaseMsg().getResponseBody().toString();
        mResBodyNormalUnstripped = refreshedmessage.getResponseBody().toString();
        mResBodyNormalStripped = this.stripOff(mResBodyNormalUnstripped, origParamValue);

        if (!sqlInjectionFoundForUrl && doOrderByBased && countOrderByBasedRequests < doOrderByMaxRequests) {

            String modifiedParamValue = TestSQLInjection.getURLDecode(origParamValue) + " ASC "
                    + SQL_ONE_LINE_COMMENT;

            HttpMessage msg5 = getNewMsg();
            setParameter(msg5, param, modifiedParamValue);

            sendAndReceive(msg5);
            countOrderByBasedRequests++;

            String modifiedAscendingOutputUnstripped = msg5.getResponseBody().toString();
            String modifiedAscendingOutputStripped = this.stripOff(modifiedAscendingOutputUnstripped,
                    modifiedParamValue);

            //set up two little arrays to ease the work of checking the unstripped output, and then the stripped output
            String normalBodyOutput[] = { mResBodyNormalUnstripped, mResBodyNormalStripped };
            String ascendingBodyOutput[] = { modifiedAscendingOutputUnstripped,
                    modifiedAscendingOutputStripped };
            boolean strippedOutput[] = { false, true };

            for (int booleanStrippedUnstrippedIndex = 0; booleanStrippedUnstrippedIndex < 2; booleanStrippedUnstrippedIndex++) {
                //if the results of the modified request match the original query, we may be onto something.
                if (ascendingBodyOutput[booleanStrippedUnstrippedIndex]
                        .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) == 0) {
                    if (this.debugEnabled)
                        log.debug("Check X, "
                                + (strippedOutput[booleanStrippedUnstrippedIndex] ? "STRIPPED" : "UNSTRIPPED")
                                + " html output for modified Order By parameter [" + modifiedParamValue
                                + "] matched (refreshed) original results for "
                                + refreshedmessage.getRequestHeader().getURI());
                    //confirm that a different parameter value generates different output, to minimise false positives

                    //use the descending order this time
                    String modifiedParamValueConfirm = TestSQLInjection.getURLDecode(origParamValue) + " DESC "
                            + SQL_ONE_LINE_COMMENT;

                    HttpMessage msg5Confirm = getNewMsg();
                    setParameter(msg5Confirm, param, modifiedParamValueConfirm);

                    sendAndReceive(msg5Confirm);
                    countOrderByBasedRequests++;

                    String confirmOrderByOutputUnstripped = msg5Confirm.getResponseBody().toString();
                    String confirmOrderByOutputStripped = this.stripOff(confirmOrderByOutputUnstripped,
                            modifiedParamValueConfirm);

                    //set up two little arrays to ease the work of checking the unstripped output or the stripped output
                    String confirmOrderByBodyOutput[] = { confirmOrderByOutputUnstripped,
                            confirmOrderByOutputStripped };

                    if (confirmOrderByBodyOutput[booleanStrippedUnstrippedIndex]
                            .compareTo(normalBodyOutput[booleanStrippedUnstrippedIndex]) != 0) {
                        //the confirm query did not return the same results.  This means that arbitrary queries are not all producing the same page output.
                        //this means the fact we earlier reproduced the original page output with a modified parameter was not a coincidence

                        //Likely a SQL Injection. Raise it
                        String extraInfo = null;
                        if (strippedOutput[booleanStrippedUnstrippedIndex])
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.orderbybased.extrainfo", modifiedParamValue,
                                    "");
                        else
                            extraInfo = Constant.messages.getString(
                                    "ascanrules.sqlinjection.alert.orderbybased.extrainfo", modifiedParamValue,
                                    "NOT ");

                        //raise the alert, and save the attack string for the "Authentication Bypass" alert, if necessary
                        sqlInjectionAttack = modifiedParamValue;
                        bingo(Alert.RISK_HIGH, Alert.WARNING, getName(), getDescription(), null, //url
                                param, sqlInjectionAttack, extraInfo, getSolution(), msg5);

                        sqlInjectionFoundForUrl = true;
                    }
                }
            }

        }

        //###############################

        //if a sql injection was found, we should check if the page is flagged as a login page
        //in any of the contexts.  if it is, raise an "SQL Injection - Authentication Bypass" alert in addition to the alerts already raised
        if (sqlInjectionFoundForUrl) {
            boolean loginUrl = false;
            //log.debug("### A SQL Injection may lead to auth bypass..");

            //are we dealing with a login url in any of the contexts?
            ExtensionAuth extAuth = (ExtensionAuth) Control.getSingleton().getExtensionLoader()
                    .getExtension(ExtensionAuth.NAME);
            URI requestUri = getBaseMsg().getRequestHeader().getURI();

            //using the session, get the list of contexts for the url
            List<Context> contextList = extAuth.getModel().getSession().getContextsForUrl(requestUri.getURI());

            //now loop, and see if the url is a login url in each of the contexts in turn..
            for (Context context : contextList) {
                HttpMessage loginRequest = extAuth.getApi().getLoginRequest(context.getIndex());
                if (loginRequest != null) {
                    URI loginUri = loginRequest.getRequestHeader().getURI();
                    if (requestUri.getScheme().equals(loginUri.getScheme())
                            && requestUri.getHost().equals(loginUri.getHost())
                            && requestUri.getPort() == loginUri.getPort()
                            && requestUri.getPath().equals(loginUri.getPath())) {
                        //we got this far.. only the method (GET/POST), user details, query params, fragment, and POST params
                        //are possibly different from the login page.
                        loginUrl = true;
                        //DEBUG only
                        //log.debug("##### The right login page was found");
                        break;
                    } else {
                        //log.debug("#### This is not the login page you're looking for");
                    }
                } else {
                    //log.debug("### This context has no login page set");
                }
            }
            if (loginUrl) {
                //log.debug("##### Raising auth bypass");
                //raise the alert, using the custom name and description
                String vulnname = Constant.messages.getString("ascanrules.sqlinjection.authbypass.name");
                String vulndesc = Constant.messages.getString("ascanrules.sqlinjection.authbypass.desc");

                //raise the alert, using the attack string stored earlier for this purpose
                bingo(Alert.RISK_HIGH, Alert.WARNING, vulnname, vulndesc,
                        refreshedmessage.getRequestHeader().getURI().getURI(), //url
                        param, sqlInjectionAttack, "", getSolution(), getBaseMsg());

            } //not a login page
        } //no sql Injection Found For Url

    } catch (Exception e) {
        //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("An error occurred checking a url for SQL Injection vulnerabilities", e);
    }
}

From source file:davmail.exchange.ExchangeSession.java

protected String getAbsoluteUri(HttpMethod method, String path) throws URIException {
    URI uri = method.getURI();
    if (path != null) {
        // reset query string
        uri.setQuery(null);/*from   w w w . ja  v  a  2 s  . c o  m*/
        if (path.startsWith("/")) {
            // path is absolute, replace method path
            uri.setPath(path);
        } else if (path.startsWith("http://") || path.startsWith("https://")) {
            return path;
        } else {
            // relative path, build new path
            String currentPath = method.getPath();
            int end = currentPath.lastIndexOf('/');
            if (end >= 0) {
                uri.setPath(currentPath.substring(0, end + 1) + path);
            } else {
                throw new URIException(uri.getURI());
            }
        }
    }
    return uri.getURI();
}

From source file:davmail.exchange.ExchangeSession.java

protected String getScriptBasedFormURL(HttpMethod initmethod, String pathQuery) throws URIException {
    URI initmethodURI = initmethod.getURI();
    int queryIndex = pathQuery.indexOf('?');
    if (queryIndex >= 0) {
        if (queryIndex > 0) {
            // update path
            String newPath = pathQuery.substring(0, queryIndex);
            if (newPath.startsWith("/")) {
                // absolute path
                initmethodURI.setPath(newPath);
            } else {
                String currentPath = initmethodURI.getPath();
                int folderIndex = currentPath.lastIndexOf('/');
                if (folderIndex >= 0) {
                    // replace relative path
                    initmethodURI.setPath(currentPath.substring(0, folderIndex + 1) + newPath);
                } else {
                    // should not happen
                    initmethodURI.setPath('/' + newPath);
                }/*from  ww  w. j a v  a  2s .c  o m*/
            }
        }
        initmethodURI.setQuery(pathQuery.substring(queryIndex + 1));
    }
    return initmethodURI.getURI();
}

From source file:nl.nn.adapterframework.util.SsoUtil.java

public static void addSsoCredential(HttpMethod method, HttpState state, String defaultForwardHost) {
    try {/*  ww  w.jav a  2 s.co  m*/
        String name = SsoUtil.getSsoTokenName();
        String value = SsoUtil.getSsoToken();
        if (StringUtils.isEmpty(value)) {
            if (log.isDebugEnabled())
                log.debug("no value for SsoCredential [" + name + "]");
        } else {
            if (log.isDebugEnabled())
                log.debug("constructing SsoCredentialCookie [" + name + "]");
            Cookie ssoCookie = new Cookie();
            ssoCookie.setName(name);

            ssoCookie.setValue(value);
            String forwardHost;
            try {
                URI uri = method.getURI();
                forwardHost = uri.getHost();
                if (StringUtils.isEmpty(forwardHost)) {
                    if (log.isDebugEnabled())
                        log.debug("did not find host from URI [" + uri.getURI() + "], will use default ["
                                + defaultForwardHost + "] for SSO credential cookie");
                    forwardHost = defaultForwardHost;
                }
            } catch (Throwable t) {
                log.warn("could not extract host from URI", t);
                forwardHost = defaultForwardHost;
            }
            ssoCookie.setDomain(forwardHost);
            // path must have a value, otherwise cookie is not appended to request
            ssoCookie.setPath("/");
            if (log.isDebugEnabled())
                log.debug("set SSOcookie attributes: domain [" + ssoCookie.getDomain() + "] path ["
                        + ssoCookie.getPath() + "]");
            state.addCookie(ssoCookie);
        }

    } catch (Exception e) {
        log.warn("could not obtain SsoToken: " + e.getMessage());
    }
}

From source file:org.andrewberman.sync.InheritMe.java

static String relativeToAbsoluteURL(String base, String href) throws Exception {
    //      System.out.println(href);
    href = StringEscapeUtils.unescapeHtml(href);
    //      System.out.println(href);
    href = urlEncoder.decode(href);// w  w w. j ava2s .c  om
    //      System.out.println(href);

    base = StringEscapeUtils.unescapeHtml(base);
    base = urlEncoder.decode(base);

    URI baseURI = new URI(base, false);
    URI childURI = new URI(baseURI, href, false);

    //      System.out.println(childURI.toString());
    return childURI.getURI();
    // return childURI.toString();
}

From source file:org.glite.slcs.shibclient.ShibbolethClient.java

/**
 * Authenticates the user on his IdP for the given SP.
 * /*from   w w w .  j  ava 2  s.  c om*/
 * @param spEntryURL
 *            The Service Provider entry point URL
 * @return <code>true</code> iff the user have been authenticated by his
 *         Identity Provider.
 * @throws AuthException
 * @throws RemoteException
 * @throws ServiceException
 * @throws UnknownResourceException
 */
public boolean authenticate(String spEntryURL)
        throws AuthException, RemoteException, ServiceException, UnknownResourceException {

    String idpProviderID = credentials_.getIdentityProviderID();
    IdentityProvider idp = metadata_.getIdentityProvider(idpProviderID);
    if (idp == null) {
        throw new UnknownResourceException("IdP " + idpProviderID + " not found in Metadata");
    }
    LOG.info(spEntryURL + " IdP=" + idp.getUrl() + " AuthType=" + idp.getAuthTypeName());
    try {
        URI idpSSOResponseURI = null;

        // 1. get the first redirection, or the SAML2 DS response, or the
        // same
        // (already authN)
        URI spLoginResponseURI = processSPEntry(spEntryURL, idp);
        // either wayf or idp or same (already authenticated)
        String spLoginResponseURL = spLoginResponseURI.getEscapedURI();
        LOG.debug("spLoginResponseURL=" + spLoginResponseURL);
        // check if already authenticated (multiple call to authenticate)
        if (spLoginResponseURL.startsWith(spEntryURL)) {
            LOG.info("Already authenticated? " + isAuthenticated_ + ": " + spLoginResponseURL);
            return this.isAuthenticated_;
        }

        // 2. process the IdP SSO login
        idpSSOResponseURI = processIdPSSO(idp, spLoginResponseURI);

        // 3. process the IdP SSO response -> Artifact or Browser/POST
        // profile
        URI idpResponseURI = processIdPSSOResponse(idp, idpSSOResponseURI);
        String url = idpResponseURI.getURI();
        if (url.equals(spEntryURL)) {
            this.isAuthenticated_ = true;
            LOG.info("Sucessful authentication");
        }

    } catch (URIException e) {
        LOG.error("URIException: " + e);
        e.printStackTrace();
    } catch (HttpException e) {
        LOG.error("HttpException: " + e);
        e.printStackTrace();
    } catch (IOException e) {
        LOG.error("IOException: " + e);
        e.printStackTrace();
        throw new RemoteException(e);
    }
    return this.isAuthenticated_;
}