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

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

Introduction

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

Prototype

public URI(String scheme, String userinfo, String host, int port, String path) throws URIException 

Source Link

Document

Construct a general URI from the given components.

Usage

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

/**
 * attempts to find a backup file for the given file
 *
 * @param uri the URI of a file/*from   w  w  w.java 2  s  .  co m*/
 * @return
 */
private void findBackupFile(HttpMessage originalMessage) throws Exception {

    try {
        boolean gives404s = true;
        boolean parentgives404s = true;
        byte[] nonexistparentmsgdata = null;

        URI originalURI = originalMessage.getRequestHeader().getURI();

        // request a file in the same directory to see how it handles "File not found". Using a
        // 404? Something else?
        String temppath = originalURI.getPath();
        if (temppath == null)
            temppath = "";
        int slashposition = temppath.lastIndexOf("/");
        if (slashposition < 0) {
            // WTF? there was no slash in the path..
            throw new Exception("The message has a path with a malformed path component");
        }
        String filename = originalMessage.getRequestHeader().getURI().getName();

        String randomfilename = RandomStringUtils.random(filename.length(),
                "abcdefghijklmoopqrstuvwxyz9123456789");
        String randomfilepath = temppath.substring(0, slashposition) + "/" + randomfilename;

        if (log.isDebugEnabled())
            log.debug("Trying non-existent file: " + randomfilepath);
        HttpMessage nonexistfilemsg = new HttpMessage(
                new URI(originalURI.getScheme(), originalURI.getAuthority(), randomfilepath, null, null));
        try {
            nonexistfilemsg.setCookieParams(originalMessage.getCookieParams());
        } catch (Exception e) {
            if (log.isDebugEnabled())
                log.debug("Could not set the cookies from the base request:" + e);
        }
        sendAndReceive(nonexistfilemsg, false);
        byte[] nonexistfilemsgdata = nonexistfilemsg.getResponseBody().getBytes();
        // does the server give a 404 for a non-existent file?
        if (nonexistfilemsg.getResponseHeader().getStatusCode() != HttpStatus.SC_NOT_FOUND) {
            gives404s = false;
            if (log.isDebugEnabled())
                log.debug("The server does not return a 404 status for a non-existent path: "
                        + nonexistfilemsg.getRequestHeader().getURI().getURI());
        } else {
            gives404s = true;
            if (log.isDebugEnabled())
                log.debug("The server gives a 404 status for a non-existent path: "
                        + nonexistfilemsg.getRequestHeader().getURI().getURI());
        }

        // now request a different (and non-existent) parent directory,
        // to see whether a non-existent parent folder causes a 404
        String[] pathbreak = temppath.split("/");
        HttpMessage nonexistparentmsg = null;
        if (pathbreak.length > 2) { // the file has a parent folder that is not the root folder (ie, there is
            // a parent folder to mess with)
            String[] temppathbreak = pathbreak;
            String parentfoldername = pathbreak[pathbreak.length - 2];
            String randomparentfoldername = RandomStringUtils.random(parentfoldername.length(),
                    "abcdefghijklmoopqrstuvwxyz9123456789");

            // replace the parent folder name with the random one, and build it back into a
            // string
            temppathbreak[pathbreak.length - 2] = randomparentfoldername;
            String randomparentpath = StringUtils.join(temppathbreak, "/");

            if (log.isDebugEnabled())
                log.debug("Trying non-existent parent path: " + randomparentpath);
            nonexistparentmsg = new HttpMessage(
                    new URI(originalURI.getScheme(), originalURI.getAuthority(), randomparentpath, null, null));
            try {
                nonexistparentmsg.setCookieParams(originalMessage.getCookieParams());
            } catch (Exception e) {
                if (log.isDebugEnabled())
                    log.debug("Could not set the cookies from the base request:" + e);
            }
            sendAndReceive(nonexistparentmsg, false);
            nonexistparentmsgdata = nonexistparentmsg.getResponseBody().getBytes();
            // does the server give a 404 for a non-existent parent folder?
            if (nonexistparentmsg.getResponseHeader().getStatusCode() != HttpStatus.SC_NOT_FOUND) {
                parentgives404s = false;
                if (log.isDebugEnabled())
                    log.debug("The server does not return a 404 status for a non-existent parent path: "
                            + nonexistparentmsg.getRequestHeader().getURI().getURI());
            } else {
                parentgives404s = true;
                if (log.isDebugEnabled())
                    log.debug("The server gives a 404 status for a non-existent parent path: "
                            + nonexistparentmsg.getRequestHeader().getURI().getURI());
            }
        }

        String actualfilename = originalURI.getName();
        String actualfileExtension = null;
        String path = originalURI.getPath();
        if (path == null)
            path = "";

        // record the position of the various injection points, always relative to the full path
        int positionExtensionInjection = 0;
        int positionFileSuffixInjection = 0;
        if (actualfilename.contains(".")) {
            positionExtensionInjection = path.lastIndexOf(".");
            positionFileSuffixInjection = positionExtensionInjection;
            actualfileExtension = actualfilename.substring(actualfilename.lastIndexOf("."));
        } else {
            positionExtensionInjection = path.length();
            positionFileSuffixInjection = path.length();
            actualfileExtension = "";
        }
        int positionFilePrefixInjection = path.lastIndexOf("/") + 1;
        int positionDirectorySuffixInjection = path.lastIndexOf("/");
        int positionDirectoryPrefixInjection = 0;
        if (positionDirectorySuffixInjection >= 0)
            positionDirectoryPrefixInjection = path.substring(0, positionDirectorySuffixInjection)
                    .lastIndexOf("/") + 1;

        // the set of files we will try, in the order of insertion
        Set<URI> candidateBackupFileURIs = new LinkedHashSet<URI>();
        Set<URI> candidateBackupFileChangedFolderURIs = new LinkedHashSet<URI>(); // for a changed parent folder name, which we need to handle
        // separately

        log.debug("The path is " + path);

        // for each file extension to try (both appending, and replacing)
        int counted = 0;
        for (String fileExtensionToTry : fileExtensions) {
            // to append, inject the file extension at the end of the path
            String candidateBackupFilePath = path + fileExtensionToTry;
            log.debug("File Extension (append): '" + candidateBackupFilePath + "'");
            candidateBackupFileURIs.add(new URI(originalURI.getScheme(), originalURI.getAuthority(),
                    candidateBackupFilePath, null, null));

            // to replace the extension, append the file extension at positionExtensionInjection
            candidateBackupFilePath = path.substring(0, positionExtensionInjection) + fileExtensionToTry;
            log.debug("File Extension (replace): '" + candidateBackupFilePath + "'");
            candidateBackupFileURIs.add(new URI(originalURI.getScheme(), originalURI.getAuthority(),
                    candidateBackupFilePath, null, null));

            // to switch the extension (if there was one), append the file extension at
            // positionExtensionInjection
            if (!actualfileExtension.equals("") && doSwitchFileExtension) {
                candidateBackupFilePath = path.substring(0, positionExtensionInjection) + fileExtensionToTry
                        + actualfileExtension;
                log.debug("File Extension (switch): '" + candidateBackupFilePath + "'");
                candidateBackupFileURIs.add(new URI(originalURI.getScheme(), originalURI.getAuthority(),
                        candidateBackupFilePath, null, null));
            }
            counted++;
            if (counted > numExtensionsToTry) {
                break; // out of the loop.
            }
        }

        // for each file suffix to try
        counted = 0;
        for (String fileSuffixToTry : fileSuffixes) {
            // inject the file suffix at positionFileSuffixInjection
            String candidateBackupFilePath = path.substring(0, positionFileSuffixInjection) + fileSuffixToTry
                    + (positionFileSuffixInjection >= path.length() ? ""
                            : path.substring(positionFileSuffixInjection));
            log.debug("File Suffix (insert): '" + candidateBackupFilePath + "'");
            candidateBackupFileURIs.add(new URI(originalURI.getScheme(), originalURI.getAuthority(),
                    candidateBackupFilePath, null, null));
            counted++;
            if (counted > numSuffixesToTry) {
                break; // out of the loop.
            }
        }

        // for each file prefix to try
        counted = 0;
        for (String filePrefixToTry : filePrefixes) {
            // inject the file prefix at positionFilePrefixInjection
            String candidateBackupFilePath = path.substring(0, positionFilePrefixInjection) + filePrefixToTry
                    + (positionFilePrefixInjection >= path.length() ? ""
                            : path.substring(positionFilePrefixInjection));
            log.debug("File Prefix (insert): '" + candidateBackupFilePath + "'");
            candidateBackupFileURIs.add(new URI(originalURI.getScheme(), originalURI.getAuthority(),
                    candidateBackupFilePath, null, null));
            counted++;
            if (counted > numPrefixesToTry) {
                break; // out of the loop.
            }
        }

        // for each directory suffix/prefix to try (using the file prefixes/suffixes - or
        // whatever the plural of prefix/suffix is)
        counted = 0;
        if (pathbreak.length > 2) {
            // if there is a a parent folder to play with
            for (String fileSuffixToTry : fileSuffixes) {
                // inject the directory suffix at positionDirectorySuffixInjection
                String candidateBackupFilePath = path.substring(0, positionDirectorySuffixInjection)
                        + fileSuffixToTry + (positionDirectorySuffixInjection >= path.length() ? ""
                                : path.substring(positionDirectorySuffixInjection));
                log.debug("Directory Suffix (insert): '" + candidateBackupFilePath + "'");
                candidateBackupFileChangedFolderURIs.add(new URI(originalURI.getScheme(),
                        originalURI.getAuthority(), candidateBackupFilePath, null, null));
                counted++;
                if (counted > numSuffixesToTry) {
                    break; // out of the loop.
                }
            }
            for (String filePrefixToTry : filePrefixes) {
                // inject the directory prefix at positionDirectorySuffixInjection
                String candidateBackupFilePath = path.substring(0, positionDirectoryPrefixInjection)
                        + filePrefixToTry + (positionDirectoryPrefixInjection >= path.length() ? ""
                                : path.substring(positionDirectoryPrefixInjection));
                log.debug("Directory Suffix (insert): '" + candidateBackupFilePath + "'");
                candidateBackupFileChangedFolderURIs.add(new URI(originalURI.getScheme(),
                        originalURI.getAuthority(), candidateBackupFilePath, null, null));
                counted++;
                if (counted > numSuffixesToTry) {
                    break; // out of the loop.
                }
            }
        }

        // now we have a set of candidate URIs appropriate to the attack strength chosen by the
        // user
        // try each candidate URI in turn.
        for (URI candidateBackupFileURI : candidateBackupFileURIs) {
            byte[] disclosedData = {};
            if (log.isDebugEnabled())
                log.debug("Trying possible backup file path: " + candidateBackupFileURI.getURI());
            HttpMessage requestmsg = new HttpMessage(candidateBackupFileURI);
            try {
                requestmsg.setCookieParams(originalMessage.getCookieParams());
            } catch (Exception e) {
                if (log.isDebugEnabled())
                    log.debug("Could not set the cookies from the base request:" + e);
            }
            // Do not follow redirects. They're evil. Yep.
            sendAndReceive(requestmsg, false);
            disclosedData = requestmsg.getResponseBody().getBytes();
            int requestStatusCode = requestmsg.getResponseHeader().getStatusCode();

            // just to complicate things.. I have a test case which for the random file, does
            // NOT give a 404 (so gives404s == false)
            // but for a "Copy of" file, actually gives a 404 (for some unknown reason). We need
            // to handle this case.
            if (!isEmptyResponse(disclosedData) && ((gives404s && requestStatusCode != HttpStatus.SC_NOT_FOUND)
                    || ((!gives404s) && nonexistfilemsg.getResponseHeader().getStatusCode() != requestStatusCode
                            && (!Arrays.equals(disclosedData, nonexistfilemsgdata))))) {
                bingo(Alert.RISK_MEDIUM, Alert.CONFIDENCE_MEDIUM,
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.name"),
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.desc"),
                        requestmsg.getRequestHeader().getURI().getURI(), // originalMessage.getRequestHeader().getURI().getURI(),
                        null, // parameter being attacked: none.
                        candidateBackupFileURI.getURI(), // attack
                        originalMessage.getRequestHeader().getURI().getURI(), // new String (disclosedData),  //extrainfo
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.soln"),
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.evidence", originalURI,
                                candidateBackupFileURI.getURI()),
                        requestmsg // originalMessage
                );
            }

            if (isStop()) {
                if (log.isDebugEnabled())
                    log.debug("The scanner was stopped in response to a user request");
                return;
            }
        }

        // now try the changed parent folders (if any)
        // the logic here needs to check using the parent 404 logic, and the output for a
        // non-existent parent folder.
        for (URI candidateBackupFileURI : candidateBackupFileChangedFolderURIs) {
            byte[] disclosedData = {};
            if (log.isDebugEnabled())
                log.debug("Trying possible backup file path (with changed parent folder): "
                        + candidateBackupFileURI.getURI());
            HttpMessage requestmsg = new HttpMessage(candidateBackupFileURI);
            try {
                requestmsg.setCookieParams(originalMessage.getCookieParams());
            } catch (Exception e) {
                if (log.isDebugEnabled())
                    log.debug("Could not set the cookies from the base request:" + e);
            }
            // Do not follow redirects. They're evil. Yep.
            sendAndReceive(requestmsg, false);
            disclosedData = requestmsg.getResponseBody().getBytes();
            int requestStatusCode = requestmsg.getResponseHeader().getStatusCode();
            // If the response is empty it's probably not really a backup

            if (!isEmptyResponse(disclosedData)
                    && ((parentgives404s && requestStatusCode != HttpStatus.SC_NOT_FOUND) || ((!parentgives404s)
                            && nonexistparentmsg.getResponseHeader().getStatusCode() != requestStatusCode
                            && (!Arrays.equals(disclosedData, nonexistparentmsgdata))))) {
                bingo(Alert.RISK_MEDIUM, Alert.CONFIDENCE_MEDIUM,
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.name"),
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.desc"),
                        requestmsg.getRequestHeader().getURI().getURI(), // originalMessage.getRequestHeader().getURI().getURI(),
                        null, // parameter being attacked: none.
                        candidateBackupFileURI.getURI(), // attack
                        originalMessage.getRequestHeader().getURI().getURI(), // new String (disclosedData),  //extrainfo
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.soln"),
                        Constant.messages.getString("ascanbeta.backupfiledisclosure.evidence", originalURI,
                                candidateBackupFileURI.getURI()),
                        requestmsg // originalMessage
                );
            }

            if (isStop()) {
                if (log.isDebugEnabled())
                    log.debug("The scanner was stopped in response to a user request");
                return;
            }
        }

    } catch (Exception e) {
        log.error("Some error occurred when looking for a backup file for '"
                + originalMessage.getRequestHeader().getURI(), e);
        return;
    }
}

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

