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

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

Introduction

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

Prototype

@Override
public String toString() 

Source Link

Document

Get the escaped URI string.

Usage

From source file:org.zaproxy.zap.extension.alert.PopupMenuShowAlerts.java

@Override
public boolean isButtonEnabledForHistoryReference(HistoryReference href) {
    List<Alert> alerts = href.getAlerts();
    if (href.getSiteNode() != null) {
        alerts = href.getSiteNode().getAlerts();
    }// w w w  . j ava2  s . c o  m
    URI hrefURI = href.getURI();
    List<PopupMenuShowAlert> alertList = new ArrayList<>(alerts.size());
    for (Alert alert : alerts) {
        // Just show ones for this node
        if (hrefURI != null && !alert.getUri().equals(hrefURI.toString())) {
            continue;
        }
        final PopupMenuShowAlert menuItem = new PopupMenuShowAlert(alert.getAlert(), alert);
        menuItem.setIcon(new ImageIcon(alert.getIconUrl()));

        alertList.add(menuItem);
    }
    Collections.sort(alertList);

    for (PopupMenuShowAlert pmsa : alertList) {
        this.add(pmsa);
    }

    return (alertList.size() > 0);
}

From source file:org.zaproxy.zap.extension.ascanrules.TestDirectoryBrowsing.java

private void checkIfDirectory(HttpMessage msg) throws URIException {

    URI uri = msg.getRequestHeader().getURI();
    uri.setQuery(null);//  w  ww. j a  v a  2s .c  o m
    String sUri = uri.toString();
    if (!sUri.endsWith("/")) {
        sUri = sUri + "/";
    }
    msg.getRequestHeader().setURI(new URI(sUri, true));
}

From source file:org.zaproxy.zap.extension.ascanrulesBeta.UsernameEnumeration.java

/**
 * looks for username enumeration in the login page, by changing the username field to be a
 * valid / invalid user, and looking for differences in the response
 */// w  w  w . java 2  s .  c om
