Recently I was performing an external penetration test, and there was not a lot of attack surface but there was a firewall device present with one of those browser based SSL VPN services. Without a lot to go on other than some usernames gathered from LinkedIn, this seemed like a door worth trying to force. I wished to target these users with a password spray, and I also wanted to have a go at some possible local users that might’ve been defined on the device, like root, fwAdmin, admin, etc. I was less worried about locking out these accounts, so towards the end of the engagement I tried a straight brute-force on them once I was ready to be loud.
Ah, but there were problems. Aren’t there always? The device did not submit the passwords in the HTTP request, even though they were TLS protected. Some kind of digest was used. It looked like md5.
Additionally, the URL being posted to wasn’t the same as the form it came from. Looking at the login process, I concluded that I first needed to request that form, collect multiple values, and finally perform some kind of digest calculation using my proposed password. Here are a couple excerpts from the login page.
It set a couple cookies, and calculated a CHAP response. Looking into the chapDigest() function I discovered that the param1 and id values from the form get converted from ASCII hex into bytes, concatenated with the password, and finally an md5 sum is generated and converted back to ASCII hex. This is not entirely complex but spread across two requests with sessId also moved from form fields to cookies, and it’s more than I want to figure out inside of Burp alone.
Fortunately, I have an extension I wrote that I use often to help with these situations. You can get a copy here: https://github.com/GeoffWalton/Burp-Command/blob/master/externalCommand.rb.
Basically, it lets me process or generate Intruder payloads using external commands. So first I needed to ensure that I could calculate the digest correctly. I didn’t have a device to actually test a valid login with so what I did is just make the requests using a browser, test the parameters in my local script, and verified the digest matched the one generated by my browser.
All but the last line was lifted directly from the device! I just needed to take the arguments in, and print the resulting digest out.
If the page structure had been much more complex, a little Ruby or Python script with some XPATH queries might have been a cleaner approach, but in this case, it was faster to just throw this together in bash.
This script returned a single string without a newline including most of the parameters I needed for my authentication request when given a password on standard input. It’s worth pointing out that curl was using Burp as a proxy. This means Burp would log these requests so I would keep a complete request history if the customer needed it. Now I just needed to set up the Intruder attack.
First step: send one of the actual authentication requests to the Intruder.
Next, I did a little rearranging and editing to accommodate the output of my script. Note that I went ahead and made the cookie name part of the replacement value. I also replaced the parameters my script was writing out with a bogus insertion point, “x”.
Next, I jumped over to my extension’s tab and configured it to call my script.
Finally, I disabled making the unmodified payload request and configured the payloads as indicated in the screen shots to follow. Remember they run top to bottom, left to right, so I needed to reference payload three (3) in payload one (1) to fill in that cookie value.
Here in payload set two (2) I popped in some user names.
Finally, in payload set three (3) came my list of passwords and I used my custom payload processor “command.”
This was ideal for my password spray attack (not shown) using Sniper, however for the cluster bomb attack, Burp will only run the payload processor once per cluster. I didn’t know if the sessId could be reused for multiple login attempts or not with this device, so that could have been a problem for this particular brute-force attack effort, although I didn’t see any output to indicate that. I had only some Repeater experiments that indicated that sessions expired after some number of seconds.
Still, despite the above draw back, Burp was a good tool for this. You might be asking, “Couldn’t you just script out making the request either with another curl command, Ruby, Python, etc.?” Sure, I have already created most of the script logic. Burp is still adding a lot of value here for me though:
- It’s keeping a full request / attack history.
- I don’t know what a successful login looks like so I’m glad to be able to sort easily by response length, and possibly use grep match/extract after the fact.
- I can easily pivot from my password spray to brute-force without re-working my script.
- I can visually inspect the requests to ensure they look right; again, it’s important not having a valid login or device I can reference for testing.