private void scanAdobeCrossdomainPolicyFile(URI originalURI) throws IOException, XPathExpressionException {
    // retrieve the Adobe cross domain policy file, and assess it
    HttpMessage crossdomainmessage = new HttpMessage(new URI(originalURI.getScheme(),
            originalURI.getAuthority(), "/" + ADOBE_CROSS_DOMAIN_POLICY_FILE, null, null));
    sendAndReceive(crossdomainmessage, false);

    if (crossdomainmessage.getResponseBody().length() == 0) {
        return;/*from ww w .j  a va2 s . c o m*/
    }

    byte[] crossdomainmessagebytes = crossdomainmessage.getResponseBody().getBytes();

    // parse the file. If it's not parseable, it might have been because of a 404
    try {
        // work around the "no protocol" issue by wrapping the content in a ByteArrayInputStream
        Document adobeXmldoc = docBuilder
                .parse(new InputSource(new ByteArrayInputStream(crossdomainmessagebytes)));

        // check for cross domain read (data load) access
        XPathExpression exprAllowAccessFromDomain = xpath
                .compile("/cross-domain-policy/allow-access-from/@domain"); // gets the domain
        // attributes
        NodeList exprAllowAccessFromDomainNodes = (NodeList) exprAllowAccessFromDomain.evaluate(adobeXmldoc,
                XPathConstants.NODESET);
        for (int i = 0; i < exprAllowAccessFromDomainNodes.getLength(); i++) {
            String domain = exprAllowAccessFromDomainNodes.item(i).getNodeValue();
            if (domain.equals("*")) {
                // oh dear me.
                bingo(getRisk(), Alert.CONFIDENCE_MEDIUM,
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "name"),
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE + "desc"),
                        crossdomainmessage.getRequestHeader().getURI().getURI(), // the url field
                        "", // parameter being attacked: none.
                        "", // attack
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "extrainfo",
                                "/" + ADOBE_CROSS_DOMAIN_POLICY_FILE), // extrainfo
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE_READ + "soln"), // solution
                        "<allow-access-from domain=\"*\"", // evidence
                        crossdomainmessage // the message on which to place the alert
                );
            }
        }
        // check for cross domain send (upload) access
        XPathExpression exprRequestHeadersFromDomain = xpath
                .compile("/cross-domain-policy/allow-http-request-headers-from/@domain"); // gets
        // the
        // domain attributes
        NodeList exprRequestHeadersFromDomainNodes = (NodeList) exprRequestHeadersFromDomain
                .evaluate(adobeXmldoc, XPathConstants.NODESET);
        for (int i = 0; i < exprRequestHeadersFromDomainNodes.getLength(); i++) {
            String domain = exprRequestHeadersFromDomainNodes.item(i).getNodeValue();
            if (domain.equals("*")) {
                // oh dear, dear me.
                bingo(getRisk(), Alert.CONFIDENCE_MEDIUM,
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "name"),
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE + "desc"),
                        crossdomainmessage.getRequestHeader().getURI().getURI(), // the url field
                        "", // parameter being attacked: none.
                        "", // attack
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "extrainfo",
                                "/" + ADOBE_CROSS_DOMAIN_POLICY_FILE), // extrainfo
                        Constant.messages.getString(MESSAGE_PREFIX_ADOBE_SEND + "soln"), // solution
                        "<allow-http-request-headers-from domain=\"*\"", // evidence
                        crossdomainmessage // the message on which to place the alert
                );
            }
        }
    } catch (SAXException | IOException e) {
        // Could well be a 404 or equivalent
        log.debug("An error occurred trying to parse " + ADOBE_CROSS_DOMAIN_POLICY_FILE + " as XML: " + e);
    }
}

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