@Override
public void scan() {

    // the technique to determine if usernames can be enumerated is as follows, using a variant
    // of the Freiling+Schinzel method,
    // adapted to the case where we do not know which is the username field
    //
    // 1) Request the original URL n times. (The original URL is assumed to have a valid
    // username, if not a valid password). Store the results in A[].
    // 2) Compute the longest common subsequence (LCS) of A[] into LCS_A
    // 3) for each parameter in the original URL (ie, for URL params, form params, and cookie
    // params)
    //   4) Change the current parameter (which we assume is the username parameter) to an invalid
    // username (randomly), and request the URL n times. Store the results in B[].
    //   5) Compute the longest common subsequence (LCS) of B[] into LCS_B
    //   6) If LCS_A <> LCS_B, then there is a Username Enumeration issue on the current parameter

    try {
        boolean loginUrl = false;

        // Are we dealing with a login url in any of the contexts of which this uri is part
        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) {
            URI loginUri = extAuth.getLoginRequestURIForContext(context);
            if (loginUri != null) {
                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;
                    log.info(requestUri.toString()
                            + " falls within a context, and is the defined Login URL. Scanning for possible Username Enumeration vulnerability.");
                    break; // Stop checking
                }
            }
        }

        // the Username Enumeration scanner will only run for logon pages
        if (loginUrl == false) {
            if (this.debugEnabled) {
                log.debug(requestUri.toString() + " is not a defined Login URL.");
            }
            return; // No need to continue for this URL
        }

        // find all params set in the request (GET/POST/Cookie)
        TreeSet<HtmlParameter> htmlParams = new TreeSet<>();
        htmlParams.addAll(getBaseMsg().getRequestHeader().getCookieParams()); // request cookies only. no response cookies
        htmlParams.addAll(getBaseMsg().getFormParams()); // add in the POST params
        htmlParams.addAll(getBaseMsg().getUrlParams()); // add in the GET params

        int numberOfRequests = 0;
        if (this.getAttackStrength() == AttackStrength.INSANE) {
            numberOfRequests = 50;
        } else if (this.getAttackStrength() == AttackStrength.HIGH) {
            numberOfRequests = 15;
        } else if (this.getAttackStrength() == AttackStrength.MEDIUM) {
            numberOfRequests = 5;
        } else if (this.getAttackStrength() == AttackStrength.LOW) {
            numberOfRequests = 3;
        }

        // 1) Request the original URL n times. (The original URL is assumed to have a valid
        // username, if not a valid password). Store the results in A[].
        // make sure to manually handle all redirects, and cookies that may be set in response.
        // allocate enough space for the responses

        StringBuilder responseA = null;
        StringBuilder responseB = null;
        String longestCommonSubstringA = null;
        String longestCommonSubstringB = null;

        for (int i = 0; i < numberOfRequests; i++) {

            // initialise the storage for this iteration
            // baseResponses[i]= new StringBuilder(250);
            responseA = new StringBuilder(250);

            HttpMessage msgCpy = getNewMsg(); // clone the request, but not the response

            sendAndReceive(msgCpy, false, false); // request the URL, but do not automatically follow redirects.

            // get all cookies set in the response
            TreeSet<HtmlParameter> cookies = msgCpy.getResponseHeader().getCookieParams();

            int redirectCount = 0;
            while (HttpStatusCode.isRedirection(msgCpy.getResponseHeader().getStatusCode())) {
                redirectCount++;

                if (this.debugEnabled)
                    log.debug("Following redirect " + redirectCount + " for message " + i + " of "
                            + numberOfRequests + " iterations of the original query");

                // append the response to the responses so far for this particular instance
                // this will give us a complete picture of the full set of actual traffic
                // associated with following redirects for the request
                responseA.append(msgCpy.getResponseHeader().getHeadersAsString());
                responseA.append(msgCpy.getResponseBody().toString());

                // and manually follow the redirect
                // create a new message from scratch
                HttpMessage msgRedirect = new HttpMessage();

                // create a new URI from the absolute location returned, and interpret it as
                // escaped
                // note that the standard says that the Location returned should be absolute,
                // but it ain't always so...
                URI newLocation = new URI(msgCpy.getResponseHeader().getHeader(HttpHeader.LOCATION), true);
                try {
                    msgRedirect.getRequestHeader().setURI(newLocation);
                } catch (Exception e) {
                    // the Location field contents may not be standards compliant. Lets generate
                    // a uri to use as a workaround where a relative path was
                    // given instead of an absolute one
                    URI newLocationWorkaround = new URI(msgCpy.getRequestHeader().getURI(),
                            msgCpy.getResponseHeader().getHeader(HttpHeader.LOCATION), true);
                    // try again, except this time, if it fails, don't try to handle it
                    if (this.debugEnabled)
                        log.debug("The Location [" + newLocation
                                + "] specified in a redirect was not valid (not absolute?). Trying absolute workaround url ["
                                + newLocationWorkaround + "]");
                    msgRedirect.getRequestHeader().setURI(newLocationWorkaround);
                }
                msgRedirect.getRequestHeader().setMethod(HttpRequestHeader.GET); // it's always a GET for a redirect
                msgRedirect.getRequestHeader().setContentLength(0); // since we send a GET, the body will be 0 long
                if (cookies.size() > 0) {
                    // if a previous request sent back a cookie that has not since been
                    // invalidated, we need to set that cookie when following redirects, as a
                    // browser would
                    msgRedirect.getRequestHeader().setCookieParams(cookies);
                }

                if (this.debugEnabled)
                    log.debug("DEBUG: Following redirect to [" + newLocation + "]");
                sendAndReceive(msgRedirect, false, false); // do NOT redirect.. handle it here

                // handle scenario where a cookie is unset in a subsequent iteration, or where
                // the same cookie name is later re-assigned a different value
                // ie, in these cases, do not simply (and dumbly) accumulate cookie detritus.
                // first get all cookies set in the response
                TreeSet<HtmlParameter> cookiesTemp = msgRedirect.getResponseHeader().getCookieParams();
                for (Iterator<HtmlParameter> redirectSetsCookieIterator = cookiesTemp
                        .iterator(); redirectSetsCookieIterator.hasNext();) {
                    HtmlParameter cookieJustSet = redirectSetsCookieIterator.next();
                    // loop through each of the cookies we know about in cookies, to see if it
                    // matches by name.
                    // if so, delete that cookie, and add the one that was just set to cookies.
                    // if not, add the one that was just set to cookies.
                    for (Iterator<HtmlParameter> knownCookiesIterator = cookies.iterator(); knownCookiesIterator
                            .hasNext();) {
                        HtmlParameter knownCookie = knownCookiesIterator.next();
                        if (cookieJustSet.getName().equals(knownCookie.getName())) {
                            knownCookiesIterator.remove();
                            break; // out of the loop for known cookies, back to the next cookie
                            // set in the response
                        }
                    } // end of loop for cookies we already know about
                      // we can now safely add the cookie that was just set into cookies, knowing
                      // it does not clash with anything else in there.
                    cookies.add(cookieJustSet);
                } // end of for loop for cookies just set in the redirect

                msgCpy = msgRedirect; // store the last redirect message into the MsgCpy, as we
                // will be using it's output in a moment..
            } // end of loop to follow redirects

            // now that the redirections have all been handled.. was the request finally a
            // success or not?  Successful or Failed Logins would normally both return an OK
            // HTTP status
            if (!HttpStatusCode.isSuccess(msgCpy.getResponseHeader().getStatusCode())) {
                log.warn("The original URL [" + getBaseMsg().getRequestHeader().getURI()
                        + "] returned a non-OK HTTP status " + msgCpy.getResponseHeader().getStatusCode()
                        + " (after " + i + " of " + numberOfRequests
                        + " steps). Could be indicative of SQL Injection, or some other error. The URL is not stable enough to look at Username Enumeration");
                return; // we have not even got as far as looking at the parameters, so just
                // abort straight out of the method
            }

            if (this.debugEnabled)
                log.debug("Done following redirects!");

            // append the response to the responses so far for this particular instance
            // this will give us a complete picture of the full set of actual traffic associated
            // with following redirects for the request
            responseA.append(msgCpy.getResponseHeader().getHeadersAsString());
            responseA.append(msgCpy.getResponseBody().toString());

            // 2) Compute the longest common subsequence (LCS) of A[] into LCS_A
            // Note: in the Freiling and Schinzel method, this is calculated recursively. We
            // calculate it iteratively, but using an equivalent method

            // first time in, the LCS is simple: it's the first HTML result.. no diffing
            // required
            if (i == 0)
                longestCommonSubstringA = responseA.toString();
            // else get the LCS of the existing string, and the current result
            else
                longestCommonSubstringA = this.longestCommonSubsequence(longestCommonSubstringA,
                        responseA.toString());

            // optimisation step: if the LCS of A is 0 characters long already, then the URL
            // output is not stable, and we can abort now, and save some time
            if (longestCommonSubstringA.length() == 0) {
                // this might occur if the output returned for the URL changed mid-way. Perhaps
                // a CAPTCHA has fired, or a WAF has kicked in.  Let's abort now so.
                log.warn("The original URL [" + getBaseMsg().getRequestHeader().getURI()
                        + "] does not produce stable output (at " + i + 1 + " of " + numberOfRequests
                        + " steps). There is no static element in the output that can be used as a basis of comparison for the result of requesting URLs with the parameter values modified. Perhaps a CAPTCHA or WAF has kicked in!!");
                return; // we have not even got as far as looking at the parameters, so just
                // abort straight out of the method
            }
        }
        // get rid of any remnants of cookie setting and Date headers in the responses, as these
        // cause false positives, and can be safely ignored
        // replace the content length with a non-variable placeholder
        // replace url parameters with a non-variable placeholder to eliminate tokens in URLs in
        // the output
        longestCommonSubstringA = longestCommonSubstringA.replaceAll("Set-Cookie:[^\\r\\n]+[\\r\\n]{1,2}", "");
        longestCommonSubstringA = longestCommonSubstringA.replaceAll("Date:[^\\r\\n]+[\\r\\n]{1,2}", "");
        longestCommonSubstringA = longestCommonSubstringA.replaceAll("Content-Length:[^\\r\\n]+[\\r\\n]{1,2}",
                "Content-Length: XXXX\n");
        longestCommonSubstringA = longestCommonSubstringA
                .replaceAll("(?<=(&amp;|\\?)[^\\?\"=&;]+=)[^\\?\"=&;]+(?=(&amp;|\"))", "YYYY");

        if (this.debugEnabled)
            log.debug("The LCS of A is [" + longestCommonSubstringA + "]");

        // 3) for each parameter in the original URL (ie, for URL params, form params, and
        // cookie params)
        for (Iterator<HtmlParameter> iter = htmlParams.iterator(); iter.hasNext();) {

            HttpMessage msgModifiedParam = getNewMsg();
            HtmlParameter currentHtmlParameter = iter.next();

            if (this.debugEnabled)
                log.debug("Handling [" + currentHtmlParameter.getType() + "] parameter ["
                        + currentHtmlParameter.getName() + "], with value [" + currentHtmlParameter.getValue()
                        + "]");

            // 4) Change the current parameter value (which we assume is the username parameter)
            // to an invalid username (randomly), and request the URL n times. Store the results
            // in B[].

            // get a random user name the same length as the original!
            String invalidUsername = RandomStringUtils.random(currentHtmlParameter.getValue().length(),
                    RANDOM_USERNAME_CHARS);
            if (this.debugEnabled)
                log.debug("The invalid username chosen was [" + invalidUsername + "]");

            TreeSet<HtmlParameter> requestParams = null;
            if (currentHtmlParameter.getType().equals(HtmlParameter.Type.cookie)) {
                requestParams = msgModifiedParam.getRequestHeader().getCookieParams();
                requestParams.remove(currentHtmlParameter);
                requestParams.add(new HtmlParameter(currentHtmlParameter.getType(),
                        currentHtmlParameter.getName(), invalidUsername.toString())); // add in the invalid username
                msgModifiedParam.setCookieParams(requestParams);
            } else if (currentHtmlParameter.getType().equals(HtmlParameter.Type.url)) {
                requestParams = msgModifiedParam.getUrlParams();
                requestParams.remove(currentHtmlParameter);
                requestParams.add(new HtmlParameter(currentHtmlParameter.getType(),
                        currentHtmlParameter.getName(), invalidUsername.toString())); // add in the invalid username
                msgModifiedParam.setGetParams(requestParams);
            } else if (currentHtmlParameter.getType().equals(HtmlParameter.Type.form)) {
                requestParams = msgModifiedParam.getFormParams();
                requestParams.remove(currentHtmlParameter);
                requestParams.add(new HtmlParameter(currentHtmlParameter.getType(),
                        currentHtmlParameter.getName(), invalidUsername.toString())); // add in the invalid username
                msgModifiedParam.setFormParams(requestParams);
            }

            if (this.debugEnabled)
                log.debug("About to loop for " + numberOfRequests
                        + " iterations with an incorrect user of the same length");

            boolean continueForParameter = true;
            for (int i = 0; i < numberOfRequests && continueForParameter; i++) {

                // initialise the storage for this iteration
                responseB = new StringBuilder(250);

                HttpMessage msgCpy = msgModifiedParam; // use the message we already set up, with the
                // modified parameter value

                sendAndReceive(msgCpy, false, false); // request the URL, but do not automatically follow redirects.

                // get all cookies set in the response
                TreeSet<HtmlParameter> cookies = msgCpy.getResponseHeader().getCookieParams();

                int redirectCount = 0;
                while (HttpStatusCode.isRedirection(msgCpy.getResponseHeader().getStatusCode())) {
                    redirectCount++;

                    if (this.debugEnabled)
                        log.debug("Following redirect " + redirectCount + " for message " + i + " of "
                                + numberOfRequests + " iterations of the modified query");

                    // append the response to the responses so far for this particular instance
                    // this will give us a complete picture of the full set of actual traffic
                    // associated with following redirects for the request
                    responseB.append(msgCpy.getResponseHeader().getHeadersAsString());
                    responseB.append(msgCpy.getResponseBody().toString());

                    // and manually follow the redirect
                    // create a new message from scratch
                    HttpMessage msgRedirect = new HttpMessage();

                    // create a new URI from the absolute location returned, and interpret it as
                    // escaped
                    // note that the standard says that the Location returned should be
                    // absolute, but it ain't always so...
                    URI newLocation = new URI(msgCpy.getResponseHeader().getHeader(HttpHeader.LOCATION), true);
                    try {
                        msgRedirect.getRequestHeader().setURI(newLocation);
                    } catch (Exception e) {
                        // the Location field contents may not be standards compliant. Lets
                        // generate a uri to use as a workaround where a relative path was
                        // given instead of an absolute one
                        URI newLocationWorkaround = new URI(msgCpy.getRequestHeader().getURI(),
                                msgCpy.getResponseHeader().getHeader(HttpHeader.LOCATION), true);
                        // try again, except this time, if it fails, don't try to handle it
                        if (this.debugEnabled)
                            log.debug("The Location [" + newLocation
                                    + "] specified in a redirect was not valid (not absolute?). Trying absolute workaround url ["
                                    + newLocationWorkaround + "]");
                        msgRedirect.getRequestHeader().setURI(newLocationWorkaround);
                    }
                    msgRedirect.getRequestHeader().setMethod(HttpRequestHeader.GET); // it's always a GET for a redirect
                    msgRedirect.getRequestHeader().setContentLength(0); // since we send a GET, the body will be 0 long
                    if (cookies.size() > 0) {
                        // if a previous request sent back a cookie that has not since been
                        // invalidated, we need to set that cookie when following redirects, as
                        // a browser would
                        msgRedirect.getRequestHeader().setCookieParams(cookies);
                    }

                    sendAndReceive(msgRedirect, false, false); // do NOT redirect.. handle it here

                    // handle scenario where a cookie is unset in a subsequent iteration, or
                    // where the same cookie name is later re-assigned a different value
                    // ie, in these cases, do not simply (and dumbly) accumulate cookie
                    // detritus.
                    // first get all cookies set in the response
                    TreeSet<HtmlParameter> cookiesTemp = msgRedirect.getResponseHeader().getCookieParams();
                    for (Iterator<HtmlParameter> redirectSetsCookieIterator = cookiesTemp
                            .iterator(); redirectSetsCookieIterator.hasNext();) {
                        HtmlParameter cookieJustSet = redirectSetsCookieIterator.next();
                        // loop through each of the cookies we know about in cookies, to see if
                        // it matches by name.
                        // if so, delete that cookie, and add the one that was just set to
                        // cookies.
                        // if not, add the one that was just set to cookies.
                        for (Iterator<HtmlParameter> knownCookiesIterator = cookies
                                .iterator(); knownCookiesIterator.hasNext();) {
                            HtmlParameter knownCookie = knownCookiesIterator.next();
                            if (cookieJustSet.getName().equals(knownCookie.getName())) {
                                knownCookiesIterator.remove();
                                break; // out of the loop for known cookies, back to the next
                                // cookie set in the response
                            }
                        } // end of loop for cookies we already know about
                          // we can now safely add the cookie that was just set into cookies,
                          // knowing it does not clash with anything else in there.
                        cookies.add(cookieJustSet);
                    } // end of for loop for cookies just set in the redirect

                    msgCpy = msgRedirect; // store the last redirect message into the MsgCpy, as
                    // we will be using it's output in a moment..
                } // end of loop to follow redirects

                // now that the redirections have all been handled.. was the request finally a
                // success or not?  Successful or Failed Logins would normally both return an OK
                // HTTP status
                if (!HttpStatusCode.isSuccess(msgCpy.getResponseHeader().getStatusCode())) {
                    log.warn("The modified URL [" + msgModifiedParam.getRequestHeader().getURI()
                            + "] returned a non-OK HTTP status " + msgCpy.getResponseHeader().getStatusCode()
                            + " (after " + i + 1 + " of " + numberOfRequests + " steps for ["
                            + currentHtmlParameter.getType() + "] parameter " + currentHtmlParameter.getName()
                            + "). Could be indicative of SQL Injection, or some other error. The URL is not stable enough to look at Username Enumeration");
                    continueForParameter = false;
                    continue; // skip directly to the next parameter. Do not pass Go. Do not
                    // collect $200.
                }

                if (this.debugEnabled)
                    log.debug("Done following redirects!");

                // append the response to the responses so far for this particular instance
                // this will give us a complete picture of the full set of actual traffic
                // associated with following redirects for the request
                responseB.append(msgCpy.getResponseHeader().getHeadersAsString());
                responseB.append(msgCpy.getResponseBody().toString());

                // 5) Compute the longest common subsequence (LCS) of B[] into LCS_B
                // Note: in the Freiling and Schinzel method, this is calculated recursively. We
                // calculate it iteratively, but using an equivalent method

                // first time in, the LCS is simple: it's the first HTML result.. no diffing
                // required
                if (i == 0)
                    longestCommonSubstringB = responseB.toString();
                // else get the LCS of the existing string, and the current result
                else
                    longestCommonSubstringB = this.longestCommonSubsequence(longestCommonSubstringB,
                            responseB.toString());

                // optimisation step: if the LCS of B is 0 characters long already, then the URL
                // output is not stable, and we can abort now, and save some time
                if (longestCommonSubstringB.length() == 0) {
                    // this might occur if the output returned for the URL changed mid-way.
                    // Perhaps a CAPTCHA has fired, or a WAF has kicked in.  Let's abort now so.
                    log.warn("The modified URL [" + msgModifiedParam.getRequestHeader().getURI() + "] (for ["
                            + currentHtmlParameter.getType() + "] parameter " + currentHtmlParameter.getName()
                            + ") does not produce stable output (after " + i + 1 + " of " + numberOfRequests
                            + " steps). There is no static element in the output that can be used as a basis of comparison with the static output of the original query. Perhaps a CAPTCHA or WAF has kicked in!!");
                    continueForParameter = false;
                    continue; // skip directly to the next parameter. Do not pass Go. Do not
                    // collect $200.
                    // Note: if a CAPTCHA or WAF really has fired, the results of subsequent
                    // iterations will likely not be accurate..
                }
            }

            // if we didn't hit something with one of the iterations for the parameter (ie, if
            // the output when changing the parm is stable),
            // check if the parameter might be vulnerable by comparins its LCS with the original
            // LCS for a valid login
            if (continueForParameter == true) {
                // get rid of any remnants of cookie setting and Date headers in the responses,
                // as these cause false positives, and can be safely ignored
                // replace the content length with a non-variable placeholder
                // replace url parameters with a non-variable placeholder to eliminate tokens in
                // URLs in the output
                longestCommonSubstringB = longestCommonSubstringB
                        .replaceAll("Set-Cookie:[^\\r\\n]+[\\r\\n]{1,2}", "");
                longestCommonSubstringB = longestCommonSubstringB.replaceAll("Date:[^\\r\\n]+[\\r\\n]{1,2}",
                        "");
                longestCommonSubstringB = longestCommonSubstringB
                        .replaceAll("Content-Length:[^\\r\\n]+[\\r\\n]{1,2}", "Content-Length: XXXX\n");
                longestCommonSubstringB = longestCommonSubstringB
                        .replaceAll("(?<=(&amp;|\\?)[^\\?\"=&;]+=)[^\\?\"=&;]+(?=(&amp;|\"))", "YYYY");

                if (this.debugEnabled)
                    log.debug("The LCS of B is [" + longestCommonSubstringB + "]");

                // 6) If LCS_A <> LCS_B, then there is a Username Enumeration issue on the
                // current parameter
                if (!longestCommonSubstringA.equals(longestCommonSubstringB)) {
                    // calculate line level diffs of the 2 Longest Common Substrings to aid the
                    // user in deciding if the match is a false positive
                    // get the diff as a series of patches
                    Patch diffpatch = DiffUtils.diff(
                            new LinkedList<String>(Arrays.asList(longestCommonSubstringA.split("\\n"))),
                            new LinkedList<String>(Arrays.asList(longestCommonSubstringB.split("\\n"))));

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

                    // and convert the list of patches to a String, joining using a newline
                    // String diffAB = StringUtils.join(diffpatch.getDeltas(), "\n");
                    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 Valid Username  : " + delta.getOriginal() + "\n"); // no blank lines
                        tempDiff.append("\nOutput for Invalid Username: " + delta.getRevised() + "\n"); // blank line before
                    }
                    String diffAB = tempDiff.toString();
                    String extraInfo = Constant.messages.getString(
                            "ascanbeta.usernameenumeration.alert.extrainfo", currentHtmlParameter.getType(),
                            currentHtmlParameter.getName(), currentHtmlParameter.getValue(), // original value
                            invalidUsername.toString(), // new value
                            diffAB, // the differences between the two sets of output
                            numberofDifferences); // the number of differences
                    String attack = Constant.messages.getString("ascanbeta.usernameenumeration.alert.attack",
                            currentHtmlParameter.getType(), currentHtmlParameter.getName());
                    String vulnname = Constant.messages.getString("ascanbeta.usernameenumeration.name");
                    String vulndesc = Constant.messages.getString("ascanbeta.usernameenumeration.desc");
                    String vulnsoln = Constant.messages.getString("ascanbeta.usernameenumeration.soln");

                    // call bingo with some extra info, indicating that the alert is
                    bingo(Alert.RISK_INFO, Alert.CONFIDENCE_LOW, vulnname, vulndesc,
                            getBaseMsg().getRequestHeader().getURI().getURI(), currentHtmlParameter.getName(),
                            attack, extraInfo, vulnsoln, getBaseMsg());

                } else {
                    if (this.debugEnabled)
                        log.debug("[" + currentHtmlParameter.getType() + "] parameter ["
                                + currentHtmlParameter.getName()
                                + "] looks ok (Invalid Usernames cannot be distinguished from Valid usernames)");
                }
            }
        } // end of the for loop around the parameter list

    } 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 Username Enumeration issues", e);
    }
}

