Password attacks against http web forms

Web form authentication

Web applications

Web applications have become important assets in a company infrastructure. If you need to do a penetration test then it is essential that you have a basic understanding of how to analyse and test these web applications.

Many, if not all, require some form of authentication. Sometimes this happens via Basic Authentication where the user needs to enter credentials in some form of popup in the web browser. More often though the authentication happens via a web form. Web forms have two major methods for sending credentials to the web server, via a GET request or a POST request.

GET and POST requests

The GET requests consists of a long URL containing all the variables in the URL whereas a POST requests sends the variables as part of the request header to the server. The latter makes the data ‘invisible’ (but not inaccessible) for a normal user.

server.domain/request.php?var1=a&var2=b&var3=c

False sense of security with POST requests

A word of warning. Using POST instead of GET does not provide any means of security. The data being sent to the web server is as easy accessible by an attacker via POST as via GET.

The disadvantage of using GET is that the full request (including the username and password) often gets logged. This logging can be at the intermediate proxy server, the web server to which you authenticate or even in the end user browser. Hence, authentication through web forms most often happens via a POST request.

Tools

For this exercise we’ll use a number of tools. Ideally we’ll use three machines but you would also be able to do this exercise with one machine. Having three machines is closer to a real world example.

  • An end-user laptop or desktop;
  • A web server with PHP support;
  • Kali Linux with a number of pentesting tools.

The vulnerable web server and Kali linux should be set up in a “Host Only” network in a virtualised environment (VMware, …). In this setup, the machine running Kali has IP address 192.168.218.145 and the web server has IP address 192.168.218.20. The ‘vulnerable’ website / script that I’ll point to is vulndemo.ckers.be (this is not a real world existing website). The end user machine should at least have a web browser and an SSH client installed.

Demo site

Below is a script that demonstrates how authentication via POST works. We’ll use this script as a starting point. Do not use this script in a production environment. It’s only purpose is to present the methodology, it’s by no means an example on how to do user authentication. Save the script below as vulndemo.php in the web root of the web server.

<?php

// Demo script for http-post-form authentication via hydra
//	cudeso - 2013
	
$login = false;
$username = "myuser";
$password = "secret";

if ($_POST["submit"] == "Login") {
	if ($_POST["username"] == $username and $_POST["password"] == $password)	$login = true;
	else {
		?><h1 style="background-color:#F2DEDE; border:1px solid #EED3D7; padding:8px 35px 8px 14px; color: #B94A48;" >
						Invalid credentials, wrong username or password</h1> <hr />
		<?php	
	}
}

if (!$login) {
?>
	<html><head></head><body>
	<p>Website to private and restricted access area for <?php echo $password; ?> data in the company dashboard.</p>
	<p>Contact <?php echo $username; ?>@ckers.be or info@ckers.be for more information.</p>
	<p>Use admin@ckers.be for help or visit the wordpress blog.</p>
	<h1>Enter your username and password</h1>
	<form method="POST" action="<?php echo $_SERVER["SCRIPT_NAME"]; ?>">
		<label>Username</label>
		<input name="username" value="" placeholder="Your username" required />
		<br />
		<label>Password</label>
		<input name="password" type="password" value="" placeholder="Your password" required />	
		<br />
		<input name="submit" type="submit" value="Login" />
	</form>
	</body></html>
<?php
}
else {
?>
  <html><head></head><body>
  	<h1 style="background-color:#DFF0D8; border:1px solid #D6E9C6; padding:8px 35px 8px 14px; color: #468847;" >
  		Welcome <? echo $username; ?> to your Secret Control Panel</h1>
  	<a href="<?php echo $_SERVER["SCRIPT_NAME"]; ?>">Log out</a>
  </body></html>
<?php
}

If you visit the site with a browser you’ll be presented with a login screen. The code contains a hard coded username (myuser) and password (secret). A failed login returns an error message, a succesfull login a welcome page.

Password guessing compared to password cracking