private void scanSilverlightCrossdomainPolicyFile(URI originalURI)
        throws IOException, XPathExpressionException {
    // retrieve the Silverlight client access policy file, and assess it.
    HttpMessage clientaccesspolicymessage = new HttpMessage(new URI(originalURI.getScheme(),
            originalURI.getAuthority(), "/" + SILVERLIGHT_CROSS_DOMAIN_POLICY_FILE, null, null));
    sendAndReceive(clientaccesspolicymessage, false);

    if (clientaccesspolicymessage.getResponseBody().length() == 0) {
        return;//  ww w  . j ava 2  s  .c o m
    }

    byte[] clientaccesspolicymessagebytes = clientaccesspolicymessage.getResponseBody().getBytes();

    // parse the file. If it's not parseable, it might have been because of a 404
    try {
        // work around the "no protocol" issue by wrapping the content in a ByteArrayInputStream
        Document silverlightXmldoc = docBuilder
                .parse(new InputSource(new ByteArrayInputStream(clientaccesspolicymessagebytes)));
        XPathExpression exprAllowFromUri = xpath
                .compile("/access-policy/cross-domain-access/policy/allow-from/domain/@uri"); // gets the uri attributes
        // check the "allow-from" policies
        NodeList exprAllowFromUriNodes = (NodeList) exprAllowFromUri.evaluate(silverlightXmldoc,
                XPathConstants.NODESET);
        for (int i = 0; i < exprAllowFromUriNodes.getLength(); i++) {
            String uri = exprAllowFromUriNodes.item(i).getNodeValue();
            if (uri.equals("*")) {
                // tut, tut, tut.
                if (log.isDebugEnabled())
                    log.debug("Bingo! " + SILVERLIGHT_CROSS_DOMAIN_POLICY_FILE
                            + ", at /access-policy/cross-domain-access/policy/allow-from/domain/@uri");
                bingo(getRisk(), Alert.CONFIDENCE_MEDIUM,
                        Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "name"),
                        Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "desc"),
                        clientaccesspolicymessage.getRequestHeader().getURI().getURI(), // the url field
                        "", // parameter being attacked: none.
                        "", // attack
                        Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "extrainfo"), // extrainfo
                        Constant.messages.getString(MESSAGE_PREFIX_SILVERLIGHT + "soln"), // solution
                        "<domain uri=\"*\"", // evidence
                        clientaccesspolicymessage // the message on which to place the alert
                );
            }
        }

    } catch (SAXException | IOException e) {
        // Could well be a 404 or equivalent
        log.debug(
                "An error occurred trying to parse " + SILVERLIGHT_CROSS_DOMAIN_POLICY_FILE + " as XML: " + e);
    }
}

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

