2009-04-22 4 views
30

я в настоящее время есть ссылка для входа на моем приложение, которое выглядит примерно так:ReturnUrl в ASP.NET MVC

<a href="/login?ReturnUrl=" + <%= Request.RawUrl %>>Login</a> 

Я хочу, чтобы обработать команду POST на странице входа в действие контроллера ниже:

[AcceptVerbs(HttpVerbs.Post)] 
public ActionResult Login(string returnUrl) 
{ 
    // Authenticate user 

    return Redirect(returnUrl); 
} 

проблема здесь в том случае, если RawUrl что-то с несколькими параметрами URL-адрес как «somepage? param1 = 1 & param2 = 2 & param3 = 3», то ReturnUrl, которая будет послана в Регистрационное действие усекается после первого амперсанд: "somepage? p aram1 = 1" .

Я пробовал UrlEncoding RawUrl, но это, похоже, имеет значение. Кажется, что структура ASP.NET MVC здесь UrlDecoding params url, прежде чем сопоставлять их с параметрами действия контроллера, что заканчивает отмену дополнительных параметров url, которые я хочу увидеть в моем параметре returnUrl.

Есть ли способ обойти это? Я знаю, что могу просто использовать Request.Path и проанализировать нужные мне значения, но я подумал, что сначала посмотрю, был ли более чистый подход.

ответ

36

Возможно, вы неправильно кодируете ссылки. Да, они должны быть закодированы. Вот как мы это делаем:

<a href="<%= Url.Action("Delete", "TimeRecord", 
    new RouteValueDictionary(new { id = timeRecord.AltId, 
    returnUrl=ViewContext.HttpContext.Request.Url.PathAndQuery })) %>"> 
+2

Это хорошо; PathAndQuery не включает домен, поэтому вы не уязвимы для злоумышленника, используя ваш сервер для перенаправления на свой сайт. – Will

+6

Я бы не сказал, что ты не уязвим. Люди могут изменять данные формы с помощью Fiddler и т. П. Вы все еще должны дезинфицировать URI на сервере. С другой стороны, хорошо не заполнять форму плохими данными. :) –

+0

Выглядит хорошо. Остерегайтесь, хотя 'ViewContext.HttpContext.Request.Url' может вернуть значение null, что означает, что у вас может быть« NullReferenceException ». –

-2

Хорошо, ваше решение имеет запах; Я не могу поместить палец на ссылку, описывающую атаку (она должна быть какой-то захватной сессией), но слепо перенаправление через querystring имеет GOT, чтобы быть дырой в безопасности. Кто-то отвечает или комментирует информацию, pls.

Не задумываясь над аспектом безопасности этого, одним из быстрых решений будет Base64, кодирующий весь URL-адрес возврата. Вот код, я полностью ganked от a blog, которые могут или не могут работать:

public static string ToBase64(this HtmlHelper me, string toEncode) 
{ 
     byte[] toEncodeAsBytes 
      = System.Text.ASCIIEncoding.ASCII.GetBytes(toEncode); 
     string returnValue 
      = System.Convert.ToBase64String(toEncodeAsBytes); 
     return returnValue; 
} 

public static string FromBase64(this HtmlHelper me, string encodedData) 
{ 
     byte[] encodedDataAsBytes 
      = System.Convert.FromBase64String(encodedData); 
     string returnValue = 
     System.Text.ASCIIEncoding.ASCII.GetString(encodedDataAsBytes); 
     return returnValue; 
} 
+2

. Я думаю, что атака выглядит примерно так: http://login.ebay.com/?returnUrl=www.MyFakeSiteThatLooksLikeEbay.com/lolyourescrewed.html поэтому люди нажимают на вашу ссылку, регистрируются в ebay и перенаправляются на ваш поддельный сайт, который выглядит как ebay, где вы попросите пользователя подтвердить данные своей кредитной карты. – Will

+0

Делает смысл. Решение, которое Craig Stuntz опубликовал, обращается к этому, используя вместо этого PathAndQuery. –

+2

Нет, нет: он передает хорошие данные без домена, но не учитывает тот факт, что если кто-то передал вам данные с помощью домена, вам все равно нужно проверить вход в методе контроллера – Jaykul

8

Убедитесь, что URL кодирования RawUrl перед его использованием.

<%= Url.Encode(Request.RawUrl) %> 

Это должно сделать это за вас.

+2

Это правильный путь делать это. – ajma

+0

Как говорится в первоначальном вопросе, это не работает. –

+0

Это прекрасно работает, оригинальное сообщение неправильно проанализировало, что происходит. –