From source file:org.zaproxy.zap.extension.authstats.ExtensionAuthStats.java

@Override
public void onHttpResponseReceive(HttpMessage msg, int initiator, HttpSender sender) {
    String comp;/*from  w  w w.  j a  v  a  2  s.  c om*/
    switch (initiator) {
    case HttpSender.ACTIVE_SCANNER_INITIATOR:
        comp = "ascan";
        break;
    case HttpSender.AUTHENTICATION_INITIATOR:
        comp = "auth";
        break;
    case HttpSender.FUZZER_INITIATOR:
        comp = "fuzz";
        break;
    case HttpSender.MANUAL_REQUEST_INITIATOR:
        comp = "manual";
        break;
    case HttpSender.PROXY_INITIATOR:
        comp = "proxy";
        break;
    case HttpSender.SPIDER_INITIATOR:
        comp = "spider";
        break;
    default:
        comp = Integer.toString(initiator);
        break;
    }
    Session session = Model.getSingleton().getSession();
    URI uri = msg.getRequestHeader().getURI();
    try {
        String site = SessionStructure.getHostName(msg);
        for (Context context : session.getContexts()) {
            if (context.isInScope()) {
                if (context.isInContext(uri.toString())) {
                    String prefix = "stats.auth." + comp + ".state.";
                    if (!msg.getResponseHeader().isHtml()) {
                        // Record for info
                        Stats.incCounter(site, prefix + "nothtml");
                    } else if (!HttpStatusCode.isSuccess(msg.getResponseHeader().getStatusCode())) {
                        // Record for info
                        Stats.incCounter(site, prefix + "notsuccess");
                    } else {
                        updateAuthIndicatorStats(msg, site, prefix, context);
                    }
                }
            }
        }
    } catch (URIException e) {
        log.error(e.getMessage(), e);
    }
}