/**
 * finds the source code for the given file, using SVN metadata on the server (if this is
 * available)//from w  w w. j av a  2 s.  c o  m
 *
 * @param uri the URI of a file, whose source code we want to find
 * @return Did we find the source code?
 */
private boolean findSourceCodeSVN(HttpMessage originalMessage) throws Exception {

    AlertThreshold alertThreshold = getAlertThreshold();

    // SVN formats 1-10 (format 11 is not used) are supported by this logic.
    // TODO: The SQLite based (and centralised, except for pre-release formats which we don't
    // plan to support) ".svn/wc.db" style used from SVN format 12 through to 31
    // (and possibly later formats) is not yet supported here. It's a work in progress.
    // It is fully supported in the Spider, however.

    URI uri = originalMessage.getRequestHeader().getURI();
    String path = uri.getPath();
    if (path == null)
        path = "";
    // String filename = path.substring( path.lastIndexOf('/')+1, path.length() );
    String urlfilename = uri.getName();

    String fileExtension = null;
    if (urlfilename.contains(".")) {
        fileExtension = urlfilename.substring(urlfilename.lastIndexOf(".") + 1);
        fileExtension = fileExtension.toUpperCase();
    }

    // do not recurse into a Subversion folder... this would cause infinite recursion issues in
    // Attack Mode. (which goes depth first!)
    // in any event, it doesn't make sense to do this.
    if (path.contains("/.svn/") || path.endsWith("/.svn")) {
        if (log.isDebugEnabled())
            log.debug(
                    "Nope. It doesn't make any sense to look for a Subversion repo *within* a Subversion repo");
        return false;
    }

    // Look for SVN < 1.7 metadata (ie internal SVN format < 29) containing source code
    // These versions all store the pristine copies in the the same format (insofar as the logic
    // here is concerned, at least)
    try {
        String pathminusfilename = path.substring(0, path.lastIndexOf(urlfilename));

        HttpMessage svnsourcefileattackmsg = new HttpMessage(new URI(uri.getScheme(), uri.getAuthority(),
                pathminusfilename + ".svn/text-base/" + urlfilename + ".svn-base", null, null));
        svnsourcefileattackmsg.setCookieParams(this.getBaseMsg().getCookieParams());
        // svnsourcefileattackmsg.setRequestHeader(this.getBaseMsg().getRequestHeader());
        sendAndReceive(svnsourcefileattackmsg, false); // do not follow redirects

        int attackmsgResponseStatusCode = svnsourcefileattackmsg.getResponseHeader().getStatusCode();

        if (shouldStop(alertThreshold, attackmsgResponseStatusCode)) {
            return false;
        }

        if (originalMessage.getResponseBody().toString()
                .equals(svnsourcefileattackmsg.getResponseBody().toString())) {
            if (log.isDebugEnabled()) {
                log.debug("Response bodies are exactly the same, so can not be the source code");
            }
        } else if (!UNWANTED_RESPONSE_CODES.contains(attackmsgResponseStatusCode)) { // If the response is wanted (not on the
            // unwanted list)

            String attackFilename = uri.getScheme() + "://" + uri.getAuthority() + pathminusfilename
                    + ".svn/text-base/" + urlfilename + ".svn-base";
            if (log.isDebugEnabled()) {
                log.debug("The contents for request '" + attackFilename
                        + "' do not return 404 or 3**, so we possibly have the source code using SVN < 1.7");
            }
            // check the contents of the output to some degree, if we have a file extension.
            // if not, just try it (could be a false positive, but hey)
            String evidence = findEvidenceForExtension(svnsourcefileattackmsg.getResponseBody().getBytes(),
                    fileExtension);
            if (evidence != null) {
                // if we get to here, is is very likely that we have source file inclusion
                // attack. alert it.
                bingo(Alert.RISK_MEDIUM, getConfidence(attackmsgResponseStatusCode), getName(),
                        getDescription(), getBaseMsg().getRequestHeader().getURI().getURI(), null,
                        attackFilename, getExtraInfo(urlfilename, attackFilename), getSolution(), evidence,
                        svnsourcefileattackmsg);
                // if we found one, do not even try the "super" method, which tries each of the
                // parameters,
                // since this is slow, and we already found an instance
                return true;
            } else {
                if (log.isDebugEnabled())
                    log.debug("The HTML output does not look like source code of type " + fileExtension);
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Got an unsuitable response code "
                        + svnsourcefileattackmsg.getResponseHeader().getStatusCode()
                        + ", so it looks like SVN < 1.7 source code file was not found");
            }
        }
    } catch (Exception e) {
        log.warn("Got an error trying to find source code using the format used by SVN < 1.7", e);
    }

    // try again, by assuming that SVN 1.7 or later is used.  These versions use a different
    // internal format, and store the source code in different locations compared to SVN < 1.7.
    // Note that it's not as simple this time around, because the name of the file that contains
    // the source code is based on a SHA1 hash of the file contents, rather than being based on
    // the source file name.
    // In other words, we can't guess the name of the internal SVN file, and we can't just
    // calculate it from the file name.  The good news is that the file name that we need is
    // contained in the centralised
    // "wc.db" SVN metadata file that is associated with SVN >= 1.7.
    // "wc.db" lives in ".svn/wc.db".  This file contains data for all of the files in the repo
    // (ie, it contains data for the root directory and all subdirectories of the repo).
    // The only real issue we have is the question of where within the web folder structure (or
    // mappings) that the "wc.db" file resides.
    // For instance, the ".svn" directory might have been deployed into
    // "http://www.example.com/.svn",
    // or it *might* have been deployed into "http://www.example.com/dir1/dir2/.svn".
    // If we're looking for the SVN >= 1.7 source for
    // "http://www.example.com/dir1/dir2/login.php", for instance, we need to check for the
    // "wc.db" file in the following locations:
    //   "http://www.example.com/dir1/dir2/.svn/wc.db"
    //   "http://www.example.com/dir1/.svn/wc.db"
    //   "http://www.example.com/.svn/wc.db"
    // ie, we need to traverse all the way back to the web root looking for it.
    // Once we've found the "wc.db" file, we use it as an index, looking up the name of the file
    // for which we're trying to get the source code.
    // That gives us the internal SVN file name (containing the SHA1 value), which we can (in
    // theory) then retrieve. If it works, we will retrieve the source code for the file!
    try {
        String pathminusfilename = path.substring(0, path.lastIndexOf(urlfilename));
        while (!pathminusfilename.equals("/")) {
            HttpMessage svnWCDBAttackMsg = new HttpMessage(
                    new URI(uri.getScheme(), uri.getAuthority(), pathminusfilename + ".svn/wc.db", null, null));
            svnWCDBAttackMsg.setCookieParams(this.getBaseMsg().getCookieParams());
            // svnsourcefileattackmsg.setRequestHeader(this.getBaseMsg().getRequestHeader());
            sendAndReceive(svnWCDBAttackMsg, false); // do not follow redirects

            int svnWCDBAttackMsgStatusCode = svnWCDBAttackMsg.getResponseHeader().getStatusCode();

            if (shouldStop(alertThreshold, svnWCDBAttackMsgStatusCode)) {
                return false;
            }

            if (originalMessage.getResponseBody().toString()
                    .equals(svnWCDBAttackMsg.getResponseBody().toString())) {
                if (log.isDebugEnabled()) {
                    log.debug("Response bodies are exactly the same, so can not be the source code");
                }
            } else if (!UNWANTED_RESPONSE_CODES.contains(svnWCDBAttackMsgStatusCode)) { // If the response is wanted (not on the
                // unwanted list)
                // calculate the path used to access the wc.db, as well as the matching relpath
                // to query the wc.db
                // since the relpath is calculated from the original message URL path, after
                // removing the base used in the wc.db url path
                String wcdbAttackFilename = uri.getScheme() + "://" + uri.getAuthority() + pathminusfilename
                        + ".svn/wc.db";
                String relPath = path.substring(path.indexOf(pathminusfilename) + pathminusfilename.length());
                if (log.isDebugEnabled()) {
                    log.debug("The contents for request '" + wcdbAttackFilename
                            + "' do not return 404 or 3**, so we found the '.svn/wc.db' file for SVN >= 1.7..");
                    log.debug("The relpath to query SQLite is '" + relPath + "'");
                }

                // so we found the wc.db file... handle it.
                // get the binary data, and put it in a temp file we can use with the SQLite
                // JDBC driver
                // Note: File is not AutoClosable, so cannot use a "try with resources" to
                // manage it
                File tempSqliteFile;
                tempSqliteFile = File.createTempFile("sqlite_svn_wc_db", null);
                tempSqliteFile.deleteOnExit();
                OutputStream fos = new FileOutputStream(tempSqliteFile);
                fos.write(svnWCDBAttackMsg.getResponseBody().getBytes());
                fos.close();

                if (log.isDebugEnabled()) {
                    org.sqlite.JDBC jdbcDriver = new org.sqlite.JDBC();
                    log.debug("Created a temporary SQLite database file '" + tempSqliteFile + "'");
                    log.debug("SQLite JDBC Driver is version " + jdbcDriver.getMajorVersion() + "."
                            + jdbcDriver.getMinorVersion());
                }

                // now load the temporary SQLite file using JDBC, and query the file entries
                // within.
                Class.forName("org.sqlite.JDBC");
                String sqliteConnectionUrl = "jdbc:sqlite:" + tempSqliteFile.getAbsolutePath();

                try (Connection conn = DriverManager.getConnection(sqliteConnectionUrl)) {
                    if (conn != null) {
                        Statement pragmaStatement = null;
                        PreparedStatement nodeStatement = null;
                        ResultSet rsSVNWCFormat = null;
                        ResultSet rsNode = null;
                        ResultSet rsRepo = null;
                        try {
                            pragmaStatement = conn.createStatement();
                            rsSVNWCFormat = pragmaStatement.executeQuery("pragma USER_VERSION");

                            // get the precise internal version of SVN in use
                            // this will inform how the scanner should proceed in an efficient
                            // manner.
                            int svnFormat = 0;
                            while (rsSVNWCFormat.next()) {
                                if (log.isDebugEnabled())
                                    log.debug("Got a row from 'pragma USER_VERSION'");
                                svnFormat = rsSVNWCFormat.getInt(1);
                                break;
                            }
                            if (svnFormat < 29) {
                                throw new Exception(
                                        "The SVN Working Copy Format of the SQLite database should be >= 29. We found "
                                                + svnFormat);
                            }
                            if (svnFormat > 31) {
                                throw new Exception("SVN Working Copy Format " + svnFormat
                                        + " is not supported at this time.  We support up to and including format 31 (~ SVN 1.8.5)");
                            }
                            if (log.isDebugEnabled()) {
                                log.debug("Internal SVN Working Copy Format for " + tempSqliteFile + " is "
                                        + svnFormat);
                                log.debug(
                                        "Refer to http://svn.apache.org/repos/asf/subversion/trunk/subversion/libsvn_wc/wc.h for more details!");
                            }

                            // allow future changes to be easily handled
                            switch (svnFormat) {
                            case 29:
                            case 30:
                            case 31:
                                nodeStatement = conn.prepareStatement(
                                        "select kind,local_relpath,'pristine/'||substr(checksum,7,2) || \"/\" || substr(checksum,7)|| \".svn-base\" from nodes where local_relpath = ? order by wc_id");
                                break;
                            }
                            // now set the parameter, and execute the query
                            nodeStatement.setString(1, relPath);
                            rsNode = nodeStatement.executeQuery();

                            // and get the internal name of the SVN file stored in the SVN repo
                            while (rsNode.next()) {
                                if (log.isDebugEnabled())
                                    log.debug("Got a Node from the SVN wc.db file (format " + svnFormat + ")");
                                // String kind = rsNode.getString(1);
                                // String filename = rsNode.getString(2);
                                String svnFilename = rsNode.getString(3);

                                if (svnFilename != null && svnFilename.length() > 0) {
                                    log.debug("Found " + relPath + " in the wc.db: " + svnFilename);

                                    // try get the source, using the internal SVN file path,
                                    // building the path back up correctly
                                    HttpMessage svnSourceFileAttackMsg = new HttpMessage(
                                            new URI(uri.getScheme(), uri.getAuthority(),
                                                    pathminusfilename + ".svn/" + svnFilename, null, null));
                                    svnSourceFileAttackMsg.setCookieParams(this.getBaseMsg().getCookieParams());
                                    // svnsourcefileattackmsg.setRequestHeader(this.getBaseMsg().getRequestHeader());
                                    sendAndReceive(svnSourceFileAttackMsg, false); // do not follow redirects

                                    int svnSourceFileAttackMsgStatusCode = svnSourceFileAttackMsg
                                            .getResponseHeader().getStatusCode();

                                    if (shouldStop(alertThreshold, svnSourceFileAttackMsgStatusCode)) {
                                        return false;
                                    }

                                    if (!UNWANTED_RESPONSE_CODES.contains(svnSourceFileAttackMsgStatusCode)) { // If the
                                        // response is
                                        // wanted (not
                                        // on the
                                        // unwanted
                                        // list)

                                        String attackFilename = uri.getScheme() + "://" + uri.getAuthority()
                                                + pathminusfilename + ".svn/" + svnFilename;
                                        if (log.isDebugEnabled()) {
                                            log.debug("The contents for request '" + attackFilename
                                                    + "' do not return 404 or 3**, so we possibly have the source code using SVN >= 1.7");
                                        }
                                        // check the contents of the output to some degree, if
                                        // we have a file extension.
                                        // if not, just try it (could be a false positive, but
                                        // hey)
                                        String evidence = findEvidenceForExtension(
                                                svnSourceFileAttackMsg.getResponseBody().getBytes(),
                                                fileExtension);
                                        if (evidence != null) {
                                            // if we get to here, is is very likely that we have
                                            // source file inclusion attack. alert it.
                                            bingo(Alert.RISK_MEDIUM,
                                                    getConfidence(svnSourceFileAttackMsgStatusCode), getName(),
                                                    getDescription(),
                                                    getBaseMsg().getRequestHeader().getURI().getURI(), null,
                                                    attackFilename, getExtraInfo(urlfilename, attackFilename),
                                                    getSolution(), evidence, svnSourceFileAttackMsg);
                                            // do not return.. need to tidy up first
                                        } else {
                                            if (log.isDebugEnabled())
                                                log.debug(
                                                        "The HTML output does not look like source code of type "
                                                                + fileExtension);
                                        }
                                    } else {
                                        if (log.isDebugEnabled()) {
                                            log.debug("Got an unsuitable response code "
                                                    + svnSourceFileAttackMsg.getResponseHeader().getStatusCode()
                                                    + ", so it looks like SVN >= 1.7 source code file was not found");
                                        }
                                    }

                                    break; // out of the loop. even though there should be just
                                    // 1 entry
                                }
                            }
                        } catch (SQLException sqlEx) {
                            StringBuilder errorSb = new StringBuilder(300);
                            errorSb.append("Error executing SQL on temporary SVN SQLite database '");
                            errorSb.append(sqliteConnectionUrl);
                            errorSb.append("': ");
                            errorSb.append(sqlEx);
                            errorSb.append("\nThe saved response likely wasn't a SQLite db.");
                            log.debug(errorSb);
                        } catch (Exception e) {
                            log.debug("An error has occurred, related to the temporary SVN SQLite DB. " + e);
                        } finally {
                            // the JDBC driver in use does not play well with "try with
                            // resource" construct. I tried!
                            if (rsRepo != null)
                                rsRepo.close();
                            if (rsNode != null)
                                rsNode.close();
                            if (rsSVNWCFormat != null)
                                rsSVNWCFormat.close();
                            if (pragmaStatement != null)
                                pragmaStatement.close();
                            if (nodeStatement != null)
                                nodeStatement.close();
                        }
                    } else
                        throw new SQLException("Could not open a JDBC connection to SQLite file "
                                + tempSqliteFile.getAbsolutePath());
                } catch (Exception e) {
                    // the connection will have been closed already, since we're used a try with
                    // resources
                    log.error("Error parsing temporary SVN SQLite database " + sqliteConnectionUrl);
                } finally {
                    // delete the temp file.
                    // this will be deleted when the VM is shut down anyway, but better to be
                    // safe than to run out of disk space.
                    tempSqliteFile.delete();
                }

                break; // out of the while loop
            } // non 404, 300, etc for "wc.db", for SVN >= 1.7
              // set up the parent directory name
            pathminusfilename = pathminusfilename.substring(0,
                    pathminusfilename.substring(0, pathminusfilename.length() - 1).lastIndexOf("/") + 1);
        }

    } catch (Exception e) {
        log.warn("Got an error trying to find source code using the format used by SVN >= 1.7", e);
    }
    return false;
}

From source file:ru.org.linux.util.formatter.ToHtmlFormatter.java

public String memberURL(User user, boolean secure) throws URIException {
    URI mainUri = configuration.getMainURI();
    String scheme;// www  .  j av  a2s  . c om
    if (secure) {
        scheme = "https";
    } else {
        scheme = "http";
    }
    return (new URI(scheme, null, mainUri.getHost(), mainUri.getPort(),
            String.format("/people/%s/profile", user.getNick()))).getEscapedURIReference();
}