List of usage examples for org.apache.commons.httpclient URI toString
@Override
public String toString()
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("(?<=(&|\\?)[^\\?\"=&;]+=)[^\\?\"=&;]+(?=(&|\"))", "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("(?<=(&|\\?)[^\\?\"=&;]+=)[^\\?\"=&;]+(?=(&|\"))", "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; }