Обычно, когда сайт требует, чтобы Вы были зарегистрированы, прежде чем можно будет получить доступ к определенной странице, Вы взяты на экран входа в систему и после успешной аутентификации себя, Вы перенаправляетесь назад к первоначально требуемой странице. Здорово для удобства использования - но без тщательного исследования, эта функция может легко стать открытой уязвимостью перенаправления.
К сожалению, для примера этой уязвимости, посмотрите не далее, чем действие LogOn по умолчанию, обеспеченное ASP.NET MVC 2:
[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); // open redirect vulnerability HERE
} else {
return RedirectToAction("Index", "Home");
}
} else {
ModelState.AddModelError("", "User name or password incorrect...");
}
}
return View(model);
}
Если пользователь успешно аутентифицируется, они перенаправляются к "returnUrl" (если он был обеспечен через представление формы входа в систему).
Вот простое нападение в качестве примера (один из многих, на самом деле), который использует эту уязвимость:
http://www.mybank.com/logon?returnUrl=http://www.badsite.com
http://www.badsite.com
который сделан точно походить на веб-сайт банка жертвы, таким образом, жертва не знает, что он находится теперь на другом сайте.http://www.badsite.com
говорит что-то как, "Мы должны обновить наши записи - введите в некоторых чрезвычайно персональных данных ниже: [ssn], [адрес], [номер телефона], и т.д.".Какие-либо идеи о том, как поддержать эту redirect-on-successful-login функциональность уже, избегают уязвимости открытого перенаправления?
Я склоняюсь к опции разделения "returnUrl" параметра в части контроллера/действия и использование "RedirectToRouteResult" вместо просто "Перенаправления". Это приближается открытый какие-либо новые уязвимости?
Обновление
Путем ограничения меня маршрутами контроллера/действия я не могу перенаправить к пользовательским маршрутам (например. /backend/calendar/2010/05/21
). Я знаю, что путем передачи большего количества параметров действию LogOn, мог заставить это работать, но я чувствую, что буду всегда пересматривать этот метод - совершенствование его с нашей схемой маршрутизации. Так, вместо того, чтобы разделить returnUrl на его части контроллера/действия, я сохраняю returnUrl как есть и анализирую его, чтобы удостовериться, что он содержит только относительный путь (например, /users/1
) и не полный путь (например, http://www.badsite.com/users/1
). Вот код, который я использую:
private static bool CheckRedirect(string url) {
try {
new Uri(url, UriKind.Relative);
}
catch (UriFormatException e) {
return false;
}
return true;
}
Примечание стороны: Я знаю, что это открытое перенаправление, может казаться, не грандиозное предприятие по сравнению с подобными XSS и CSRF, но нам, разработчики являются единственной вещью, защищающей наших клиентов от плохих парней - что-либо, что мы можем сделать для создания задания плохих парней, тяжелее победа в моей книге.
Спасибо, Brad
Да, это уязвимость. Перед перенаправлением вам необходимо проверить строковый параметр returnUrl
, передав его объекту Uri , и убедиться, что целевой домен совпадает с запрашивающим доменом. Вы также должны принять во внимание случай, когда returnUrl
является относительным адресом, например / admin
. В этом случае нет проблем, поскольку перенаправление будет в то же приложение.
Вы всегда можете сохранить запись предыдущей страницы с помощью TempData, когда пользователь не аутентифицирован, и использовать это для перенаправления на предыдущую страницу вместо параметра url.
Если вы используете один из вариантов перенаправления, который использует контроллер и параметры действия или имя маршрута, все должно быть в порядке, при условии, что у вас есть соответствующие меры безопасности для методов вашего контроллера.
Идея заключается в том, что все, что вы используете для перенаправления, должно проходить через механизм маршрутизации и проверяться путем сопоставления маршрута.
Но я подозреваю, что настоящая уязвимость - это межсайтовый скриптинг. Если ваш злонамеренный пользователь не может внедрить какой-либо Javascript на страницу, у него нет возможности манипулировать возвращаемым URL-адресом или любым из его параметров (поскольку вы в противном случае управляете всем кодом сервера и браузера).