top of page

Portswigger : Flawed two-factor verification logic

Yazarın fotoğrafı: Songül ÖZÜGÜRLER
Songül ÖZÜGÜRLER
28 Nis
4 dakikada okunur

Portswigger : Flawed two-factor verification logic

Bazen 2FA (two-factor authentication) adımlarındaki hatalı mantık nedeniyle, kullanıcı ilk giriş adımını doğru şekilde tamamlasa bile, web uygulaması ikinci adımı yapan kişinin aynı kullanıcı olup olmadığını düzgün şekilde doğrulamaz.

Örneğin kullanıcı ilk adımda normal kullanıcı adı ve şifresiyle giriş yapıyor:

POST /login-steps/first HTTP/1.1
Host: vulnerable-website.com
…
username=carlos&password=qwerty

Bu adım tamamlanınca sunucu, kullanıcıya hesabıyla ilişkili bir cookie veriyor ve ardından ikinci adıma yönlendiriyor:

HTTP/1.1 200 OK
Set-Cookie: account=carlos

GET /login-steps/second HTTP/1.1
Cookie: account=carlos

Kullanıcı doğrulama kodunu gönderdiğinde, uygulama hangi hesaba erişmeye çalıştığını bu cookie değerine bakarak anlıyor:

POST /login-steps/second HTTP/1.1
Host: vulnerable-website.com
Cookie: account=carlos
...
verification-code=123456

Bu senaryoda bir saldırgan, kendi hesabıyla ilk adımdan giriş yapabilir, fakat ikinci adımda doğrulama kodunu gönderirken account cookie’sinin değerini istediği bir kullanıcı adıyla değiştirebilir:

POST /login-steps/second HTTP/1.1
Host: vulnerable-website.com
Cookie: account=victim-user
...
verification-code=123456

Eğer saldırgan doğrulama kodunu brute-force ile tahmin edebiliyorsa, bu durum son derece kritiktir; çünkü sadece kullanıcı adını bilerek rastgele kullanıcı hesaplarına giriş yapabilir. Kullanıcının gerçek şifresini bilmesine bile gerek kalmaz.

Lab: 2FA Broken Logic

Senin giriş bilgilerin: wiener : peter Kurbanın kullanıcı adı: carlos Ayrıca kendi 2FA doğrulama kodunu almak için e-mail server’a erişimin de var.

İpucu: Carlos siteye kendi hesabıyla giriş yapmayı denemeyecek .

Önce kendi hesabım olan wiener:peter ile giriş yaptım. 2FA adımında gönderilen POST /login2 isteğini incelediğimde, kullanıcıyı doğrulayan mekanizmanın session değil doğrudan verify parametresi olduğunu fark ettim. Bunu nereden anlıyoruz? Çünkü bu POST isteğinde session’a özgü bir kontrol yok; sunucu tamamen verify değerine bakarak işlemi tamamlıyor. Bu da ciddi bir mantık hatası oluşturuyor.

Portswigger : Flawed two-factor verification logic

Hesaptan çıkış yaptım. GET /login2 isteğini Repeater’a gönderdim ve verify=wiener yerine verify=carlos olarak değiştirdim. Bu değişiklik, sistemin Carlos için geçici bir 2FA kodu üretmesini sağlıyor.

Portswigger : Flawed two-factor verification logic

Giriş ekranına dönüp tekrar wiener:peter ile giriş yaptım. 2FA ekranında bilerek yanlış bir kod gönderdim. Bu sayede POST /login2 isteğini yakalayarak Intruder’a gönderdim.

Portswigger : Flawed two-factor verification logic
Portswigger : Flawed two-factor verification logic

Intruder içinde verify=carlos olarak bırakıyorum. mfa-code parametresine payload pozisyonu ekliyorum. Lab’de 2FA kodu 4 haneli, bu yüzden 0000–9999 arası brute-force gerekiyor.Burp bazen 0007 yerine 7 gönderdiği için brute-force doğru çalışmaz. Bunu çözmek için Numbers payload’ında şu ayarı yaptım:

python ile küçük bir kod yazarak 0000 dan 9999a kadar tüm sayıları yazdırıp çıktı aldım .

Portswigger : Flawed two-factor verification logic
Portswigger : Flawed two-factor verification logic

Bu kod aslında 0000’dan 9999’a kadar bütün 4 haneli sayıları üretmek için yazılmış basit bir döngü.

for i in range(10000):
 print(f"{i:04}")

range(10000) dediğimde Python, i’yi 0’dan başlayıp 9999’a kadar sırayla veriyor. Ama sayı 0, 7 ya da 58 gibi kısa olduğunda direkt yazdırırsam 0, 7, 58 diye görünür. Benim istediğim ise hepsinin 4 haneli olması.

