ZAP Proxy and DVWA
Not quite finished, I have solved the user and password hacking parts with Brute Force and SQL Injection. More will come…
I wanted to see how ZAP Proxy worked for testing website vulnerabilities.
I know the theory and can do some manual testing, but learning a toolset and how to use it is an important knowledge journey.
FIRST setup
- Install DVWA — I chose to install and run using Docker. The website for DVWA provides all the instructions needed, so there are no repeats here.
- Install ZAP Proxy — I am running on MAC. Easy to install and run on a modern M2 MacBook Pro
Scanning
The first step was a basic automatic scan. My first stumble was not knowing the username and password for DVWA AND needing to change security to ‘low’.
username: admin password: password
Launch ZAP Proxy > Automated Scan > Attack
Outcome
Check the Alerts; you will find a mainly unimpressive list of issues to address. It is nothing spectacular, but at least Zap is looking at the site.
Next…
Change to ‘Manual Explore’; doing this should get better results, as ZAP should be scanning whilst moving through the app.
TIP: You must ensure that ZAP and the browser work together, if not, check the ZAP documents.
Here, I switch OFF the HUD (Heads Up Display), set the URL and click ‘Launch Browser’. This starts a Chrome browser connected to ZAP.
After login goto DVWA Security and set Security Level to ‘low’. This is the first thing for you should do.
Now bounce through every link and perform the basic steps listed on the application. This is a clean pass, no attempt at hacking just to see if ZAP finds obvious issues.
The number of alerts has increased, and additional domains have been added. Useful but good nothing major found.
Now remove the domains I am not testing, this removes from the scope of proxy and gives less noise to dig through.
Two key pieces of information tell us that the server is Apache running PHP. This is useful for refining scanning.
Brute Force
The first test is to find the password for the user admin. I already know it, BUT if I did not know, how would this be done using the form given?
This form is sending a GET using the URL http://localhost:4280/vulnerabilities/brute/?username=admin&password=password&Login=Login#
I can use ZAP to fuzz the password repeatedly to test this form. I can get a list of popular passwords from any GIT repo, I chose a list from https://github.com/danielmiessler/SecLists/blob/master/Passwords/Common-Credentials/10-million-password-list-top-100.txt
I download the password list files to /Downloads.
I chose the URL [http://localhost:4280/vulnerabilities/brute/?username=admin&password=password&Login=Login#] listed in ‘History’ right click and choose Fuzz… from the Attack option.
From the Fuzzer choose the value password in the GET URL to Add a fuzz location. Select a file, which is the list of input values to use in the password placeholder. Choose one of the downloaded password files.
Also add a Message Processor. If the password is correct it will show Welcome on the page returned, use this as the tag.
Click Start Fuzzer
After the fuzzer completes running any rows with STATE ‘USER FOUND’ shows the password that worked.
First Simple test done.
SQL Injection
Now to find all users and repeat to find all usernames and passwords. First break the inputs that hit the DB to find out the database used, this will help target the same fields with db specific exploits.
Now alter ZAP PROXY settings to target MariaDB, Apache and Linux. All of which can be determined from the error thrown.
From the SQL Injection page constuct a URL to query for the list of tables,
This will pull the name for admin (which is as expected) and ALSO pull the list of tables in the database.
From here, we can determine the name of all the database tables, and the most likely table for user creds is ‘users’
Change the URL query to list the columns in the users table.
It can now be assumed that the user is the username, and the password is the password for each user. Change the URL one more time to address the users table.
*NOTE: Medium is strange. The hyphen symbol gets translated into something else, so use a notepad to enter hyphen hyphen like the picture below
GAME OVER!
Values for password are listed, we know that the admin pwd is password. Thave value in the database is 32 characters long which just a happens to be the length that any MD5 has would be.
The values for password are not clear text, BUT checking any MD5 decrypt site confirms that all passwords are stored in MD5.
The list of usernames and passwords looks like this when running each hash through a website that holds possible hash values for commonly used words and passwords. This is why LONG and COMPLEX passwords give better protection.
- admin password
- gordonb abc123
- 1337 charley
- pablo letmein
- smithy password
These can be validated manually OR the Brute Force can be re-run..
Brute Force the Login form
This test has been performed using the Fuzz tool, by selecting the Logon POST from the History tab.
Using the Fuzzer, add payloads for the user and password. As we know the values, we can use them; otherwise, a file containing common passwords could be used. The application also uses a redirect after login; this can be followed by selecting the option. Lastly, set a TAG based on the expected value on the login success page.
Change ‘Concurrent Scanning Threads per Scan’ down to 1 and increase the delay. This gives the server and ZAP tool time to get a new CSRF token, POST and follow the redirect.
Success tested the login screen and verified the usernames and passwords are valid.
Brute Force at Medium and Hard levels
The same brute force in low-security mode is tougher in Medium and Hard modes but can be solved.
Medium mode pauses an invalid response for 2 seconds, so the ZAP Proxy fuzzer can perform, but the attack takes longer while waiting for each response.
High-security mode wants a unique CSRF token to be posted. To get the token, the calling page must be called first with a logged-in session. To do this, first log in with a valid user to get the value for the cookie. Then, open the brute force page with the cookie to get the user_token, which is the csrf. Use the csrf in the GET to the Brute force, and it will test for a valid user and password. This cannot be done out of the box with ZAP Proxy, a python script (see below) does this better.
This process exhausts the routes used to brute force user and passwords.
Command Injection
Simple to execute, this one runs a command based on data entry into the form.
Done manually, knowing that the server is Linux OS running Apache web server, the most basic attack is adding an additional command.
In LOW the IP is shown and files in the default folder are listed.
List all users on the server, their home directories. As this is wide open you could chain another attack to write a file to the OS and then execute from here.
Medium attempts to tighten the data input. This is doen by replacing && and ;. However other options like || and & still work to allow a command to be passed into the input box. In fact using || is easier than && as this means run the command if the one on the left fails, so the site expects to run a ping command against and IP address so if you leave this blank then your alternative comand will run…
“ || ls “
CSRF
The page allows the user to change pwd.
In basis terms the site wants a GET to be sent with a new password. ANY site could call the same URL so we can hack this easily.
Option 1: Most simple is a HTML page with the same link. The web page MUST be in the same browser as a currently logged in user. Risk is that the link may not be opened by the victim whilst they are logged in, common attack vector with Phishing emails with links.
Option 2:
If the server is expecting the referrer to come from the same server then clicking a link from a different source location will not work. So use the method below to make the link from from the server.
Put the link into the stored XSS page to execute the same command for ANY user accessing the site. The page stops data entry for a useful payload as the field is short, but ZAP Proxy lets you put any length payload into the form post. Create an XSS payload that will drop a link onto the form that we want the victim to click; this will then reset the user's pwd.
I want the user to reset their password BUT use the password they want me to use. I will put a link in the Guest book, label it as ‘Free Viagra’ and hope the user will click my link and reset their password. Once this is done, it’s game over. The user thinks they clicked the wrong link but will not want to tell someone they wanted something naughty. They will not get logged out, so they will continue until the next time they log in.
First, build the payload and encode it using ZAP tools.
Alter the POST from ZAP tools to sign the guest book and bury the payload that would change the password IF the user clicks the link. The link is placed into the mtxMessage POST variable. The payload is not checked with low security, just written to the guest book.
This method also ensures that if the server is checking if the request is coming from the correct referring URL, then this hack defeats this check also which is the check performed in Medium security mode.
If the user clicks the link for the Free Viagra then instead of what is promised the browser changes to the page for changing the password, the password gets changed in the context of the logged-in user.
The password is reset.
You can add complication by first sending the link to a separate server that action (taking any payload from the link) and then redirecting to the target server to change the password.
Option 3:
At high level, the same page is checking for a csrf token rather than checking the referrer.
This token is picked up from the page prior to the GET request to save the password.
This hack is not as easy now so I abandoned on this exploration.