From source file:org.zaproxy.zap.extension.compare.ExtensionCompare.java

private void buildHistoryMap(TableHistory th, Map<String, String> map)
        throws DatabaseException, HttpMalformedHeaderException {

    // Get the first session id
    RecordHistory rh = null;/* w  w w .  j a va 2  s . c om*/
    for (int i = 0; i < 100; i++) {
        rh = th.read(i);
        if (rh != null) {
            break;
        }
    }
    if (rh == null) {
        return;
    }

    List<Integer> hIds = th.getHistoryIdsOfHistType(rh.getSessionId(), HistoryReference.TYPE_PROXIED,
            HistoryReference.TYPE_ZAP_USER);
    for (Integer hId : hIds) {
        RecordHistory recH = th.read(hId);
        URI uri = recH.getHttpMessage().getRequestHeader().getURI();
        String mapKey = recH.getHttpMessage().getRequestHeader().getMethod() + " " + uri.toString();

        // TODO Optionally strip off params?
        if (mapKey.indexOf("?") > -1) {
            mapKey = mapKey.substring(0, mapKey.indexOf("?"));
        }

        String val = map.get(mapKey);
        String code = recH.getHttpMessage().getResponseHeader().getStatusCode() + " ";
        if (val == null) {
            map.put(mapKey, code);
        } else if (val.indexOf(code) < 0) {
            map.put(mapKey, val + code);
        }
    }
}

