Cause of the Incident#
The case encountered by 3sNwgeek
at work, GitHub link
This expert also has another Worm Webshell Series Based on AWD Competition
which is also good.
It can be explored when there is a chance.
Environment Setup#
You can set it up using an environment similar to phpstudy
.
git clone https://github.com/3sNwgeek/BruteForc_test
Then open BruteForc_test/low.html
to access it.
Burp settings can refer to the article written a few days ago on setting up Pikachu and Burp for brute-forcing Token-based forms.
level-1_hint: Sign-in Question#
Using the dictionary.
level-2_hint: Captcha Reuse#
Send to repeater
, try changing the password without changing the captcha:
It is found that there is no captcha error reported, meaning the captcha can be reused, using the same steps as above.
level-3_hint: Captcha Manipulation#
Check again in repeater
, and find that there is a limit on the number of times the captcha can be used:
View the source code and find that, in addition to the front-end code, there is also a captcha file.
And the parameters of the captcha file are passed in by the front end.
Let's test the Ccode
parameter and find a special case.
When the parameter is 111
, the resulting captcha can be one of 1
, 11
, 111
, 1111
.
At the same time, here, after entering the captcha incorrectly, the captcha is not reset.
The captcha will only be reset when it is entered correctly and the password is incorrect. So there is a situation where the captcha can be brute-forced.
The brute-force script is as follows:
import requests
code_url = 'http://127.0.0.1/BruteForc_test/yzm2.php?Ccode=111'
login_url = 'http://127.0.0.1/BruteForc_test/LoginMid2.php'
passwd_list = open('./10-million-password-list-top-1000.txt',
'r').read().splitlines()
for passwd in passwd_list:
r = requests.session()
r.get(code_url)
for i in range(0, 4):
number_list = ['1', '11', '111', '1111']
data = {
'name': 'admin',
'password': passwd,
'yzm': number_list[i]
}
html = r.post(login_url, data=data)
if 'Login successful' in html.text:
print("attack success!password:{}".format(passwd))
exit()
else:
break
level-4_hint: Bypass Front-end Encryption#
Normal testing, first pop up a window to display the entered username and password:
Then pop up another window to display a string of characters, capturing the packet shows that only this login_key
is transmitted.
Since it is front-end encryption, we cannot use the intruder
module of burp
for brute-forcing.
Currently unable to find the encryption file, so let's put it aside for now.
level-5_hint: Captcha OCR Recognition#
Here, the previous issues do not exist, and we need to use captcha recognition tools to recognize the captcha and then post
together.
Python Script#
Download the official installation package, after default installation, the installation path is: C:\Program Files (x86)\Tesseract-OCR\tesseract.exe
.
Install the library with pip
: pip install pytesseract
.
Moreover, there are cases where captcha recognition fails, and each password needs to be tested multiple times until "Captcha error" or "Login successful" appears.
The full code is as follows:
import pytesseract
from PIL import Image
import requests
from io import BytesIO
pass_list = open('./10-million-password-list-top-1000.txt',
'r').read().splitlines()
url = 'http://192.168.1.11/BruteForc_test/LoginHigh.php'
for line in pass_list:
while True:
s = requests.session()
pytesseract.pytesseract.tesseract_cmd = 'C:/Program Files (x86)/Tesseract-OCR/tesseract.exe'
response = s.get('http://192.168.1.11/BruteForc_test/yzm.php')
image = Image.open(BytesIO(response.content))
code = pytesseract.image_to_string(image)
data = {
'name': 'admin',
'password': line,
'yzm': code
}
html = s.post(url, data=data) # Attempt brute-forcing
print('[[-]error]:{}'.format(line))
if 'Login successful' in html.text:
print('[[+]succeed] password:{}'.format(line))
exit()
if 'Captcha error' not in html.text:
break
But the efficiency is not high:
PKAV HTTP Fuzzer#
Here I used an old software PKAV HTTP Fuzzer
.
In the variant settings, put the intercepted packet from burp
.
And select the value of password
to add a tag, and add the value of the captcha to the captcha tag.
Add a dictionary on the right:
Switch to the image captcha recognition tab, fill in the captcha address:
http://192.168.1.11/BruteForc_test/yzm.php
The built-in engine is not good, both the built-in Yisi captcha recognition engine and the next-generation captcha recognition engine can be used.
However, it can only load images and cannot recognize them. You need to create a recognition library yourself, and both of these software are paid.
I couldn't find a working cracked version of Yisi, but I found one for the next generation, with the extraction password being xiazai.94fb.cn
.
The specific operation is too complicated; you can watch the video to learn.
Finally, export a recognition library .cds
file, and after loading it, you can recognize the captcha:
I won't share the recognition library; trying to create a library is quite fun. If you want it, you can contact me via tg
.
Switch to the packet sender tab and click start to begin cracking:
Burp Plugin#
The burpsuite
plugin reCAPTCHA
is also not usable here.
You can try the plugin captcha-killer
, but this plugin itself does not have recognition capabilities and requires external API calls.
level-6_hint: Sliding Captcha Recognition#
Try sending packets twice in repeater
:
You can see that the token
value has not changed, but the return value is different, indicating that the focus is not on the token
but on detecting the session
.
Python Script#
Detecting the session
is very simple for python
, as requests
has a session()
method specifically for maintaining sessions.
By viewing the source code, you can find that the token
value is placed just below the input box in the page source code:
Using beautifulsoup
to parse the page to get the token
and then send it out is all that is needed.
The full code is as follows:
import requests
from bs4 import BeautifulSoup
url = 'http://127.0.0.1/BruteForc_test/hdyzma/'
login_url = 'http://127.0.0.1/BruteForc_test/hdyzma/welcome.php'
pass_list = open('./10-million-password-list-top-1000.txt',
'r').read().splitlines()
for line in pass_list:
s = requests.session()
html = s.get(url)
soup = BeautifulSoup(html.text, 'html5lib')
tag = soup.find_all('input')
token = tag[2].get('value')
data = {
'name': 'admin',
'password': line,
'token': token
}
html = s.post(login_url, data=data)
if 'Login successful' in html.text:
print('[[+]succeed] password is:{}'.format(line))
exit()
Burp#
Follow the original author of the target 3sNwGeek
to do it once.
In one of the packets captured while pulling the captcha, there is a token value
in the response
.
So we can use the macro feature of burpsuite
to extract the token
value from the login page and fill it into the login request.
Create Macros#
Switch to the Project options
tab, go to Sessions
, scroll down to Macros
.
Click add, a pop-up will appear, and we select the only get
packet from 192.168.1.11
:
Click OK, modify the Macro
description, and click the configure item
button next to it:
In the tab below, click Add
to add the specified token
parameter:
Select the token
value with the mouse, and burp
will automatically fill in the start and end markers, just fill in Parameter name
as token
.
If your settings differ from this, it is recommended to change them to match this, for example, after selecting the token
value.
The starting regular expression is value ="
, it is recommended to change it to "token" value ="
.
Session Handling Rules#
A new rule has already been added in Session Handling Rules
.
Click edit, customize the name, delete the default rule action, and add a new one Run a macro
:
Add the macro we just set and set the parameter name to the token
we just set.
Then set the scope of the macro, as we only need to brute-force account passwords,
So in Tools Scope, only select Repeater and Intruder, other modules can be checked as needed:
Brute Force#
Return to Repeater
, click Go
to resend the packet, and you can see that the token
parameter will refresh automatically:
Use Intruder to brute-force account passwords, set the mode to Cluster bomb
.
This mode must set two or more payloads
, so we set username
as a payload as well.
Then in the first position of payload sets
, only add one admin
, and the second payload remains top-1000
.
Because multi-threading will refresh the token simultaneously, causing some request packets to obtain a token that has already been refreshed, so it can only be set to run in single-threaded mode.
Successfully brute-forced the account admin/123456a
.
Reference articles:
End of article.