Showing posts with label ZAProxy. Show all posts
Showing posts with label ZAProxy. Show all posts

Monday, October 29, 2012

Anti-CSRF Token Detection for Fun and Breaking Code

Detecting CSRF countermeasures is an important feature for penetration testing tools of web applications. It helps to detect CSRF issues, as well as to indicate the spider that the targeted request has to be carried out with the secret token in order to perform it successfully.

ZAP currently bases its anti-csrf token detection mechanism on a static list of known tag names, which will generate false negatives in real world apps. I thought it could be funny to enhance the ZAP mechanism by attempting to build a dynamic, behavior-based, approach.

In this post, I will describe the approach I designed and show its results. There is an interesting thread in the ZAP development group about it.


Algorithm Description

I implemented my approach as a ZAP 1.4 extension, which is currently available in the main codebase. There is no plugin jar file available yet. If you want to test it, you will need to either compile it by yourself or to ping me and I'll send it to you.

The algorithm works as follows. For each page, it first checks whether the page has input parameters (user-controllable data) or not. If so, the page potentially performs a critical action, and therefore, it might be vulnerable to CSRF attacks. Otherwise, the page does not perform security critical actions and performing a CSRF attack does not produce any impact.

For each potential vulnerable page, the scanner will attempt to determine whether there is a anti-csrf token or not. To achieve this, the scanner creates a hash map of the input hidden fields of the targeted page. Then, it starts a new session, requests again the page and matches the new input hidden fields with the previous ones. If there is a input hidden field whose value changed in the second request and it passes a set of tests to avoid false positives, then the field will be marked as an anti-csrf token, and consequently, the page will not be marked as vulnerable to CSRF attacks. Otherwise, it will.
The interesting part of the algorithm is the one that attempts to determine which ones of the hidden input fields are actually anti-csrf tokens. To achieve this, it performs thw following checks:

  • Entropy estimation: After performing the second request, it is carried out a randomness estimation (by computing the Levenshtein distance ratio) of both of the token values. If the resulting ratio is lower than a determined threshold, then the token is either not random enough or not an anti-csrf token. This will avoid false positives in fields that have similar behavior to anti-csrf tokens such as counters.
  • Request status: I implemented another function that tries to determine if the second request (without cookies) is either properly carried out or the server is redirecting us to the login page. I perform this check by looking at the HTTP code status.
  • Session Id check: The value is compared with the session id to avoid missdetermining it as an anti-csrf token.

Regarding performance, the plugin only performs one HTTP request on pages that have input tags, so it does not perform many extra requests.



Experimentation

I carried out experiments in both specific anti-csrf frameworks and real world apps.

The first target was NoCSRF, a framework available at http://bkcore.com/blog/code/nocsrf-php-class.html

In the following code block, I show the results of the ZAP plugin in debugging mode:
INFO org.parosproxy.paros.core.scanner.HostProcess-start host http://aopcgr.uab.es:10001 | Csrftokenscan level HIGH

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan-The page has parameters marked temporary vulnerable

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan-Input Tag: csrf_token, MTM1MTUwNjQ4MGJjQUQ0cko2bURvRHBIdlFVQ25xZm5xUGF5RmNuNTBB

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan-Input Tag: csrf_token, whateverkey

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan -The distance between "whateverkey" and "MTM1MTUwNjUxMUp1aVFzcTBsaDZVUUlMakc5dk1JQTlUUmRVcXAzUXVO" is 53 and their ratio is: 0.9464285714285714, random enough

 DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- "Found Anti-CSRF token: csrf_token, MTM1MTUwNjUxMUp1aVFzcTBsaDZVUUlMakc5dk1JQTlUUmRVcXAzUXVO"

INFO org.parosproxy.paros.core.scanner.HostProcess-completed host/plugin http://aopcgr.uab.es:10001 | Csrftokenscan in 0.087s

INFO org.parosproxy.paros.core.scanner.HostProcess-completed host http://aopcgr.uab.es:10001 in 0.111s

As we can see, it successfully detects the csrf_token input field as an anti-csrf token without producing any false positive.

The second framework tested was bodgeit, available at http://code.google.com/p/bodgeit/
INFO org.parosproxy.paros.core.scanner.HostProcess - start host http://localhost:10001 | Csrftokenscan level HIGH

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan - The page has parameters marked temporary vulnerable

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: null,

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: anticsrf, 0.02386741959595151

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The distance between "0.02386741959595151" and "0.45802788970587016" is 14 and their ratio is: 0.7368421052631579, random enough

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- "Found Anti-CSRF token: anticsrf, 0.45802788970587016"

In this framework we also detected the anti-csrf tokem, called anticsrf, and got none false positives.

The next targeted page I tested was Facebook:
DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The page has parameters marked temporary vulnerable

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: lsd, AVpYQ7RX

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: default_persistent, 0

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: next, http://www.facebook.com/directory/people/A-80081761-80772120

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: charset_test, €,´,€,´,水,Д,Є

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: timezone,

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: lgnrnd, 020036_NZ89

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: lgnjs, n

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: locale, es_ES

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: o, 2048

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: init, dir200

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The distance between "AVogYVkR" and "AVqTjOmD" is 6 and their ratio is: 0.75, random enough

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- "Found Anti-CSRF token: lsd, AVqTjOmD"

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The distance between "020038_ST8S" and "020208_v1NR" is 6 and their ratio is: 0.5454545454545454, random enough

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- "Found Anti-CSRF token: lgnrnd, 020208_v1NR"

The plugin found an anti-csrf token called lsd in several pages, googling a bit I found that it is actually a csrf countermeasure http://www.pallmallmedical.co.uk/cookies I could not find information in google about the lgnrnd parameter but it also looks like a random anti-csrf token.