From source file:org.zaproxy.zap.extension.imagelocationscanner.ImageLocationScanner.java

@Override
public void scanHttpResponseReceive(HttpMessage msg, int id, Source source) {
    long start = 0;
    if (logger.isDebugEnabled()) {
        start = System.currentTimeMillis();
    }/*w w w .j  a  va2  s  .c  o  m*/

    // Mnemonic: CT ==> Content-Type
    String CT = msg.getResponseHeader().getHeader("Content-Type");
    if (null == CT) {
        CT = "";
    } else {
        CT.toLowerCase();
    }

    URI uri = msg.getRequestHeader().getURI();
    String url = uri.toString();
    String fileName;
    try {
        fileName = uri.getName();
        if (fileName == null) {
            fileName = "";
        }
    } catch (URIException e) {
        // e.printStackTrace();
        // If we cannot decode the URL, then just set filename to empty.
        fileName = "";
    }
    String extension = "";
    int i = fileName.lastIndexOf('.');
    if (i > 0) {
        extension = fileName.substring(i + 1).toLowerCase();
    }

    if (logger.isDebugEnabled()) {
        logger.debug("\tCT: " + CT + " url: " + url + " fileName: " + fileName + " ext: " + extension);
    }

    // everything is already lowercase
    if (CT.startsWith("image/jpeg") || CT.startsWith("image/jpg") || extension.equals("jpeg")
            || extension.equals("jpg") || CT.startsWith("image/png") || extension.equals("png")
            || CT.startsWith("image/tiff") || extension.equals("tiff") || extension.equals("tif")) {

        String hasGPS = ILS.scanForLocationInImage(msg.getResponseBody().getBytes(), false);

        if (!hasGPS.isEmpty()) {
            Alert alert = new Alert(getPluginId(), Alert.RISK_INFO, Alert.CONFIDENCE_MEDIUM, getAlertTitle());
            alert.setDetail(getDescription(), url, "", // Param
                    "", // Attack
                    "", // Other info
                    getSolution(), getReference(), getAlertDetailPrefix() + " " + hasGPS, // Evidence
                    200, // CWE-200: Information Exposure
                    13, // WASC-13: Information Leakage
                    msg);

            parent.raiseAlert(id, alert);
        }

    }
    if (logger.isDebugEnabled()) {
        logger.debug("\tScan of record " + id + " took " + (System.currentTimeMillis() - start) + " ms");
    }
}

