ASP.NET page methods are only as secure as you make them
AJAX, ASP.NET, jQuery By Dave Ward. Posted September 8, 2011Note: This post is part of a long-running series of posts covering the union of jQuery and ASP.NET: jQuery for the ASP.NET Developer.
Topics in this series range all the way from using jQuery to enhance UpdatePanels to using jQuery up to completely manage rendering and interaction in the browser with ASP.NET only acting as a backend API. If the post you're viewing now is something that interests you, be sure to check out the rest of the posts in this series.
One of the most persistent misconceptions about ASP.NET’s page methods is the notion that they have some intrinsic protection against requests that don’t originate from the page where they’re defined. Since a page method’s code resides within a page’s code-behind file, it’s intuitive to assume that those methods benefit from some form of inherent security.
Unfortunately, that is not the case.
Exploiting your page’s insecurities
In case it’s hard to believe these code-behind methods truly are so easily accessible, let’s take a look at a quick example. Let’s say you have a page method that returns sensitive business information, like so:
[WebMethod] public static int SecretFormula() { return 42; }
Assuming that method is defined in a Default.aspx file’s code-behind, located in a folder named TopSecret, here’s a bit of jQuery you could use to request the secret formula from any page on the site:
$.ajax({ url: '/TopSecret/Default.aspx/SecretFormula', type: 'POST', contentType: 'application/json', data: '{}', success: function(result) { alert(result.d); } });
In fact, you can even make that request from a plain HTML file. In this example, I’m making the request right from a simple HTML file named index.htm:
Not only is the request not originating from the ASPX file that contains the page method, that request wasn’t originating from an ASPX file at all!
Is this really a problem?
You might be asking yourself if this is really a problem to begin with. After all, you aren’t very likely to write client-side code that requests sensitive data unless you actually need that data, regardless of whether you write that code on an ASPX page, HTML page, or anywhere else.
The trouble is, a villain could land on any of your site’s pages, open up Firebug, and start probing for weaknesses like this one. In this case, the obscurity of the exact location of the page method might lead you to a false sense of security, but if an attacker has any knowledge of your system’s architecture then the door is wide open.
Even more troubling, as long as an attacker uses POST requests with an application/json Content-Type, they could use a tool as simple as Fiddler to interrogate your site’s services remotely. A few lines of server-side code, and your competition could set up a site driven by the page method APIs on your site that you thought were private!
A fixable problem
Page methods aren’t indefensible against the shenanigans of external interlopers though. You can secure them with ASP.NET’s built-in authorization mechanism, just as you would any other ASPX page (or ASMX service). In fact, if you secure an ASPX page with ASP.NET authorization, page methods defined in its code-behind are automatically equally secure.
To deny unauthenticated access to methods in our TopSecret folder, adding an authorization entry to the web.config in that folder is all that’s necessary:
<?xml version="1.0"?> <configuration> <system.web> <authorization> <deny users="?" /> </authorization> </system.web> </configuration>
Now, an unauthenticated user trying to access the SecretFormula method from index.htm (or anywhere else, without authenticating first) is denied access:
Of course, there are a variety of ways to control access to these methods. You might test to see which role a user’s in and respond accordingly, or you might only need to verify some token stored in the Session.
Regardless of the particular mechanism, the key is to remember that none of this is automatic and that you must be mindful of regulating access to your page methods.
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.





