mysql

mysql


Detayları çekilecek blogpostun id'si GET'ten "post" parametresi ile alınıyor. Ardından o blogpostun detaylarının çekilmesi için "mw_blogs" tablosundan "id" kolonu gelen değere eşit olan blogpost çekiliyor. Ardından "mw_comments" tablosundan "postid" kolonu gelen değere eşit olan commentler çekiliyor.

Bunları join ile yapmamışlar, ayrı ayrı 2 sorgu ile yapmışlar, birazdan göstereceğim.

Örnek "mw_blogs" tablom aşağıdaki gibi;


Örnek "mw_comments" tablom aşağıdaki gibi;


Sayfadaki kodlar ise şu şekil;

SELECT * FROM ".$database['prefix']."blogs

WHERE id = '$b_post'

LIMIT 1

SELECT * FROM ".$database['prefix']."comments

WHERE postid = '$b_post'

ORDER BY id ".($SETTINGS->commentsOrder=='asc' ? 'DESC' : 'DESC')."

Bug'ın detayları

Şöyleki; WHERE içerisinde 2 farklı condition OR bağlacı ile kullanıldı ise; eğer ilk condition sağlanıyor ise 2. contition'nın sağlanması için 1. condition dışında kalan row'larda işlem yapılıyor. Bu anlattığımı şöyle ifade edeyim;

select * from mw_comments where postid=1 OR email like '%a%'

gibi bir sorguda ilk condition'da postid'si 1 olan row seçilip köşeye alınıyor; 2. condition için postid'si 1 olmayan rowlarda işlem yapılıyor. 

Şimdi; bu case'in bana assigne edildiği yorumda %27%20OR%20(SLEEP(10))=0--+ patternı ile PoC yapıldığı yazıyor.

Durum 1; Bu pattern'ı postid'si 1 olan blogpost için uyguladığımızda sorgu şöyle oluyor;

SELECT * FROM mw_comments

WHERE postid = '1' OR (SLEEP(10))=0 -- '

ORDER BY id ASC

Bu sorguda ilk condition postid=1 olduğundan postid'si 1 olan 4 row seçiliyor (idleri 2,3,4,5 olanlar). Geriye sadece postid'si 2 olan 1 row kalıyor. 

Bu sorgu için geriye 1 row kaldığından sleep fonksiyonu 1 kere çalışıyor ve toplam süre = (1 * sleep(10)) + (normal query time) oluyor.

Durum 2; Bu pattern'ı postid'si 2 olan blogpost için uyguladığımızda sorgu şöyle oluyor;

SELECT * FROM mw_comments

WHERE postid = '2' OR (SLEEP(10))=0 -- '

ORDER BY id ASC

Bu sorguda ilk condition postid=2 olduğundan postid'si 2 olan 1 row seçiliyor. Geriye postid'si 1 olan 4 row kalıyor.

Bu sorgu için geriye 4 row kaldığından sleep fonksiyonu 4 kere çalışıyor ve toplam süre = (4 * sleep(10)) + (normal query time) oluyor.

Özetle; sleep'in kullanıldığı condition a ulaşıldığında geriye kaç row sayısı kadar dönüyor sleep. Bunu belki MySQL'e bildirebiliriz.

Bu casedeki asıl sorun bu başlıktı sanırım. Bunu araştırıken yukarıdaki detayları tespit ettim. Biz aşağıdaki gibi saldırmışız;

http://debianserver/ScanApp/maian_weblog/publish/index.php?cmd=blog&post=123%27%20OR%20(SLEEP(10))=0--+

Öncelikle şunu belirteyim; yukarıda dediğim gibi adamlar postu ve commentleri çekerken join kullanmamış. 2 ayrı query yazmış. Dolayısı ile yaptığımız injection 2 ayrı query'de çalışıyor ve 2x zamanla bize geri dönüyor.

Database'de postid'i 123 olan ne blogpost, ne comment var. O yüzden bu şekilde saldırıldığında aşağıdaki gibi bir hesaplama oluyor;

(query sayısı) * (postid'i 123 olmayan postların sayısı) * (postid'i 123 olmayan commentlerin sayısı) * (sleep)

Yukarıda verdiğim database örneğine göre; 2 * 3 * 5 * 10 = 300saniye.

Report Page