From source file:org.zaproxy.zap.extension.invoke.InvokeAppWorker.java

@Override
protected Void doInBackground() throws Exception {

    String url = ""; // Full URL
    String host = ""; // Just the server name, e.g. localhost
    String port = ""; // the port
    String site = ""; // e.g. http://localhost:8080/
    String postdata = ""; // only present in POST ops
    String cookie = ""; // from the request header
    HistoryReference historyRef = msg.getHistoryRef();
    int msgid = -1;

    if (historyRef != null) {
        msgid = historyRef.getHistoryId();
    }//from  www .  j a va  2s  . com

    URI uri = msg.getRequestHeader().getURI();
    url = uri.toString();
    host = uri.getHost();
    site = uri.getScheme() + "://" + uri.getHost();
    if (uri.getPort() > 0) {
        port = String.valueOf(uri.getPort());
        site = site + ":" + port + "/";
    } else {
        if (uri.getScheme().equalsIgnoreCase("http")) {
            port = "80";
        } else if (uri.getScheme().equalsIgnoreCase("https")) {
            port = "443";
        }
        site = site + "/";
    }
    if (msg.getRequestBody() != null) {
        postdata = msg.getRequestBody().toString();
        postdata = postdata.replaceAll("\n", "\\n");
    }
    Vector<String> cookies = msg.getRequestHeader().getHeaders(HttpHeader.COOKIE);
    if (cookies != null && cookies.size() > 0) {
        cookie = cookies.get(0);
    }

    List<String> cmd = new ArrayList<>();
    cmd.add(command);
    if (parameters != null) {
        for (String parameter : parameters.split(" ")) {
            // Replace all of the tags
            String finalParameter = parameter.replace("%url%", url).replace("%host%", host)
                    .replace("%port%", port).replace("%site%", site).replace("%cookie%", cookie)
                    .replace("%postdata%", postdata).replace("%msgid%", String.valueOf(msgid));

            // Replace header tags
            Matcher headers = Pattern.compile("%header-([A-z0-9_-]+)%").matcher(finalParameter);
            while (headers.find()) {
                String headerValue = msg.getRequestHeader().getHeader(headers.group(1));
                if (headerValue == null) {
                    headerValue = "";
                }
                finalParameter = finalParameter.replace(headers.group(0), headerValue);
            }

            cmd.add(finalParameter);
        }
    }

    logger.debug("Invoking: " + cmd.toString());
    View.getSingleton().getOutputPanel().append("\n" + cmd.toString() + "\n");
    ProcessBuilder pb = new ProcessBuilder(cmd);
    if (workingDir != null) {
        pb.directory(workingDir);
    }
    pb.redirectErrorStream(true);
    Process proc;
    try {
        proc = pb.start();
    } catch (final Exception e) {
        View.getSingleton().getOutputPanel()
                .append(Constant.messages.getString("invoke.error") + e.getLocalizedMessage() + "\n");
        logger.warn("Failed to start the process: " + e.getMessage(), e);
        return null;
    }

    if (captureOutput) {
        try (BufferedReader brOut = new BufferedReader(new InputStreamReader(proc.getInputStream()))) {
            String line;
            boolean isOutput = false;
            StringBuilder sb = new StringBuilder();
            if (msg.getNote() != null) {
                sb.append(msg.getNote());
                sb.append('\n');
            }

            // Show any stdout/error messages
            while ((line = brOut.readLine()) != null) {
                View.getSingleton().getOutputPanel().append(line + "\n");
                sb.append(line);
                sb.append('\n');
                isOutput = true;
            }
            if (isOutput) {
                // Somethings been written, switch to the Output tab
                View.getSingleton().getOutputPanel().setTabFocus();
            }

            if (outputNote) {
                HistoryReference hr = msg.getHistoryRef();
                if (hr != null) {
                    hr.setNote(sb.toString());
                }
            }
        }
    }

    return null;
}