This is very interesting – I have been looking in to securing my .asmx web services recently. I use such for my javascript to interact with the server.
I had some code setup to pass values in the http header of the request that are validated on the server side to test that source was from the javascript but was not happy with my approach.
How could I setup what you outlined to allow calls to my .asmx files located in a “Services” folder from my javascript, which is within my solution, but deny it from any other source?
Your help would be great on this.
Thanks.
Are the users that need to access those .asmx files authenticated with your site? Do they have Session state?
No they are not authenticated, they are just normal visitors to site that trigger asmx calls via javascript. I want to allow any calls from javascript and disallow any calls made directly to the services, not via the applications javascript. Not sure if this is possible or not but after reading your article I thought it may be.
That can be tough to do comprehensively. One fairly reliable approach is to use an anti-CSRF library to embed an anti-CSRF token in the page, then include that as a data parameter in requests to your services, and verify that token in your service methods. That lets you at least verify that the service request is a result of someone having actually requested one of your pages.
Ultimately though, anything you expose without authentication can be scraped. It’s virtually impossible to totally prevent that from happening.
Thanks for your help Dave, your article has raised some interesting questions.
Hi Dave,
You just described a CSRF attack, but your solution does not go far enough to fix it.
Basically, regardless of the type of authentication your website uses, you are still vulnerable if your user is currently authenticated to your website. We can set up our own malicious “index.htm” on our own server, lure the user to it, and since the user is authenticated to your website, our “index.htm” can have its way with your website.
For an excellent background, google the PDF titled “Cross-Site Request Forgeries: Exploitation and Prevention” by William Zeller and Edward W. Felten. I especially liked the vulnerability that was exposed by a major banking institution.
Ted.
I don’t believe this particular example would be vulnerable to a CSRF attack. You could use a cross-domain-posting form to successfully make a request for the secret formula with the user’s auth cookie, but you wouldn’t be able to capture the result.
Of course you’re right that CSRF is always something to keep in mind – definitely a good point to bring up. This post wasn’t intended so much to address the details of web security, but to raise awareness that security is something that’s important to remember (at all) when working with ASP.NET page methods.
Thanks Dave,
This is a nice beginner article about PageMethod security. I agree its not as obvious to newcomers that PageMethods are not part of the page, for advanced developers the clue of defining it static should be enough.
I have 2 questions regarding CRSF over the index.htm page at another server, firstly if the cookie is defined as a domain cookie, can the index.htm page access and pass this cookie to the native server?
If yes, why do you say the index.htm page will not be able to capture the result through a json request?
Your first point is correct. Our Page Method’s auth cookie would be transmitted with requests from index.htm sitting on a third-party site. If that site did something like set up a form pointing to the Page Method and called a form.submit() on it, those POSTs would appear legitimate. That’s where CSRF is particularly dangerous, because an attacker with knowledge of your site can POST values in with the user’s authentication, like a password update, account transfer, etc. We’re still relatively safe in this case though because of the additional Content-Type requirement (the malicious form would POST with a Content-Type of application/x-www-form-urlencoded instead of application/json).
However, consuming a response from a third-party site is a different story. The form-based attack will load a new page outside the attacker’s control (or, protected from DOM access if attempted within an iframe). A simple $.ajax() call like my example will fail since it’s no longer same-origin. That can be circumvented in a browser that supports CORS, but only if explicitly allowed via HTTP header on the receiving end.
Just about the only third-party vector for an attack that steals data from an authentication-protected endpoint on your site is one that requires the endpoint respond to GET requests and respond with an array. That’s why ASP.NET’s JSON endpoints generally try to dissuade you from returning JSON in response to GETs, and it’s specifically why the “.d” wrapper was added to Page Methods and ScriptServices.
really ? what you’re saying here is applicable to everything, I’ll resume your article in a sentence : “if you create an access to sensitive data, it can be … well … accessed, unless you … hmm well filter the access”.
You and I know that, but I wrote this post because I see a lot of developers using page methods under the misconception that the framework is doing something transparently to protect them from outside access. It’s easy to understand how someone might think that since they’re defined in code-behind, beside other code that is protected from unwanted outside access, and the default client-side syntax for calling them (
PageMethods.MethodName) obscures what’s going on a bit.I would have thought it was obvious that not securing a web service/web methods would mean anyone could make a call to them… ASP.NET authorisation is there for a reason after all.
Every method on our service checks the calling user to make sure they are logged in and have a valid session id tagged to their user details, anything less is idiocy.
If you already understand all of that, this post isn’t for you.
However, it’s not “idiocy” that some other developers don’t understand this yet, especially considering how many other things the framework does handle transparently. No one’s berating us for letting the framework automatically handle AES encryption on the ASP.NET auth tokens, yet that’s so different from someone new to page methods assuming that
PageMethods.MethodNamemight have some built-in framework magic too.Everyone has to start somewhere.
Doesn’t adding
If (Request.Path.IndexOf(Chr(92)) >= 0 Or _
System.IO.Path.GetFullPath(Request.PhysicalPath) Request.PhysicalPath) Then
Throw New HttpException(404, “Not Found”)
Exit Sub
End If
to the Application_BeginRequest method in a Global.asax file help with this?
PS – what about the Page ValidateRquest directive? Is thatr elevant to this? (Really showing my ignorance here I know!)
I don’t really get the point of this post. At first I thought that you were saying that any public method on the code-behind could be accessed through an HTTP request, and that scared the heck out of me, but then I looked more carefully, and I saw you explicitly put the [WebMethod] attribute and thus exposed your method to be called from the client-side…
Therefore, the developer is always aware that the method is exposed… He made that happen on purpose.
That’s easy to say if you already understand how page methods work and that the
[WebMethod]attribute opens them up to HTTP access from anywhere. However, there are many who don’t fully understand those things – you might be surprised just how many. If you do already understand, then this post isn’t for you.Let’s see if I have this right. You have to use the WebMethod attribute for this exploit to work. If you leave the WebMethod attribute off, the code behind can not be exploited. Just watch where you use the WebMethod attribute, correct?
You’ve got it right.
Than you Dave! Your article is helpful to me.
Thanks for article Dave. Quite interesting topic.
I’ve asked this question many times at many places, but no one ever gave me a satisfying answer.
Frustrating part is, no one from Microsoft published any guide lines warning developers about all the various ways you can hack around it especially when two users have the exact same roles, say both users are Facebook users.
Thanks for bringing it up.
Hey Dave, thanks for this article but I have question now:
What if I am using my own Session variables instead of using Microsoft Asp.NET built-in authentication system. I am using my own Login form, my own Session state check and so on. Is this solution working for this case as well? Since it seems this solutions works integrated with built-in authentication system.
Thanks.
Sure, you can use a custom authentication/authorization scheme. It’s just not quite as convenient as ASP.NET’s built-in providers.
In the page method, check your Session variable and throw an HttpException if the request is unauthorized.
Thanks for the article.
Some of us are still learning ASP.NET so this stuff is always good to point out. I probably would have made this assumption myself.
great article ,
but as a beginner I’ve a problem here .
does “Asp.NET’s Page Methods” mean “all methods” in the code-behind of a page or just “public methods” , as your sample says ?
I mean even a button click Method is accessible in this way ?
I searched and got something about it , sorry , I asked before searching ,
I can say that answer to my question is “No , Just those which have [webMethod] attribute have this problem “, right ?
That’s right.
sorry , but I’m just one of those newcomers to .Net coding ,
Then there is still one more question
as I read in MSDN :
“adding this attribute to a method within an XML Web service created using ASP.NET makes the method callable from remote Web clients …” .
so when someone add this attribute to their method means they want it to be accessible from remote systems. then what is the risk ?!
do you mean accessible from other domains and applications or servers ?
Yes, the
[WebMethod]attribute exposes a method to access from any machine that can make a POST request.Hi there,
My page method calls don’t seem to work if i introduce i login page.
Default.aspx is where the webmethod is applied, but when a user isn’t authenticated on my site, the webconfig file directs the URL to Login.aspx. After successfully logging in they are then redirected back to Default.aspx upon which the Ajax call isn’t being fired properly, as there is a Jquery error.
without the login page, this all works fine.