As we can see in Figure 1, this countermeasure was implemented in all the facebook pages.
Figure 1. CSRF countermeasures in facebook


The last page to test was gmail, and these are the results:
DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The page has parameters marked temporary vulnerable

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: continue,http://mail.google.com/mail/

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: service, mail

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: dsh, 7965555468608615868

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: ltmpl, default

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: GALX, Ldh-U9oUXrc

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: timeStmp,

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: secTok,

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- Input Tag: rmShown, 1200

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The distance between "7965555468608615868" and "2970808815108171516" is 14 and their ratio is: 0.7368421052631579, random enough

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- "Found Anti-CSRF token: dsh, 2970808815108171516"

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- The distance between "Ldh-U9oUXrc" and "NywfjREgMcg" is 11 and their ratio is: 1.0, random enough

DEBUG org.zaproxy.zap.extension.csrftokenscan.Csrftokenscan- "Found Anti-CSRF token: GALX, NywfjREgMcg"

I also had to find documentation in google about what inoput fields are actually anti-csrf tokens. I found that dsh is a random anti-csrf token as explained in http://nagarun.wordpress.com/2011/07/02/my-mail-to-google-on-csrf/ On the other hand, GALX is a random anti-csrf token as explained in http://userscripts.org/topics/36200 and http://nagarun.wordpress.com/2011/07/02/my-mail-to-google-on-csrf/

As we show in Figure 2, all the gmail pages have this countermeasure integrated, except the about&contact ones that do no perform any critical action.

Figure 2. CSRF countermeasures in gmail.

We think that the results for this first approach are quite good, and we plan to perform more tests and enhance its results. Any feedback on this is very welcome.

Monday, August 20, 2012

WebApps Pentesting with ZAP and its AJAX Spider Plugin

We recently developed a new plugin for ZAProxy that integrates a web spider called Crawljax, which is an open source Java spider of AJAX web applications.

By using the AJAX Spider plugin, we can discover the pages and dynamic-built links of a targeted web application, whose results can be later used by ZAP to find its vulnerabilities.

To set up the plugin, you have to perform the three following steps:
  1. Download the last release of ZAP from the zaproxy downloads tab. It is required ZAP>=1.4.1. 
  2. Download the AJAX Spider plugin from the zap-extensions site.
  3. Put the extension in the plugin folder of ZAP.
After this, ZAP and the AJAX Spider are ready to run. The AJAX Spider plugin can be invoked in the attack menu of the Sites Tab, as shown in [1] of the following image. The results of the crawling process will be shown in the AJAX Spider tab [2].


There are some parameters that you might want to configure before running it regarding the local proxy that ZAP creates to communicate with the crawljax instance, and regarding the crawling process:
  • In the local proxy options[1], you can configure its port an IP address.
  • In the crawler options[2], you can choose the web browser to be used by the plugin, the number of threads and the browser windows to open. You can also activate the "scan in depth option", which slows down a bit the process but improves its final results.
 This is shown in the next image:



When the process is started, a set of windows will be opened and the results will appear in the Sites tab[1] and also in the Spider Tab[2] where the found URLs can be clicked and the HTTP request and response will appear in [3].



I made a brief video that shows how to crawl a site and later use the generated web tree to find vulnerabilities in the targeted web application by using ZAP.



The plugin is still in alpha phase, if you have any comment, suggestion or question do no hesitate to contact me or to open a thread in the ZAP users' group.

Thursday, June 21, 2012

Enhancing AJAX Crawling capabilities of ZAProxy

Zed Attack Proxy
Zed Attack Proxy (ZAP) is a tool for penetration testing of web applications that can be easily used by both security aware  an unaware engineers .

It has several features such as a spider to discover the pages of a given site, and a set of scanners to automatically and semi-automatically discover security flaws. You can find more information about its specifications it the ZAP wiki.


I recently started working on improving its AJAX crawling capabilities by developing a plugin to integrate the OWASP Ajax Crawling Tool and Crawljax.

I am focusing my work in two different lines.
  • Building a plugin to facilitate the ajax spider integration in zaproxy.
  • Improving the results of the spiders when targeting AJAX-based sites.

To accomplish the second one, I am testing ACT and Crawljax in a security testing framework called Wivet that builds a set of links in a tricky way to difficult spiders crawling those.

When I started testing crawljax, it was not able to crawl any link of wivet due to unsupported tags issues and the spider of ZAP only a 10% of the pages.

 Since then, I improved its results up to 72% of the links so far. However, I am still working on reducing that 28% of the most hard to crawl ones.

For instance, I modified the clickTag() method of the Crawler class to support meta refresh tags as follows:
if (eventable.getElement().getTag().toLowerCase().equals("meta")) {
    Pattern p = Pattern.compile("(\\d+);\\s+URL=(.*)");
    for (Attribute e : eventable.getElement().getAttributes()) {
        Matcher m = p.matcher(e.getValue());
        if (m.find()) {
            try {
                //time*1000 to convert seconds to ms
                Thread.sleep(Integer.parseInt(m.group(1))*1000);
            } catch (Exception e) {
                LOGGER.error(e);
            }
        }
    }
}
LOGGER.info("Executing " + eventable.getEventType() + " on element: " + eventable+ "; State: "+this.getStateMachine().getCurrentState().getName());
    if (this.fireEvent(eventable)) {
        ...

I also improved in crawljax appendFrameContent() of WebDriverBackedEmbeddedBrowser and getFramesCandidates() of CandidateElementExtractor to support frame tags among other enhancements.

Below, I show a video of a test I did with the different spiders targeting  my wivet test environment.


I used a tool called Istanbul to record the video, but it looks like the time between frames is kind of high and it is not possible to change it.