Tuesday, May 19, 2020

Late to the party, or, in other words massive web enumeration using ffuf.

Few days back I had the opportunity to take part in a challenge event, which I went last minute and unprepared.

There are few good reason to the last minute and not being prepared, mainly because I was invited late on the event and I had to prepare my environment as well, when others had their tools ready.

So I was late in the party. As most of the events for me, can only take place after working hours, I had to be quick in order to catch up with the others.

The event, roughly 500 hosts in different networks (results from nmap scan were provided) non sequential and in different networks waiting to be scanned.

On the last months my favorite tool for web enumeration had been ffuf, https://github.com/ffuf/ffuf, but even with that alone I couldn't catch up easily on the others.


Web dirbuster tool comparison 

Some stats first on ffuf and comparison with other tools used in web 'dir-busting'

I'll be using http://testphp.vulnweb.com/ for the tests and default as much as possible, parameters on each tool.

dirb, time 5.43 minutes.

Image 1. dirb

gobuster time 8.8 seconds

Image 2. gobuster

wfuzz time 28.2 seconds

Image 3. wfuzz

fuff time 8.7 seconds

Image 4. ffuf

Turbo intruder time 13.3 seconds.

Image 4. Turbo intruder

Brief comparison, lower is better:

Image 5. Brief comparison


So if you are not using ffuf, or turbo intruder ( I will explain later in another post as to why ) I'll advise to give them a try.



Back to the methodology. 

As mentioned above the data set was large and I was late.  So this was my methodology to gain some advantage in time.

1. Enumeration of all common ports using aquatone, eg:

cat hosts | aquatone  -ports large -out aquatone

2. Use gnu parallel to feed ffuf workers with the urls from aqutatone, verified working, using:

cat aquatone/aquatone_urls.txt | parallel -j 50 -I{} ffuf -w /usr/share/dirb/common.txt:FUZZ -u {}FUZZ -o {#}_results.html -mc 200,403 -sf -fs 0 -of html

Aquatone is taking roughly 6 minutes for 100 hosts and it will clean up ports that are not responding.

Image 6. Aquatone results.

Ffuf was able to produce results on the first few minutes which where easy to be analysed.

The parameters on the filtering at ffuf may vary during the stage of the analysis that you are. I will recommend to have at least 403 and 301 with the 200 (OK, found) so you can see what is denied and what is redirected initially.

Having in mind that I was aiming for speed mainly and not for quality at this phase.  I was able to get a good understanding on the targets and their setup in short time.

Following post will be on turbo intruder and what makes a difference on this scanner.

Tuesday, March 24, 2020

Solving CAPTCHA using Burp suite proxy and mitmproxy.

Few days back I was facing an issue in one of my tests. The web application was logging my session off every few minutes and also it was logging me out in case of an exception, as a request that Burp was sending and couldn't be handled. 

Initial idea was to go and instruct Burp proxy to use macro and re-authenticate the session but the application was using an additional captcha challenge that had to be solved.

Overall there were 2 issues to overcome:


  • Keep the session authenticated through Burp's proxy scan (automated and manual)
  • Find a way to solve the captcha.

For these items went ahead with the following setup, Burp proxy -> mitmproxy -> Website.

Burp proxy is configured to use an upstream proxy and pass all requests through there as shown in the image below:



Burp itself is listening on port 8082 and I'm using firefox with FoxyProxy pointing to it.


Mitmproxy's script is very simple and essentially is handling this pattern that exist during the login phase.

Script is running with mitmproxy -s mitm.py

The script it self can be something as the one below:

"""
This example shows how to parse a call and execute an external script
which will re-authorize the user on the web application.
""" 
from mitmproxy import http
import subprocess 
def response(flow: http.HTTPFlow) -> None:
    # Redirect is issued on the response, this is only used in the application for sending back the user to /logout. Match the response and call script.
    if (flow.response.status_code == 302):
        subprocess.call("python3 ./imagedecode.py", shell=True)
def request(flow: http.HTTPFlow) -> None:
    if flow.request.pretty_url.startswith("domain.com/user/index/login"):
        response()



The script 'imagedecode.py' is a script which is using tesseract OCR to process the captcha values and submit them to the website together with the login credentials.

The captcha images are simple as the ones below in the specific setup:




The script itself:



from PIL import Image
import subprocess
import requests
import cv2 
# I need to define a static cookie as it's used for verification on the captcha
# this cookie is set as valid if you pass the auth 
cookies = { "PHPSESSID": "8jadummyecookiefu12erm1923a;" }
url = 'https://domain.com/UiUser/secure?sid=0.6974342321354128' 
r = requests.get(url, cookies=cookies)
with open('im.png', 'wb') as f:
    f.write(r.content)
# Tesseract to the rescue
try:
    r = subprocess.check_output(["tesseract", "im.png", "-", "--psm", "13", "--dpi", "70"]).decode('utf8').strip()
    # Got the captcha we need to authorize the same session that was used
    params = {"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"}
    datapost = "login-email=user%40domain.com&login-pwd=mypasswordhere%3D%3D&login-yanzheng="+r+"&memory=false"
    r2 = requests.post( "https://domain.com/user/index/verify", headers=params, data=datapost, cookies= cookies, timeout=35)
except:
    print("Couldn't get captcha")
There are some things that could be optimised on the script as checking proper return code of the request and re-issue in case is not successful the login, but overall it has a rough 90-95% accuracy. 

Thursday, March 12, 2020

Using Burp Intruder for auth bypass - CTF, root-me.org / BSCorp - Linux

This is a small post on using Burp's Intruder to bypass login authentication.

The idea for this post is from a CTF challenge on root-me.org.

I will not be sharing information about how one will reach on this state as I wouldn't like to spoil the fun on it.


The initial page that the user will see after proceeding in the challenge will be the following:


With no apparent information about the login, trying with 'abc' as username and password will give the following result:

It's clear that there is some filtering implemented that are blocking some characters.  

The first thing is to identify which characters are allowed. This can be done on Burp using intruder. 

Intercept your login request and pass it to intruder as shown below:


On the intruder tab select sub-tab 'Positions' and clear all selections. Select the 'abc' value on the log= and add it as payload position.


Browse to the sub tab, select Payload set 1, Payload type 'List' and populate the list with. Simply use a notepad and input all possible characters one by one. I used a notepad and copy paste the entries on Burp.


Start the attack and observe the results.


As you can see above some requests are passing and some are giving an error message' Bad characters detected'

The next step will be to exclude these bad characters and keep the valid ones.  One can choose to select all remaining characters or limit the set to specific ones.

References: https://pentestlab.blog/2012/12/24/sql-injection-authentication-bypass-cheat-sheet/http://www.lifeoverpentest.com/2018/03/sql-injection-login-bypass-cheat-sheet.html .

From the links above the set of 19 characters could be reduced to 6, which are the followings, "# (  | ' / 1" .  The rest characters that are valid as possible entries have no value to as for a potential auth bypass.

To create an iteration of these values in the intruder, change the payload type to 'Custom iterator' and paste the values.

As we don't know how many characters will be needed for the attack we can start with 2 positions and increase them adding the same values to each position.


Start the attack and check on the output. If you don't see it successful, try adjusting the Position count by increasing it and repeating the values. 

In these case you are creating random values with all 6 characters which are used as attack patterns. 

For our attack on the specific environment a value of length 5 was the one that was successful. 

This can be seen on intruder on the following way:


The login request that is created with payload '||1# is giving a 302 redirect. 

Trying the value on the web page itself, 


Will allow us to bypass authentication and login on the portal.