DVGM/doc/exercises/03-dynamic-analysis-with-za...

8.6 KiB

(Interactive) Dynamic Analysis: ZAP

In the following, we will use the OWASP Zed Attack Proxy (ZAP) for analyzing our web application. First, we will use ZAP interactively, meaning that we will manually use DVGM while all traffic is being routed through ZAP's proxy and analyzed. Then, we will use the automatic features: Spider for discovering all URLs in the app, Active Scan to get a fully automatic scan similar to Arachni's, and the Fuzzer as a more manual, but also more powerful tool. Finally, we will see how ZAP can be scripted using Python for a completely automatic workflow for, e.g., continuous integration (CI) environments.

Using ZAP as an interactive tool

Oftentimes, the Zed Attack Proxy is used passively with an automated test suite to discover additional problems, but the proxy can also be used when browsing the app interactively.

To begin, press the windows key, search for ZAP, and start the GUI of ZAP. Then, select No, I do not want to persist this session at this moment in time.

Now, in the top toolbar, click on the Chromium symbol (the right-most icon) to start a built-in version of Chromium that is already configured to use the proxy. Once the browser is started, enter http://127.0.0.1:3000/ and press enter (you can also use your hostname again, but ZAP does not require it).

Your previous attempts at hacking DVGM have been successful; you have been able to obtain the login credentials of one of the lecturers (username: achim, password: sigmisinsecure). Use them to log into the app, and browse around. You will notice that you have more permissions now.

Insecure Headers

You should notice that ZAP has been logging all visited URLs so far. Most of them should have been tagged with an alert level of Low or Medium. Change the current tab from History to Alerts to inspect the alerts in more detail. Most of them should be related to insecure HTTP headers.

Missing server-side validation

We will now tell ZAP to enable disabled form fields and also show form fields that have been set to hidden. To do so, click the white light-bulb symbol in the top toolbar.

Now, in the browser tab showing DVGM, go to the Students tab and try to create a new student. You will notice that the form looks different now.

  1. Can you create a new lecturer or even a new admin user? Try and see if you can log in with the new user.
  2. What is the vulnerability here? Does it need to be fixed on the client or server side? Try and fix the vulnerability and test your fix.

Before you continue, make sure that you log out of DVGM. We will not continue with the lecturer account; a lecturer can create multiple kinds of resources in DVGM (grades, students), which leads the automated scanner not necessarily into infinite loops, but it will increase the scan time significantly. Do deal with these kinds of issues, one could limit the depth of the scanning further or even exclude these URLs.

Using ZAP as an automated tool

We will now use the more automated functions of ZAP. Unlike previously, we will directly use them with login credentials. ZAP offers to automatically steal the authentication cookie of your interactive session and use it for the automated functions.

To do so, click on the green plus next to the Output tab and open HTTP Sessions. The table will most likely be empty, as ZAP by default checks all cookies that come through the proxy for a small set of entries that resemble sessions, which does not contain the one used by Ruby on Rails.

To add the cookie name to this set, click on the wheel in the top right corner of the HTTP Sessions tab. Click on Add..., and add user_credentials. Confirm the settings dialog with OK.

Now, log in as a student, using the credentials from peter (password: football). You will notice that ZAP detected a new session (Session 0). Right-click the session and set it to active. This will make sure that ZAP uses the session for the scans.

Spider

We will now use Spider to discover all URLs of our app, which is a prerequisite for the automated scanner. In the top left window, right-click on the URL and choose Attack -> Spider.... Click on Start Scan and observe the output. Only URLs that are below the entry URL are scanned; all others are skipped.

Before we start the scan, we want to exclude the assets and sign_out pages again. In the top left window, right-click both entries and choose Exclude From -> Scanner, and confirm with OK.

Active Scan

To start the active scan, right-click on the URL in the top left window again and choose Active Scan.... This will take a few minutes. Afterwards, in the alert tab, you will see that ZAP now also found the two XSS vulnerabilities.

These alerts can also be exported into various formats. Do to so, click on Report in the top bar. If you want to, have a look at a few generated reports.

Fuzzer

We will now try to use ZAP's fuzzer to find the SQL Injection and XSS vulnerabilities in the lecturer search bar.

To do so, select the History tab in ZAP. In DVGM, navigate to the Grades tab and search for something that is easily recognizable, e.g., FOOBAR. After pressing Filter, click on the new entry in ZAP's history tab.

In the top right part of the window, select Request to show the request that you have just sent to the server. In the first line, select your search request, e.g., FOOBAR, and right-click on the selection. Now, select Fuzz..., click on Payloads... on the right, click Add..., select File Fuzzers, open the jprofuzz sub-menu, and select SQL Injection and XSS. Confirm all dialog boxes and click Start Fuzzer.

ZAP will now take the original request and replace FOOBAR with a number of different payloads and are typically used for SQL Injections and XSS attacks. Note that this mode is less automated than the Active Scan, so we will not get alerts and a report from ZAP.

Instead, we will look for two things:

  • Reflected in the State column means that ZAP, after having sent a specific payload for the lecturer parameter, found this particular token again in the HTML response from the server, which is an indicator that there might be a XSS vulnerability here.
  • The HTTP status code in the Code and Reason columns can give a hint whether there is a SQL Injection in the app. A response code of 5xx indicates an internal server error, which might be due to a malformed SQL query as a result of the injection. This indicates that one can tamper with the structure of a SQL query, which often allows to arbitrary modification.

Before you proceed, close ZAP.

Scripting ZAP

ZAP can also be controlled with a powerful python API. Many tasks that we have just seen can therefore be automated and used as part of an automated testing strategy. The following example shows how the Spider and Active Scan can be started from python (without a user sesssion).

First, install the ZAP API:

pip3 install python-owasp-zap-v2.4

Then, start the ZAP in headless mode without a GUI:

/usr/share/zaproxy/zap.sh -daemon \
  -config api.key="dvgmisinsecure" \
  -port 8080

Finally, save the following python script somewhere and execute it:

#!/usr/bin/env python
import time
from pprint import pprint
from zapv2 import ZAPv2

target = 'http://127.0.0.1:3000'
apikey = 'dvgmisinsecure'

# By default ZAP API client will connect to port 8080
zap = ZAPv2(apikey=apikey)

# Proxy a request to the target so that ZAP has something to deal with
print('Accessing target {}'.format(target))
zap.urlopen(target)
time.sleep(2) # Give the sites tree a chance to get updated

print('Spidering target {}'.format(target))
scanid = zap.spider.scan(target)

time.sleep(2) # Give the Spider a chance to start
while (int(zap.spider.status(scanid)) < 100):
    # Loop until the spider has finished
    print('Spider progress %: {}'.format(zap.spider.status(scanid)))
    time.sleep(2)

print ('Spider completed')

while (int(zap.pscan.records_to_scan) > 0):
      print ('Records to passive scan : {}'.format(zap.pscan.records_to_scan))
      time.sleep(2)

print ('Passive Scan completed')

print ('Active Scanning target {}'.format(target))
scanid = zap.ascan.scan(target)
while (int(zap.ascan.status(scanid)) < 100):
    # Loop until the scanner has finished
    print ('Scan progress %: {}'.format(zap.ascan.status(scanid)))
    time.sleep(5)

print ('Active Scan completed')

# Report the results
print ('Hosts: {}'.format(', '.join(zap.core.hosts)))
print ('Alerts: ')
pprint (zap.core.alerts())

This script is mostly taken from https://github.com/zaproxy/zap-api-python/, where also a more sophisticated script can be found.