From source file:org.zaproxy.zap.extension.plugnhack.MonitoredPagesManager.java

/**
 * Add a 'one time' URL - this URL is 'remembered' until we receive the first client message
 * from it//from   w  w  w.  j a  v  a 2 s . co  m
 *
 * @param uri
 */
public void setMonitorOnetimeURL(URI uri) {
    this.oneTimeURLs.add(uri.toString());
}

From source file:org.zaproxy.zap.extension.proxies.ExtensionProxies.java

private ProxyServer startProxyServer(ProxiesParamProxy param) {
    String address = param.getAddress();
    int port = param.getPort();
    String key = createProxyKey(address, port);
    log.info("Starting alt proxy server: " + key);
    ProxyServer proxyServer = new ProxyServer(ZAP_PROXY_THREAD_PREFIX + key) {

        @Override//w w  w . j a  va2s.c o  m
        public boolean excludeUrl(URI uri) {
            String uriString = uri.toString();
            for (String excludePattern : getModel().getOptionsParam().getGlobalExcludeURLParam()
                    .getTokensNames()) {
                if (uriString.matches(excludePattern)) {
                    return true;
                }
            }

            for (String excludePattern : getModel().getSession().getExcludeFromProxyRegexs()) {
                if (uriString.matches(excludePattern)) {
                    return true;
                }
            }
            return false;
        }
    };
    proxyServer.getProxyParam().load(new ZapXmlConfiguration());
    applyProxyOptions(param, proxyServer);
    proxyServer.setConnectionParam(getModel().getOptionsParam().getConnectionParam());
    // Note that if this is _not_ set then the proxy will go into a nasty loop if you point a browser at it
    proxyServer.setEnableApi(true);
    if (proxyServer.startServer(address, port, false) > 0) {
        Control.getSingleton().getExtensionLoader().getExtension(ExtensionHistory.class)
                .registerProxy(proxyServer);
    }
    return proxyServer;
}