Cracking

Password cracking often requires that you have a hash (or something similar) representing a password and that you have to try to find out what the password is. This happens off-site, without interaction with the target site and often involves the use of Rainbow tables or something similar. It’s ideal if you do not want to give away the target site that you’re trying to break the login credentials but it requires you to have the hashes.

Guessing

Password guessing on the other hand involves that you guess the login by authenticating against the target. You use a set of credentials and you try them. Needless to say that this leaves a lot of traces as every probe can be spotted by the target (at least if they have some form of logging).

In this exercise we’ll use password guessing.

Reconnaissance

Gather information

Before we can guess we need to have some data that we can use to base our guesses on. You can gather usernames and passwords from all kind of sources (or even use prebuilt dictionaries). One of the easiest and most public places to find useful information is the website of the target. In this exercise we’ll use the demo page to scrape for usable content.

CeWL

CeWL, a ‘Custom Word List generator’ created by Robin Wood, is ideal for this task. Login to your instance of Kali Linux. If you run CeWL with the ‘–help’ option you get a list of all the available options. We’ll use the detection of email addresses and send a crafted useragent. The email addresses often contain a username part, we can use that to build our list of usernames. Sending a crafted useragent provides a way to blend in with the normal web requests.

  • –email : include email addresses;
  • -u : useragent to send;
  • -m : minimum word length, default is 3;
  • -d : depth to spider to, default is 2.
# cewl --email -u "Mozilla/5.0" -m 6 -d 1 http://vulndemo.ckers.be/customlogin.php
CeWL 5.0 Robin Wood (robin@digininja.org) (www.digininja.org)

Website
private
restricted
access
secret
company
dashboard
Contact
myuser
information
wordpress
username
password
Username
Password

Email addresses found
admin@ckers.be
info@ckers.be
myuser@ckers.be

This is how the request will look like in the apache web logs of the target :

192.168.218.145 - - [04/Oct/2013:07:57:10 +0200] "GET /customlogin.php HTTP/1.1" 200 806 "-" "Mozilla/5.0"

The first set of words contains possible passwords, we’ll save them in the file pass.txt. The list of email addresses can be used to build usernames. We’ll start with a list of usernames ‘admin’, ‘info’ and ‘myusers’ and save this in users.txt.

Additionally if you want to find usernames based on email addresses you can look up contact pages or do some Google searches. The MIT PGP Public Server is also a useful resource to query for email addresses.

Mapping

ZAProxy

In the next step we need to find out how the authentication form actually works. To do this, we will send our request through a proxy server. I advise you to use the Firefox browser and install the plugin Proxy Selector. This plugin allows you to easily switch between different proxies.

Make sure you know the IP address of your Kali Linux virtual host. We will use the OWASP Zed Attack Proxy. This is a Java based application and it’s pre-installed in Kali Linux. We’ll start it in Kali but forward the user interface to our desktop. To do this, you have to SSH into the Kali VM with X11-forwarding enabled and then start the proxy.

ssh -X -l root 192.168.218.145
/usr/bin/zap

Now you’ll have to configure the proxy to listen on the public interface. In Tools > Options > Local Proxy enter the IP of the Kali VM (in this example, 192.168.218.145). If you have installed the Proxy Selector plugin in Firefox you can now also add this proxy in the plugin settings (Preferences > Manage Proxies > Add).

Proxy requests

In Firefox, with the Kali proxy enabled, surf to the demo script. Because you have the proxy enabled, you’ll see the request in the proxy screen. Open the tree under Sites and click on Request in the right pane.

Now, you can use a random username and password to authenticate. The demo script will return an error that you are not authenticated and display an error string ‘Invalid credentials, wrong username or password’. In the proxy screen you’ll see a new POST request. Click on it and have a look at the details that appear in the Request tab. You’ll notice that the payload of the request has your username and password. The string that you see in the pane is the one that’s being send to the web server. The two variables username and password clearly indicate the elements that we want to run our tests against.

