Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
tarafından Jon Galloway
Bu öğreticide, ASP.NET MVC uygulamalarınızda açık yeniden yönlendirme saldırılarını nasıl önleyebileceğiniz açıklanır. Bu öğreticide, ASP.NET MVC 3'teki AccountController'da yapılan değişiklikler açıklanır ve bu değişiklikleri mevcut ASP.NET MVC 1.0 ve 2 uygulamalarınıza nasıl uygulayabileceğiniz gösterilir.
Açık Yeniden Yönlendirme Saldırısı nedir?
Sorgu dizesi veya form verileri gibi istek aracılığıyla belirtilen bir URL'ye yeniden yönlendiren herhangi bir web uygulaması, kullanıcıları dış, kötü amaçlı bir URL'ye yönlendirmek için üzerinde oynanabilir. Bu kurcalama, açık yeniden yönlendirme saldırısı olarak adlandırılır.
Uygulama mantığınız belirli bir URL'ye yeniden yönlendirildiğinde, yeniden yönlendirme URL'sinin değiştirilmediğini doğrulamanız gerekir. Hem ASP.NET MVC 1.0 hem de MVC 2 ASP.NET için varsayılan AccountController'da kullanılan oturum açma bilgileri, açık yeniden yönlendirme saldırılarına karşı savunmasızdır. Neyse ki, ASP.NET MVC 3 Preview'daki düzeltmeleri kullanmak için mevcut uygulamalarınızı kolayca güncelleştirebilirsiniz.
Güvenlik açığını anlamak için oturum açma yeniden yönlendirmesinin varsayılan ASP.NET MVC 2 Web Uygulaması projesinde nasıl çalıştığına bakalım. Bu uygulamada, [Authorize] özniteliğine sahip bir denetleyici eylemini ziyaret etmek, yetkisiz kullanıcıları /Account/LogOn görünümüne yönlendirecektir. /Account/LogOn'a yapılan bu yeniden yönlendirme, kullanıcının başarıyla oturum açtıktan sonra başlangıçta istenen URL'ye döndürülebilmesi için bir returnUrl querystring parametresi içerir.
Aşağıdaki ekran görüntüsünde, oturum açmadığınızda /Account/ChangePassword görünümüne erişme girişiminin /Account/LogOn'a yeniden yönlendirmeyle sonuçlandığını görebiliriz. ReturnUrl=%2fAccount%2fChangePassword%2f.
Şekil 01: Açık yeniden yönlendirme ile oturum açma sayfası
ReturnUrl querystring parametresi doğrulanmadığından, saldırgan açık bir yeniden yönlendirme saldırısı gerçekleştirmek üzere parametreye herhangi bir URL adresi eklemek için bunu değiştirebilir. Bunu göstermek için ReturnUrl parametresini https://bing.comolarak değiştirebiliriz, böylece sonuçta elde edilen oturum açma URL'si /Account/LogOn? olur. ReturnUrl=https://www.bing.com/. Sitede başarıyla oturum açtıktan sonra adresine yönlendiriliriz https://bing.com. Bu yeniden yönlendirme doğrulanmadığından, bunun yerine kullanıcıyı kandırmaya çalışan kötü amaçlı bir siteye işaret edebilir.
Daha karmaşık bir Açık Yeniden Yönlendirme Saldırısı
Açık yeniden yönlendirme saldırıları özellikle tehlikelidir çünkü saldırgan belirli bir web sitesinde oturum açmaya çalıştığımızı bilir ve bu da bizi bir kimlik avı saldırısına karşı savunmasız hale getirir. Örneğin, bir saldırgan parolalarını yakalamak amacıyla web sitesi kullanıcılarına kötü amaçlı e-postalar gönderebilir. Bunun NerdDinner sitesinde nasıl çalıştığına bakalım. (Canlı NerdDinner sitesinin açık yeniden yönlendirme saldırılarına karşı korunacak şekilde güncelleştirildiğini unutmayın.)
İlk olarak, saldırgan bize NerdDinner'da sahte sayfasına yönlendirme içeren bir oturum açma sayfası bağlantısı gönderir:
http://nerddinner.com/Account/LogOn?returnUrl=http://nerddiner.com/Account/LogOn
Dönüş URL'sinin nerddiner.com işaret ettiğini ve akşam yemeği sözcüğünden "n" sözcüğünün eksik olduğunu unutmayın. Bu örnekte bu, saldırganın denetleyebilen bir etki alanıdır. Yukarıdaki bağlantıya eriştiğimizde meşru NerdDinner.com oturum açma sayfasına yönlendiriliriz.
Şekil 02: NerdDinner oturum açma sayfası ve açık yeniden yönlendirme
Doğru oturum açtığımızda, MVC AccountController'ın LogOn eylemi ASP.NET bizi returnUrl querystring parametresinde belirtilen URL'ye yönlendirir. Bu durumda, saldırganın girdiği URL'dir( şeklindedir http://nerddiner.com/Account/LogOn). Son derece dikkatli olmadığımız sürece, özellikle saldırgan sahte sayfasının tam olarak meşru oturum açma sayfasına benzediğinden emin olduğundan bunu fark etmeyeceğiz. Bu oturum açma sayfası, yeniden oturum açmamızı isteyen bir hata iletisi içerir. Beceriksizce, parolamızı yanlış yazmış olmalıyız.
Şekil 03: Sahte NerdDinner Oturum Açma ekranı
Kullanıcı adımızı ve parolamızı yeniden yazdığınızda sahte oturum açma sayfası bilgileri kaydeder ve bizi yasal NerdDinner.com sitesine geri gönderir. Bu noktada, NerdDinner.com sitesi kimliğimizi zaten doğrulamıştır, bu nedenle sahte oturum açma sayfası doğrudan o sayfaya yönlendirebilir. Sonuç olarak saldırganın kullanıcı adı ve parolamız vardır ve bu adı onlara sağladığımızın farkında değildir.
AccountController LogOn Eylemindeki güvenlik açığı bulunan koda bakma
ASP.NET MVC 2 uygulamasında LogOn eyleminin kodu aşağıda gösterilmiştir. Başarılı bir oturum açma işleminin ardından denetleyicinin returnUrl'e bir yeniden yönlendirme döndürdüğünü unutmayın. returnUrl parametresinde doğrulama gerçekleştirilmediğini görebilirsiniz.
Listeleme 1 – ASP.NET MVC 2 LogOn eylemi AccountController.cs
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Şimdi ASP.NET MVC 3 LogOn eylemindeki değişikliklere bakalım. Bu kod, adlı IsLocalUrl()System.Web.Mvc.Url yardımcı sınıfında yeni bir yöntem çağrılarak returnUrl parametresini doğrulayacak şekilde değiştirildi.
Listeleme 2 – ASP.NET MVC 3 LogOn eylemi AccountController.cs
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (Url.IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("",
"The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
Bu, System.Web.Mvc.Url yardımcı sınıfında IsLocalUrl()yeni bir yöntem çağrılarak döndürülen URL parametresini doğrulamak için değiştirilmiştir.
ASP.NET MVC 1.0 ve MVC 2 Uygulamalarınızı Koruma
IsLocalUrl() yardımcı yöntemini ekleyerek ve ReturnUrl parametresini doğrulamak için LogOn eylemini güncelleştirerek mevcut ASP.NET MVC 1.0 ve 2 uygulamalarımızda MVC 3 değişikliklerini ASP.NET yararlanabiliriz.
UrlHelper IsLocalUrl() yöntemi aslında System.Web.WebPages'te bir yönteme çağrıda bulunur çünkü bu doğrulama ASP.NET Web Sayfaları uygulamaları tarafından da kullanılır.
Listeleme 3 – ASP.NET MVC 3 UrlHelper'dan IsLocalUrl() yöntemi class
public bool IsLocalUrl(string url) {
return System.Web.WebPages.RequestExtensions.IsUrlLocalToHost(
RequestContext.HttpContext.Request, url);
}
IsUrlLocalToHost yöntemi, Listeleme 4'te gösterildiği gibi gerçek doğrulama mantığını içerir.
Listeleme 4 – System.Web.WebPages RequestExtensions sınıfından IsUrlLocalToHost() yöntemi
public static bool IsUrlLocalToHost(this HttpRequestBase request, string url)
{
return !url.IsEmpty() &&
((url[0] == '/' && (url.Length == 1 ||
(url[1] != '/' && url[1] != '\\'))) || // "/" or "/foo" but not "//" or "/\"
(url.Length > 1 &&
url[0] == '~' && url[1] == '/')); // "~/" or "~/foo"
}
ASP.NET MVC 1.0 veya 2 uygulamamızda AccountController'a bir IsLocalUrl() yöntemi ekleyeceğiz, ancak mümkünse bunu ayrı bir yardımcı sınıfa eklemeniz önerilir. AccountController içinde çalışması için IsLocalUrl() ASP.NET MVC 3 sürümünde iki küçük değişiklik yapacağız. İlk olarak, denetleyicilerdeki genel yöntemlere denetleyici eylemleri olarak erişilebildiği için bunu genel yöntemden özel bir yönteme değiştireceğiz. İkinci olarak, URL ana bilgisayarını uygulama konağıyla karşılaştıran çağrıyı değiştireceğiz. Bu çağrı UrlHelper sınıfında yerel bir RequestContext alanını kullanır. Bunu kullanmak yerine. RequestContext.HttpContext.Request.Url.Host, bunu kullanacağız. Request.Url.Host. Aşağıdaki kod, ASP.NET MVC 1.0 ve 2 uygulamalarında denetleyici sınıfıyla kullanılmak üzere değiştirilmiş IsLocalUrl() yöntemini gösterir.
Listeleme 5 – MVC Denetleyicisi sınıfıyla kullanılmak üzere değiştirilen IsLocalUrl() yöntemi
private bool IsLocalUrl(string url)
{
if (string.IsNullOrEmpty(url))
{
return false;
}
else
{
return ((url[0] == '/' && (url.Length == 1 ||
(url[1] != '/' && url[1] != '\\'))) || // "/" or "/foo" but not "//" or "/\"
(url.Length > 1 &&
url[0] == '~' && url[1] == '/')); // "~/" or "~/foo"
}
}
IsLocalUrl() yöntemi yerine getirildiğinden, aşağıdaki kodda gösterildiği gibi returnUrl parametresini doğrulamak için LogOn eylemimizden çağırabiliriz.
Listeleme 6 – returnUrl parametresini doğrulayan güncelleştirilmiş LogOn yöntemi
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl)
{
if (ModelState.IsValid)
{
if (MembershipService.ValidateUser(model.UserName, model.Password))
{
FormsService.SignIn(model.UserName, model.RememberMe);
if (IsLocalUrl(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
else
{
ModelState.AddModelError("",
"The user name or password provided is incorrect.");
}
}
}
Artık bir dış dönüş URL'si kullanarak oturum açmayı deneyerek açık bir yeniden yönlendirme saldırısını test edebiliriz. /Account/LogOn kullanalım mı? ReturnUrl=https://www.bing.com/ yeniden.
Şekil 04: Güncelleştirilmiş LogOn Eylemini Test Etme
Başarıyla oturum açtıktan sonra, dış URL yerine Giriş/Dizin Denetleyicisi eylemine yönlendiriliriz.
Şekil 05: Açık Yeniden Yönlendirme saldırısı yenildi
Özet
Yeniden yönlendirme URL'leri bir uygulamanın URL'sinde parametre olarak geçirildiğinde açık yeniden yönlendirme saldırıları oluşabilir. ASP.NET MVC 3 şablonu, açık yeniden yönlendirme saldırılarına karşı korunmaya yönelik kod içerir. ASP.NET MVC 1.0 ve 2 uygulamalarında bazı değişikliklerle bu kodu ekleyebilirsiniz. ASP.NET 1.0 ve 2 uygulamalarında oturum açarken açık yeniden yönlendirme saldırılarına karşı koruma sağlamak için bir IsLocalUrl() yöntemi ekleyin ve LogOn eyleminde returnUrl parametresini doğrulayın.