Может кто-нибудь предложить абстрактный базовый класс для предотвращения XSRF в .NET 2.0+ - PullRequest
0 голосов
/ 20 октября 2008

Я ищу решение для абстрактного базового класса или мастер-страницы, которое не позволит никому делать XSRF, используя и токен, и ttl. Кто-нибудь может указать мне правильное направление?

Редактировать: идеальное решение будет использовать cookie, который поставщик членства по умолчанию отправляет клиенту.

Ответы [ 2 ]

3 голосов
/ 21 октября 2008

Вы можете разместить скрытое поле на своей главной странице, сгенерировать ключ во время события Page_Load вашей главной страницы, назначить ключ в качестве значения скрытого поля и затем добавить это значение в свой файл cookie. Тогда вы просто сравните эти значения.

0 голосов
/ 23 октября 2008

Я запустил базовый класс, который может наследовать главная страница. Я предпочел использовать viewstate вместо того, чтобы скрыть ввод, потому что при таком подходе мне не нужно беспокоиться о множественных формах на странице и т. Д. Это также требует немного больше работы, чтобы найти это значение, чем простой «просмотр источника»

Ниже приведены некоторые проблемы, которые я пытаюсь исправить.

  • Когда я обновляю страницу (не post-back) состояние просмотра и скрытое вход, (когда я начал этот подход) значения не обновляются, как файл cookie

  • Когда я перехожу на новую страницу внутри мое приложение, новая страница запускается без действительного состояния и, следовательно, мое сравнение не удается в этом случае ...

Ниже моя работа в процессе;)

 public class PreventXSRF : MasterPage
 {

     HttpCookie mCookie = null;
     FormsAuthenticationTicket mPreviousAuthenticationTicket = null;
     FormsAuthenticationTicket mNewAuthenticationTicket = null;

     public bool IsXSRF()
     {
         if ((Request.Cookies(".ASPXAUTH") != null)) {
             mCookie = Request.Cookies(".ASPXAUTH");
             //get the current auth ticket so we can verify the token (userData) matches the value of the hidden input
             mPreviousAuthenticationTicket = FormsAuthentication.Decrypt(mCookie.Value);
         }
         else {
             ///'the membership cookie does not exist so this is not an authenticated user
             return true;
         }

         //** ** **
         // verify the cookie value matches the viewstate value
         // if it does then verify the ttl is valid
         //** ** **

         if ((mPreviousAuthenticationTicket != null)) {
             if (mPreviousAuthenticationTicket.UserData == Token) {
                 if ((TTL != null)) {
                     if (Convert.ToDateTime(TTL).AddMinutes(5) < DateTime.Now()) {
                         ///'the ttl has expired so this is not a valid form submit
                         return true;
                     }
                 }
                 else {
                     //** ** **
                     // ?? what about a hack that could exploit this when a user tries to BF
                     // a value for the token and simply keeps the viewstate for ttl null ??
                     //** ** **
                 }
             }
             else {
                 //** ** **
                 // ?? I hit this when I navigate to another page in the app (GET)
                 // in this event, it was hit because the cookie has a valid token
                 // but the page is new so viewstate is not valid ... ??
                 //** ** **
                 ///'the cookie value does not match the form so this is not a valid form submit
                 return true;
             }
         }
         else {
             ///'the authentication ticket does not exist so this is not a valid form submit
             return true;
         }

         //** ** **
         // if the code gets this far the form submit is 99.9% valid, so now we gen a new token
         // and set this new value on the auth cookie and reset the viewstate value
         // so it matches the cookie
         //** ** **

         //gen a new ttl and set the viewstate value
         TTL = GenerateTTL();
         //gen a new token and set the viewstate value
         Token = GenerateToken();

         if ((mPreviousAuthenticationTicket != null)) {
             //** ** **
             // create a new authticket using the current values + a custom token
             // we are forced to do this because the current cookie is read-only
             // ** ** **
             mNewAuthenticationTicket = new FormsAuthenticationTicket(mPreviousAuthenticationTicket.Version, mPreviousAuthenticationTicket.Name, mPreviousAuthenticationTicket.IssueDate, mPreviousAuthenticationTicket.Expiration, mPreviousAuthenticationTicket.IsPersistent, Token);
         }
         else {
             ///'TODO: if no auth ticket exists we need to return as this won't be valid
         }

         if ((mCookie != null)) {
             //** ** **
             // take the new auth ticket with the userdata set to the new token value
             // encrypt this, update the cookie, and finally apply this to the users machine
             //** ** **
             mCookie.Value = FormsAuthentication.Encrypt(mNewAuthenticationTicket);
             Response.Cookies.Add(mCookie);
         }
         else {
             ///'TODO: if no cookie exists we need to return as this won't be valid
         }

         //if we got this far without a return true, it must not be a xsrf exploit so return false
         return false;
     }

     private string GenerateToken()
     {
         RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
         byte[] randBytes = new byte[32];
         random.GetNonZeroBytes(randBytes);
         return Convert.ToBase64String(randBytes);
     }

     private string GenerateTTL()
     {
         return DateTime.Now();
     }

     private string TTL {
         get { return ViewState("TTL"); }
         set { ViewState("TTL") = value; }
     }

     private string Token {
         get { return ViewState("Token"); }
         set { ViewState("Token") = value; }
     }

 }
...