From source file:org.zaproxy.zap.extension.pscanrules.CrossDomainScriptInclusionScanner.java

private boolean isScriptFromOtherDomain(String host, String scriptURL, HttpMessage msg) {
    if (!scriptURL.startsWith("//")
            && (scriptURL.startsWith("/") || scriptURL.startsWith("./") || scriptURL.startsWith("../"))) {
        return false;
    }//from   w  ww. j a  v a 2 s .  co m
    boolean otherDomain = false;
    try {
        URI scriptURI = new URI(scriptURL, true);
        String scriptURIStr = scriptURI.toString();
        String scriptHost = scriptURI.getHost();
        if (scriptHost != null && !scriptHost.toLowerCase().equals(host.toLowerCase())) {
            otherDomain = true;
        }
        if (otherDomain && !Plugin.AlertThreshold.LOW.equals(this.getAlertThreshold())) {
            // Get a list of contexts that contain the original URL
            List<Context> contextList = getModel().getSession()
                    .getContextsForUrl(msg.getRequestHeader().getURI().toString());
            for (Context context : contextList) {
                if (context.isInContext(scriptURIStr)) {
                    // The scriptURI is in a context that the original URI is in
                    // At MEDIUM and HIGH Threshold consider this an OK cross domain inclusion
                    return false; // No need to loop further
                }
            }
        }
    } catch (URIException e) {
        logger.debug("Error: " + e.getMessage());
    }
    return otherDomain;
}