A secure implementation of Page.IsPostBack?

别来无恙 提交于 2019-12-05 10:46:18

I had a project a couple of years ago where we had some penetration testing done on the code. They flagged up the fact that by default IsPostback doesn't check the http verb. To address this I created an abstract Page class with its' own implementation of IsPostback that shadows the default implmentation:

Public Class ProjectPage : System.Web.UI.Page

    public new bool IsPostBack()
    {
        return (Page.IsPostBack && Request.HttpMethod.ToUpper() == "POST");
    }

End Class

This allows you to do testing on the http verb, but you could easily extend the method to do other checks as well.

OK, here's what I think is the solution: Page.IsPostBack is already secure enough, as long as event validation is enabled. Let me explain my reasoning below and I'd be happy for anyone to add a comment if I've gotten something wrong.

In order for a spoof postback to be posted to ASP.net and trigger a control's OnClick event, with event validation enabled, the client has to send the __EVENTVALIDATION form field. This field contains a uniquely-generated string that basically tells ASP.net which controls a postback event for that page may have originated from. If you try to spoof a postback for a button which has had .Visibility = false set on it, you'll see an event validation error message. So, it looks like you can't directly spoof a click on a hidden control.

What about spoofing a postback of one of the existing buttons on the page that you has been rendered (ie. you do have permission to view/click on it)? Well, you can send the postback to the page, but you need to submit a valid __VIEWSTATE or you'll just get a 'state information invalid' error. In order to have a valid __VIEWSTATE, you already need to have loaded the page as a non-postback, right? That means that the security-checking code will have executed at least once, hiding the appropriate controls and recording that in the __VIEWSTATE. So, when you post the spoof postback, yes it will cause Page.IsPostBack to be true, but it doesn't matter because the submitted __VIEWSTATE will already have been generated on the previous non-postback page load to hide the content that you shouldn't have access to... so, you can spoof a postback, but only by passing a __VIEWSTATE that has been previously generated by a non-postback page load.

So, because of these facts, it should be safe to only put security-checking code inside a Page.IsPostBack == false block. This must always get run once before a valid postback can be submitted to the ASP.net server. Or am I missing something?

A cookie is a much better mechanism for your needs. The cookie is a token that could only have been generated by the server and vouches for the holder of the token certain claims such as having signed in recently and for having certain permissions and/or preferences. Some of these features are built into FormsAuthentication. You can implement your own cookie mechanism, but you should research secure cookie protocols because there are several non-obvious security considerations.

The benefit is that you don't have to go to the database on every request, you just trust it. This could also be a good strategy for weathering certain DoS attacks because you can tier your app such that a dedicated device in front of your app servers validates tokens too and throws out invalid requests.

If cookies aren't allowed, you can send the token as part of the url, as formsauth allows, or as a form field in your postback. But that's more work to manage then cookies, IMHO, once you've gone through the trouble of generating a proper token.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!