username=demo&password=demo&submit=Login

ZAP with SSL websites

In this example we use ZAP against an http website. If you would use ZAP against an https site you will have to change the launch script ‘/usr/share/zaproxy/zap.sh’ and add ‘-Djsse.enableSNIExtension=false’. The last line of the launch script would be as follows :

exec java ${JMEM} -XX:PermSize=256M -Djsse.enableSNIExtension=false -jar "${BASEDIR}/zap.jar" $*

Scanning

We now have the necessary information to test authentication with a set of users and passwords :

  • The query string for the POST request;
  • The error message returned for a failed login.

The next tool that we’ll use is THC Hydra. Hydra is also installed in Kali Linux and can be run from the command line or via a GUI. We’ll use the command line. Hydra supports scanning against various services but for this exercise we’ll use its http-form-post support.

  • -e sn : try empty passwords (n) and login (s) as password;
  • -v : verbose;
  • -L : list of usernames;
  • -P : list of passwords;
# hydra -e sn -v vulndemo.ckers.be http-form-post "/customlogin.php:submit=Login&username=^USER^&password=^PASS^:Invalid credentials" -L users.txt -P pass.txt 
Hydra v7.5 (c)2013 by van Hauser/THC & David Maciejak - for legal purposes only

Hydra (http://www.thc.org/thc-hydra) starting at 2013-10-04 00:15:12
[DATA] 16 tasks, 1 server, 54 login tries (l:3/p:18), ~3 tries per task
[DATA] attacking service http-post-form on port 80
[VERBOSE] Resolving addresses ... done
[80][www-form] host: 192.168.218.20   login: myuser   password: secret
[STATUS] attack finished for vulndemo.ckers.be (waiting for children to complete tests)
1 of 1 target successfully completed, 1 valid password found
Hydra (http://www.thc.org/thc-hydra) finished at 2013-10-04 00:15:13

Next to the usernames, passwords, the host and the URL, Hydra also needs an expression that indicates how it should interpret the returned results. This expression is build on three fields separated by a colon (:), the script to call (/customlogin.php), the querystring and the string that is returned with a failed login.

"/customlogin.php:submit=Login&username=^USER^&password=^PASS^:Invalid credentials"

As demonstrated in the output above, hydra has found the correct username and password.

Run Hydra through a proxy

You can run Hydra through a proxy. It makes perfectly sense to have the Hydra requests tunneled through ZAP because this allows you to inspect the requests and replies in details. All you have to do is export the HYDRA_PROXY variable and have it set to the correct proxy setting.

export HYDRA_PROXY="http://192.168.218.145:8080"

Hydra module support options

The different options used for a module or service supported by Hydra are available if you use the -U switch.

hydra -U http-form-post

Conclusion

This writeup only provides a basic overview of what is necessary to attack web form based authentication. The process involves these steps :

  1. Gather information (credentials) on the target
  2. Gather information on the authentication process (login form, variables)
  3. Run a password guessing tool

Real world applications often require a little bit more work than merely passing along the login variables. You often have to take into account unique session cookies, AJAX-requests and account lock-out policies.

The manual process of building the query string with Hydra can also be fairly automated if you use Burp Intruder but it makes sense to first understand the (semi-) manual process.

If you want to practice your skills against a number of ‘vulnerable’ websites then have a look at Web Security Dojo.

You can also follow a course at SANS. Both the SEC542: Web App Penetration Testing and Ethical Hacking as SEC560: Network Penetration Testing and Ethical Hacking provide you useful insight.

Resources

One thought on “Password attacks against http web forms

  1. Hello would you mind sharing which blog platform you’re using?
    I’m looking to start my own blog soon but I’m having a tough time selecting between BlogEngine/Wordpress/B2evolution and Drupal.

    The reason I ask is because your layout seems different then most blogs and I’m looking for something unique.

    P.S Apologies for getting off-topic but I had to ask!

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.