Burp Suite - solving E-mail and SMS TAN multi-factor authentication with Hackvertor custom tags
Why bother investing time to automate work when doing IT security testing? On one hand, manual testing is a tedious work, where you spend time doing vulnerability tests that could be done by a machine. On the other hand, letting a machine decide fully on its own on how to do tests will mostly result in the machine doing nothing useful. This is especially true for security testing, where manually checking every parameter for injection attacks is very laborious and automated security scanners go on scanning for hours while a human would have aborted the scan for various reasons. However, if we teach automated tools to do things correctly each time, we get the sweet middle spot of semi-automated security testing, where the tools do the automatic and systematic security tests and the analyst can focus on the parts of a security test, where the tools are likely insufficient.
Burp Suite Pro is one of the main tools to do all kind of HTTP related security analysis and that supports a semi-automated testing. But now and then it lacks certain features. Burp extensions can again add some of them. In this post we would like to show how to use one of the most powerful extensions, Hackvertor by Gareth Hayes and its relatively new feature of Python scripting.
Use Hackvertor to generate Swiss social security numbers
Let's start with a simple example. Imagine you are security testing a website and you found an HTTP-API that expects the de facto Swiss social security number 1 as a parameter. Nearly every adult in Switzerland has such a number. After researching, you find out this unique number always starts with 756, followed by two times four random characters and ending with another two random characters like this:
756.9217.0769.85
If you would just like to brute-force random social security numbers in HTTP requests,
you could use Burp's Intruder feature that allows you to try generate different numbers.
But what if you would like to send a new random number each time you send the request in
Burp's Repeater? This is where Hackvertor can be used. In Hackvertor's UI you can search
for tags and you should quickly find the random_num
tag. The purpose is simply to
generate a random number as shown in the input and output field in the following picture:

So generating a new random social security number is as easy as pasting the following value into an HTTP request in Burp's Repeater:
756.<@random_num_0(4) />.<@random_num_1(4) />.<@random_num_2(2) />
For example, the following request can be created in the Burp Repeater:

However, it will not be sent out from Burp as-is and the tags will be replaced by Hackvertor. How does an example request look like when it leaves Burp? This can be observed in the Logger++ extension (another very helpful extension you should use) as shown in the following picture:

This was just an easy example to start. But the truth is, Swiss social security numbers
are not fully random and the last character is an EAN13 checksum over the other characters.
And instead of sending incorrect social security numbers to a website, how about
calculating that checksum in Hackvertor? That's where custom Hackvertor code execution
tags come into play. You can write them in JavaScript or Python, we'll use Python here.
Hackvertor code execution tags allow you to write code that takes an input (passed in
the variable input
, that's whatever is put between the tags) and define the output
variable. A no-transformation example looks like this:

So here's a little Python one-liner that calculates the checksum number from the nine
random numbers that were passed as input
and assigns the value to the variable output
:
z=input;y=z.replace('.','');output=z+str(10-(sum([3*int(x) for x in y[1:][::-2]])+sum([int(x) for x in y[::-1][1::2]]))%10)[-1]
Defining it as the tag name ean13
and you should get the following picture when
you open the tag in the edit window:

Note that the leading underscore is used for every custom tag, so Hackvertor knows it is not a built-in Hackvertor tag. So how do we use such a custom tag?
First of all, there is a security measure so other people that send traffic through your
Burp can't execute the custom tag on your Burp machine. Code execution tags are only
executed when a certain random token is included in the tag. This means you'll need to
create a custom tag in the Hackvertor UI first to get that random token. Creating the
custom tag for our ean13
tag in the Hackvertor UI will result in something like this:

So keep in mind that for your Burp installation, that random number in double qutoes will be different. As the output windows in the above picture tells you, code execution tags are still disabled by default for security reasons. This is a second setting you'll need to change. You can enable them in the top main menu of Burp under the Hackvertor item. What you need to do then is to allow code execution tags in Hackvertor:

After that you will probably not see much in the output window of Hackvertor. That's because we have to give our custom tag the correct input. For example:
<@_ean13_3("83a52168fad35b2d85f6972b0eb1db91")>756.9217.0769.8<@/_ean13_3>
Now you should see the correct social security number being generated, namely 756.9217.0769.85. And here comes the real power of Hackvertor. Now you can combine the generation of random numbers feature of Hackvertor and our custom tag in a nested form:
<@_ean13_3("83a52168fad35b2d85f6972b0eb1db91")>756.<@random_num_0(4) />.<@random_num_1(4) />.<@random_num_2(1) /><@/_ean13_3>
Whenever you send this value in the Burp Repeater, it will be replaced with a random social security number with a correct checksum. Of course you can now not only generate random social security numbers, but you can also generate the random numbers with Burp Intruder and brute-force with valid EAN13 checksums.
In some cases it might be even possible to simply paste the above tags into the browser you use with Burp and the web server will receive a random social security number. However, this only works if the web application you are testing does not encode the values we put into HTML fields and Hackvertor is still able to see the tag exactly as written above. This is rather a rare case, but it might work.
Use Hackvertor to fetch second-factor authentication token
Let's do a more advanced custom tag example. Could you use the scripting capabilities of Hackvertor
to automatically solve TAN second factor verification in multi-factor authentication web forms? At
Pentagrid we have an SMS to E-mail gateway for testing purposes, meaning if second factor TANs are
sent out via SMS or E-mail, they will always land in one of our testing E-mail inboxes. Can we
retrieve the second factor TAN tokens from the E-mail inbox with a Hackvertor tag? Yes we can, with
the very useful Python imaplib
and an E-mail server that supports IMAP. Of course the entire
parsing logic for the incoming TANs is highly dependent on the web application and how the SMS or
E-mails look like. You will need to change the parsing code according to your needs. So here's a
quick'n'dirty example that worked for us for a certain web application. We created the new Hackvertor
tag like this:
import getpass, imaplib import time time.sleep(0.1) class Email: def __init__(self, data): self.data = data.decode() self.body = "\r\n\r\n".join(self.data.split("\r\n\r\n")[1:]) M = imaplib.IMAP4_SSL(host='use-your-own-mail-host.pentagrid.ch') M.login("pentagrid@example.org", "email-password") M.select() typ, data = M.search(None, 'ALL') token = "NO TOKEN WAS FOUND" for num in data[0].split()[::-1]: typ, data = M.fetch(num, '(RFC822)') email = Email(data[0][1]) for line in email.body.splitlines(): #print(line) if line.startswith("Your TAN is: "): token = line.split("Your TAN is: ")[1].strip() if token: print(token) break else: print("No token found") #print('Message %s\n%s\n' % (num, data[0][1])) print("Final token:", token) output = token M.close() M.logout()
The Python code will login to the IMAP mailbox, retrieve E-mails starting with the newest,
quick'n'dirty parse the TAN from the E-mail by interating through each line of the E-mail
and assign the the first token found to the output
variable that Hackvertor expects.
You might need to play with the sleep delay we introduced at the beginning of the script
to make sure the E-mail reaches the mailbox before you try to retrieve it. Otherwise you
could change the script to only consider the very newest E-mail but you would need to take
care to delete old E-mails. And of course you need to change your E-mail server, username
and password. Please be aware that this is as well not thread-safe, you would need a
seperate E-mail mailbox for each thread to make it concurrent.
Configuring a search and replace rule in the Burp Proxy to replace any second factor you enter with the Hackvertor tab is left as an exercise to the reader. We were able to test websites without ever entering the second factor manually again, as the entered token was replaced with a Hackvertor tag and Hackvertor fetched the token from the mailbox.
Hackvertor is therefore the perfect solution if you would like to script things that are sent in HTTP requests. With the new scripting capabilities, it is not necessary to write extensions when you want to change things sent out. Or do you? Unfortunately, there are certain limitations with this approach and in Burp. The search and replace rule for the Proxy of course only works for the Burp Proxy. But what if we want to make the Burp Crawler be able to login with second-factor TANs? We can't use session handling rules (another advanced topic of Burp), as they don't apply for Burp Crawler. But we were able to write an extension that handles that part, but that's for another blog post (it is really cool to see the headed browser of Burp login correctly). And what if you would also like to modify HTTP responses? Or what if you would like to even enhance Burp with a Transfer-Encoding feature it does not yet support? Do you want to know how you could set up an SMS to E-mail gateway? Stay tuned for our next blog posts, subscribe to our RSS feed or follow us on Twitter or LinkedIn.
- 1
-
The de facto Swiss social security number, respectively German: AHV Alters- und Hinterbliebenenversicherung, Rumantsch: AVS - Sgüranza da vegls e relatschats, Italian: AVS - Assicurazione per la vecchiaia e per i superstiti, French: AVS - L'assurance-vieillesse et survivants