Thông thường, khi một trang web yêu cầu bạn đăng nhập trước khi bạn có thể truy cập vào một trang nhất định được đưa đến màn hình đăng nhập và sau khi tự xác thực thành công, bạn được chuyển hướng trở lại trang được yêu cầu ban đầu. Điều này là rất tốt cho khả năng sử dụng - nhưng không cẩn thận, tính năng này có thể dễ dàng trở thành một lỗ hổng open redirect.Cách tránh lỗ hổng chuyển hướng mở và chuyển hướng an toàn khi đăng nhập thành công (Gợi ý: Mã mặc định ASP.NET MVC 2 dễ bị tổn thương)
Đáng buồn thay, cho một ví dụ về lỗ hổng này, lựa chọn nào tốt hơn hành động đăng nhập mặc định được cung cấp bởi 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);
}
Nếu người dùng được xác thực thành công, họ đang chuyển hướng đến "ReturnUrl" (nếu nó được cung cấp thông qua việc gửi biểu mẫu đăng nhập).
Dưới đây là một cuộc tấn công đơn giản ví dụ (một trong nhiều người, trên thực tế) mà khai thác lỗ hổng này:
- Attacker, giả vờ là ngân hàng của nạn nhân, gửi một email để nạn nhân có chứa một liên kết, như thế này:
http://www.mybank.com/logon?returnUrl=http://www.badsite.com
- Đã được dạy để xác minh tên miền ENTIRE (ví dụ: google.com = GOOD, google.com.as31x.example.com = BAD), nạn nhân biết liên kết là OK - không có bất kỳ tên miền phụ phức tạp nào lừa đảo đang diễn ra.
- Nạn nhân nhấp vào liên kết, thấy thực tế trang web ngân hàng quen thuộc của họ và được yêu cầu đăng nhập
- nạn nhân đăng nhập vào và sau đó được chuyển đến
http://www.badsite.com
được thực hiện để trông giống hệt như trang web ngân hàng của nạn nhân, vì vậy nạn nhân không biết anh ấy đang ở trên một trang web khác. http://www.badsite.com
nói điều gì đó như "Chúng tôi cần cập nhật hồ sơ của mình - vui lòng nhập một số thông tin cực kỳ cá nhân bên dưới: [ssn], [address], [phone number], v.v ..."- nạn nhân, vẫn nghĩ ông là trên trang web ngân hàng của mình, rơi cho mưu đồ và cung cấp kẻ tấn công với các thông tin
Bất kỳ ý tưởng về làm thế nào để duy trì chuyển hướng-on-thành-đăng nhập này chức năng chưa tránh open- chuyển hướng dễ bị tổn thương?
Tôi đang hướng về tùy chọn tách thông số "returnUrl" thành bộ phận điều khiển/tác vụ và sử dụng "RedirectToRouteResult" thay vì chỉ đơn giản là "Chuyển hướng". Cách tiếp cận này có mở bất kỳ lỗ hổng mới nào không?
Cập nhật
Bằng cách giới hạn bản thân mình để điều khiển các tuyến đường/hành động, tôi không thể chuyển hướng đến các tuyến đường tùy chỉnh (ví dụ /backend/calendar/2010/05/21
). Tôi biết rằng bằng cách chuyển nhiều tham số hơn cho hành động LogOn, tôi có thể làm cho nó hoạt động, nhưng tôi cảm thấy như tôi sẽ luôn luôn xem xét lại phương pháp này - giữ nó cập nhật với lược đồ định tuyến của chúng tôi. Vì vậy, thay vì tách returnUrl thành các phần điều khiển/hành động, tôi đang giữ returnUrl dưới dạng và phân tích cú pháp để đảm bảo nó chỉ chứa một đường dẫn tương đối (ví dụ: /users/1
) và không phải là đường dẫn tuyệt đối (ví dụ: http://www.badsite.com/users/1
).Đây là mã Tôi đang sử dụng:
private static bool CheckRedirect(string url) {
try {
new Uri(url, UriKind.Relative);
}
catch (UriFormatException e) {
return false;
}
return true;
}
Side lưu ý: Tôi biết mở chuyển hướng này có thể không có vẻ là một vấn đề lớn so với những cái tên như XSS và CSRF, nhưng chúng tôi phát triển là điều duy nhất bảo vệ khách hàng của chúng tôi khỏi những kẻ xấu - bất cứ điều gì chúng tôi có thể làm để làm cho công việc của kẻ xấu khó hơn là một chiến thắng trong cuốn sách của tôi.
Cảm ơn, Brad
Nếu bộ nhớ phục vụ, ReturnURL phải phù hợp với một trong những tuyến đường của bạn, hoặc điều sẽ YSOD. Nhưng tôi có thể sai. Bạn đã thử nghiệm điều này để chứng minh nó là một lỗ hổng? –
Tôi vừa thử nghiệm nó. Đúng rồi. Một câu hỏi khác có liên quan [ở đây] (http://stackoverflow.com/questions/2782710/what-is-it-about-the-default-asp-net-mvc-accountcontroller-code-that-some-hate) –
Nếu nó sẽ làm cho bạn cảm thấy tốt hơn, tôi khá chắc chắn rằng 'Redirect' không * không * làm một POST, nhưng chỉ GET. Nhưng tôi không cho rằng điều đó sẽ giúp bạn nếu thông tin nhạy cảm được truyền trong URL chuyển hướng dưới dạng tham số. –