locked
CSRF in a web app RRS feed

  • Question

  • User1310055179 posted

    Hi,

    I have a vs2013 web app and I am trying to add csrf protection.

    I tried inserting the following code to the MasterPage:

    protected void Page_Init(object sender, EventArgs e)
            {
                // The code below helps to protect against XSRF attacks
                var requestCookie = Request.Cookies[AntiXsrfTokenKey];
                Guid requestCookieGuidValue;
                if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
                {
                    // Use the Anti-XSRF token from the cookie
                    _antiXsrfTokenValue = requestCookie.Value;
                    Page.ViewStateUserKey = _antiXsrfTokenValue;
                }
                else
                {
                    // Generate a new Anti-XSRF token and save to the cookie
                    _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
                    Page.ViewStateUserKey = _antiXsrfTokenValue;
     
                    var responseCookie = new HttpCookie(AntiXsrfTokenKey)
                    {
                        HttpOnly = true,
                        Value = _antiXsrfTokenValue
                    };
                    if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
                    {
                        responseCookie.Secure = true;
                    }
                    Response.Cookies.Set(responseCookie);
                }
     
                Page.PreLoad += master_Page_PreLoad;
            }
     
            protected void master_Page_PreLoad(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    // Set Anti-XSRF token
                    ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
                    ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
                }
                else
                {
                    // Validate the Anti-XSRF token
                    if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
                        || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
                    {
                        throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
                    }
                }
            }

    In addition, the application also has a page that is not a content page and it can be opened from one of the content pages using <a> tag (example_Form.aspx).

    I added the following code to the example_Form.aspx:

    ////anti forgery variables
            private const string AntiXsrfTokenKey = "__AntiXsrfToken";
            private const string AntiXsrfUserNameKey = "__AntiXsrfUserName";
            private string _antiXsrfTokenValue;
     
            protected void Page_Init(object sender, EventArgs e)
            {
                // The code below helps to protect against XSRF attacks
                var requestCookie = Request.Cookies[AntiXsrfTokenKey];
                Guid requestCookieGuidValue;
                if (requestCookie != null && Guid.TryParse(requestCookie.Value, out requestCookieGuidValue))
                {
                    // Use the Anti-XSRF token from the cookie
                    _antiXsrfTokenValue = requestCookie.Value;
                    Page.ViewStateUserKey = _antiXsrfTokenValue;
                }
                else
                {
                    // Generate a new Anti-XSRF token and save to the cookie
                    _antiXsrfTokenValue = Guid.NewGuid().ToString("N");
                    Page.ViewStateUserKey = _antiXsrfTokenValue;
     
                    var responseCookie = new HttpCookie(AntiXsrfTokenKey)
                    {
                        HttpOnly = true,
                        Value = _antiXsrfTokenValue
                    };
                    if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
                    {
                        responseCookie.Secure = true;
                    }
                    Response.Cookies.Set(responseCookie);
                }
     
                Page.PreLoad += master_Page_PreLoad;
            }
     
            protected void master_Page_PreLoad(object sender, EventArgs e)
            {
                if (!IsPostBack)
                {
                    // Set Anti-XSRF token
                    ViewState[AntiXsrfTokenKey] = Page.ViewStateUserKey;
                    ViewState[AntiXsrfUserNameKey] = Context.User.Identity.Name ?? String.Empty;
                }
                else
                {
                    // Validate the Anti-XSRF token
                    if ((string)ViewState[AntiXsrfTokenKey] != _antiXsrfTokenValue
                        || (string)ViewState[AntiXsrfUserNameKey] != (Context.User.Identity.Name ?? String.Empty))
                    {
                        throw new InvalidOperationException("Validation of Anti-XSRF token failed.");
                    }
                }
            }

    Do I also need to add a hidden field to the content page? 

    To test my code I wrote the following HTML  to try and hack my app:

    <html>
    <head>
        <title>test csrf forgery</title>
        <script type ="text/javascript">
            document.form1.submit();
            document.getElementById("ButtonSaveOkay").click();
        </script>
    </head>
    <body>
        <form method="post" action="http://www.example.com/example_Form.aspx?TABLE=MD&STATUS=1" onsubmit="javascript:return WebForm_OnSubmit();" id="form1">
            <div class="aspNetHidden">
                <input type="hidden" name="__LASTFOCUS" id="__LASTFOCUS" value="" />
                <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />
                <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />
                <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUKMTIzNjYzNTUyOQ8PFhIeBmZvcm1JRGYeEVBvc3RCYWNrQ29udHJvbElEZR4GcmVjU3RyFRMAAAAAAAAAAAAAAAAAAAAAAAAAHg9fX0FudGlYc3JmVG9rZW4FIDg0ZTZlNWFkYjA4YzQ1MTBhZjAxZjAxNWJiMDI5MjY3HhJfX0FudGlYc3JmVXNlck5hbWUFBnNoYXZpdB4IYXBwX0NvZGUFAk1EHhJwZXJtaXNzaW9uc19wYXJhbXMVCgExATEBMQExATEBMQExATEBMQExHg5UQkxfY29kZV9hbGlhcwUCTUQeCmZvcm1TdGF0dXMCAWQWAgIDDxYCHgVzdHlsZQUZaGVpZ2h0OjI0MW1tO3dpZHRoOjMzMm1tOxYCAgUPZBYCZg9kFgQCAQ8PFgQeBVdpZHRoGwAAAAAAwHRABQAAAB4EXyFTQgKAAmQWHAIBDw8WAh4HVmlzaWJsZWhkZAIDDw8WAh8MaGRkAgUPDxYCHwxoZGQCBw8PFgIfDGhkZAIJDw8WCB4EVGV4dAULVXBkYXRlIE1vZGUeCUJhY2tDb2xvcgkApv//HglGb3JlQ29sb3IJ/////x8LAgxkZAILDw8WBB4ISW1hZ2VVcmwFH34vSW1hZ2VzL21lbnUtZmlyc3QtaWNvbl9CVy5wbmceB0VuYWJsZWRoZGQCDQ8PFgQfEAUifi9JbWFnZXMvbWVudS1wcmV2aW91cy1pY29uX0JXLnBuZx8RaGRkAg8PDxYCHxAFFn4vSW1hZ2VzL3NhdmUtaWNvbi5wbmdkZAIRDw8WBB8QBR5+L0ltYWdlcy9tZW51LW5leHQtaWNvbl9CVy5wbmcfEWhkZAITDw8WBB8QBR5+L0ltYWdlcy9tZW51LWxhc3QtaWNvbl9CVy5wbmcfEWhkZAIVDw8WAh8MaGRkAhcPD2QWAh8JBUFjdXJzb3I6cG9pbnRlcjtwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0OjMyNW1tO3RvcDowcHg7ei1pbmRleDo1MDAwO2QCGQ8PFgIfDGgWAh8JBUFjdXJzb3I6cG9pbnRlcjtwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0OjMxMm1tO3RvcDowcHg7ei1pbmRleDo1MDAwO2QCGw8PFgIfDGgWAh8JBUFjdXJzb3I6cG9pbnRlcjtwb3NpdGlvbjphYnNvbHV0ZTtsZWZ0OjMyMm1tO3RvcDowcHg7ei1pbmRleDo1MDAwO2QCAw9kFgJmD2QWAgIBD2QWAgIFD2QWAmYPZBYCAgUPPCsAEQIBEBYAFgAWAAwUKwAAZBgCBR5fX0NvbnRyb2xzUmVxdWlyZVBvc3RCYWNrS2V5X18WBgUFZmlyc3QFBHByZXYFBHNhdmUFBG5leHQFBGxhc3QFC2NhbmNlbF9lZGl0BQlHcmlkVmlldzEPZ2QX4X+IaA2x4/eX9oSreJxyBUBi1YaUmTent46Jf56oFA==" />
     
            </div>
     
     
            <h1>test csrf forgery</h1>
            <div id="form_fields">
                <div id="UpdatePanel_fields">
                    <div id="MainForm" style="text-align:center;">
                        <input name="x_2" type="text" readonly="readonly" id="x_2" size="6" style="background-color:#EBEBE4;left:2mm;top:1mm;position:absolute;z-index:2;text-align:center;font-size:12px;font-family:monospace;" />
                        <input name="D_5" type="text" id="D_5" value="20180101" />
                        <input name="D_7" type="text" id="D_7" value="20181231" />
                        <input type="submit" name="ButtonSaveOkay" value="save" id="ButtonSaveOkay" />
                    </div>
                </div>
            </div>
        </form>>
    </body>
    </html>

    I logged in to my example.com application and then I opened the HTML code located on my computer. I clicked the submit button and I managed to save a new record using the form.

    What am I missing? What am I doing wrong? 

    I tried running the html code while directing the form action to my localhost, while debugging, and I could see that the HTML file has no problem running server side script. The token is the same. a new Anti-XSRF token is never created.

    I would really appreciate your help.

    Monday, August 27, 2018 2:05 PM

All replies