O yüzden f”{i:04}” formatını kullanıyorum. Bu format, sayı kaç haneli olursa olsun başını sıfırla doldurup toplam 4 basamak yapıyor.

Mesela:

0 → 0000

7 → 0007

58 → 0058

612 → 0612

Sonuç olarak döngü, 4 basamaklı tüm kombinasyonları tek tek üretmiş oluyor. Bunu da genelde PIN/2FA kodu brute-force denemeleri gibi yerlerde kullanıyorum.

sniper modunda brute force u çalıştırıyorum ve doğru kod geldiğinde sunucu 302 yönlendirme cevabı döndü. Bu 302 cevabını tarayıcıda açtım.

Portswigger : Flawed two-factor verification logic

Tarayıcıda My account sayfasına girdiğimde lab başarıyla çözüldü.

Brute-forcing 2FA verification codes

Tıpkı parolalarda olduğu gibi, 2FA doğrulama kodlarının brute‑force ile tahmin edilmesini engellemek için de web uygulamalarının ek önlemler alması gerekiyor. Çünkü bu kodlar genellikle 4 veya 6 haneli basit sayılar oluyor. Eğer doğru bir brute‑force koruması yoksa, bu kodları kırmak gerçekten çok kolay hale geliyor.

Bazı siteler, birkaç kez yanlış kod girildiğinde kullanıcıyı otomatik olarak çıkış yaptırarak brute‑force’u engellemeye çalışıyor. Fakat bu yöntem pratikte etkili değil. Çünkü tecrübeli bir saldırgan, bu çok adımlı süreci bile Burp Intruder üzerinde makrolarla otomatikleştirebilir. Hatta Turbo Intruder eklentisi bu iş için çok daha güçlü bir seçenek sunuyor.

Vulnerabilities in other authentication mechanisms

Temel giriş fonksiyonunun yanında, web siteleri kullanıcıların hesaplarını yönetebilmesi için ek özellikler sunar. Örneğin kullanıcılar genellikle parolalarını değiştirebilir veya unuttuklarında sıfırlayabilir. Ancak bu ek fonksiyonlar bile bazen saldırganlar tarafından istismar edilebilecek zafiyetlere sahip olabilir.

Web siteleri giriş sayfalarındaki bilinen açıkları engellemeye özen gösterir. Ancak aynı güvenlik önlemlerinin parola sıfırlama, hesap ayarları gibi ilişkili fonksiyonlarda da uygulanması gerektiği çoğu zaman unutulur. Hele ki saldırgan kendi hesabını oluşturabiliyorsa, bu sayfaları kolayca inceleyip mantık hatalarını tespit edebilir.

Keeping users logged in

Birçok web sitesinde, tarayıcı kapansa bile oturumun açık kalmasını sağlayan “Remember me / Beni hatırla” seçeneği bulunur.

Bu özellik genelde bir “remember me token” üretilip kalıcı bir cookie içinde saklanarak uygulanır. Bu cookie’ye sahip olmak tüm giriş adımlarını bypass etmek anlamına geldiği için, token’ın tahmin edilmesi imkânsız olmalıdır.

Fakat bazı siteler bu cookie’yi kullanıcı adı ve timestamp gibi öngörülebilir sabit değerleri birleştirerek oluşturuyor. Hatta bazıları cookie içinde parolanın bir kısmını bile kullanıyor. Eğer saldırgan kendi hesabını oluşturabiliyorsa, kendi cookie’sini inceleyerek bu formülü çözebilir ve diğer kullanıcıların cookie’lerini brute‑force ederek hesaplarına erişebilir.

Bazı siteler cookie şifreli göründüğü sürece tahmin edilemeyeceğini varsayar. Teoride doğru olabilir ama pratikte “şifreleme” için Base64 gibi basit, iki yönlü bir encoding kullanmak hiçbir koruma sağlamaz.

Hatta doğru hashing algoritması bile kullanılsa, eğer salt eklenmemişse saldırgan hashing algoritmasını belirleyip wordlist’ini hashleyerek cookie’yi brute‑force edebilir. Bu yöntem login rate‑limit korumasını da atlatabilir çünkü çoğu zaman cookie denemelerine limit uygulanmıyor.

Saldırgan kendi hesabını oluşturamıyorsa bile bu zafiyetten yararlanabilir. Örneğin XSS kullanarak başka bir kullanıcının cookie’sini çalabilir ve cookie’nin nasıl üretildiğini buradan çözebilir. Eğer site açık kaynak bir framework kullanıyorsa, cookie’nin üretim mantığı zaten belgelerde açıkça yazıyor olabilir.

 
 
bottom of page