locked
HOWTO: Verify that custom error handling solutions do not expose padding oracle RRS feed

  • Question

  • User32459769 posted

    UPDATE: I created a script to automate the verification process described here: http://forums.asp.net/p/1605099/4092891.aspx

    I've done some digging and come up with what I think is useful information for you if you have a custom error handling solution in place instead of or as well as the usual ASP.NET <customErrors> stuff.

    From comments on ScottGu's post it seem to be that the main suspect to be the actual padding oracle is WebResource.axd (possibly other axd's).

    • If you look in .NET Reflector at the IHttpHandler.ProcessRequest method in  System.Web.Handlers.AssemblyResourceLoader there's a call to Page.DecryptString early on.
    • This is the thing that will cause a HTTP 500 status to be returned if it fails, e.g. if the padding, etc in Request.QueryString["d"] is invalid
    • If the attacker manages to get the padding right, then it continues on, ultimately to call throw new HttpException(404...)

    It's this differentiation: is the padding correct (404) or not (500) that is at the root of the exploit: the padding oracle.

    If your error handling returns exactly the same response for both - it masks the oracle. To test if you're vulnerable externally, a simple test is to request both:

    • webresource.axd?d=foo
    • webresource.axd with no parameters

    and check using FiddlerTool, or FireBug that the entire response is identical for both including the status and all the headers (except for the Date header I guess!).

    Of course I may have missed something, but I hope this information helps you until the official fix comes out.

    Duncan Smart
    Twitter: @DuncanSmart
    Blog: blog.dotsmart.net

    Monday, September 20, 2010 6:12 PM

Answers

  • User186142853 posted

    Regarding your comments on trusting tampered data from the client.  It depends on what data you are referring to, as you have among other things, the cookie, viewstate, and postback data. 

    Postback data "tampering" cannot be detected, because it is itself intended to be specified/provided by the client.  You as the programmer writing an ASP.NET application should handle postback data as though it could contain anything, meaning considering how you use that data and esnuring you are not enabling a CSRF, XSS, or SQL Injection vulnerability by mishandling that data.  Unfortunately there are lots of ASP.NET articles that say "always do this and you'll be safe", but generally that is not foolproof.  When you get into complex applications you end up passing user suppled text through many layers where it ends up in a database, and then later might get displayed to some web page.  In such a scenario it's easy to forget some weeks down the road when you are creating a webpage to display some data from the database, and forget that that particular database field contains some user supplied text(a comment on a blog for example) and you procede to display it verbatim, not checking for malicious javascript, etc.  I find many of the mechnism's MS provides for dealing with these vulnerabilities to be useless, as they are provided as magic bullets without accompaning detailed explanations of how they work to prevent the threat.  I mean really?  We are not stupid, give us the facts MS.

    Viewstate data tampering can be detected and/or encrypted, see the "View State and Security Implications" section here abou signing viewstate(there are more detailed articles but this is the jist of it):

    http://msdn.microsoft.com/en-us/library/ms972976.aspx#viewstate_topic12

    As far as cookies, MS's documentation as far as I've seen is pretty vague and useless.

    The amount of misunderstanding of this vulnerability and past vulnerabilities is testament to Microsoft's poor documentation of ASP.NET's security model.  In security communities I believe this lack of openess is considered poor because a few malicious hackers can figure out the details and use them to their advantage, while the masses of uneducated developers lack the understanding of the security principles such that they can implement them properly. 

    MS's documentation runs along the lines of "do it like this, don't worry about why it is safe, just trust us that it is".  Usually this statement is made in the context of ideal conditions.  Thus developers don't know how to assess each scenario they encounter and implement a solution that is secure for the set of threats that the scenario is exposed to.  When developers encounter a scenario like this vulnerability, suddenly they don't know what to do because no one is really sure exactly how the pieces fit together, so that they can't figure out what to fix when one is broken.  There are already lots of blog posts on this where the author seems ot think they understand the issue and are giving advice or opinions that reveal them to not understand.

    Not too long ago I saw a slashdot post get accepted that basically stated that there was an SQL injection vulnerability in ASP.NET itself.  This of course turned out to be completely false, as it turned out to be a misunderstanding on the part of the author who did not understand that SQL injection vulnerabilities are specific to the implementation of the web application, not of the ASP.NET framework across the board.  Of course there were lots of anti-microsoft commenters jumping on the board wagon, and this was fueled by ASP.NET developers who themselves didn't understand enough about security in ASP.NET applications such that they could reallize for themselves that the article was completely misleading. 

    It's a really sad state of afairs and very frustrating when you are trying to ensure the applications you work on are secure you run into the same ignorance with coworkers.  I personally feel ashamed that I don't understand more about how all the pieces work together.  I have implemented desktop C# applications and PHP applications using various cryptography standards, and I always invested the time in making sure I understood all the pieces of the puzzle and often I found that I was missing something and could make adjustments.  With ASP.NET I instead feel helpless.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, September 21, 2010 4:11 PM

All replies

  • User1311437028 posted

    Nice post. I've been wondering where the 404 errors came into play in all of this. Do you know if the reason why asp.net is getting so much attention from the authors of the exploit is because of the webresource.axd handling, or is there an issue with say using the encrypted forms authentication cookie as the source cipher text? 

    Monday, September 20, 2010 8:49 PM
  • User-821857111 posted

    You don't need to have axd files deployed on your site to be vulnerable. Cookies expose cipher text, and do provide a source of encrypted material that can be used in such an attack.


    Monday, September 20, 2010 11:42 PM
  • User32459769 posted

    @Mikesdotnetting I'm not sure I understand what you mean. The attack is based on having an oracle (an active piece of code) on your site that will inform the attacker whether ciphertext padding is valid or not. A piece of ciphertext itself is useless to the attacker without an active oracle on the server. Perhaps there are other oracles in typical ASP.NET sites, but it seems the webresource.axd handler is the main one.

    You seem to be suggesting that ciphertext itself is something precious and should be protected, which goes against most people's definitions of ciphertext.

    Tuesday, September 21, 2010 3:44 AM
  • User32459769 posted

    @reklats webresource.axd acts a bit like a function returning a boolean, e.g. "isPaddingCorrect(...)" except that instead of true/false it returns HTTP 404 for true and HTTP 500 for false.

    Tuesday, September 21, 2010 3:48 AM
  • User2054773413 posted

    Great summary. I just can't understand why the information and workaround that Microsoft is offering is so misleading (as you can see from this forum and ScottGu's blog post comments, most people get it completely wrong or simply don't understand the issue.)

    I want to add two important things though:

    • WebResource.axd is not the only problem, there is also ScriptResource.axd which seems to work exactly the same and is often used also in ASP.NET MVC context.
    • If you implement a custom workaround that is still SEO- and REST-friendly, e. g. in a way that CryptographicExceptions occuring in *Resource.axd will be returned as 404 as well (anything else can stay as it is), make sure to implement the random sleep as in the official workaround, otherwise an attacker might still be able to use it as a padding oracle, not by looking at the returned status code, but by looking at the time the request needs to be processed on the server. (This is still not perfect, however an attacker would need tens or hundred times the number of requests as he would need without the random sleep, which should be more than enough time to detect the attack while it is running and block the attacker.)

    There are still two open questions for me:

    • Could manipulated ViewState act as a padding oracle? Posting mutated ViewState will probably always cause InvalidViewState exception and therefore HTTP status code 500, however maybe there is a difference in timing when InvalidViewState is internally caused by CryptographicException or by decrypted content not matching the view state tree of the page.
    • Is there also a timing-based vulnerability for FormsAuthentication cookies? Using an invalid cookie will always result in a 302 to the login page. But may be you could learn from the processing time why you get redirected to the login page: because there was a CryptographicException while trying to decrypt the cookie value, or because the decrypted cookie value just wasn't meaningful.

    Both problems (if they are problems) could be at least improved with random sleeps, too.

    Tuesday, September 21, 2010 7:12 AM
  • User32459769 posted

    @schmidt.de - thanks. I too was a bit frustrated by the vagueness, but MS obviously think that the less specific info out there is better. Whether this is the right thing to do is arguable: they'll be damned if they do, damned if they don't.

    In my tests ScriptResource.axd appears to always return 404s (on .NET 3.5 SP1 at least), so doesn't appear to act as an oracle in that way, but once the key is compromised can be used to serve up arbitrary files in the web site (e.g. web.config, etc). 

    ViewState as padding oracle: maybe

    FormsAuthModule: in my tests it always seem to do a 302 redirect, [EDIT: yes: there may be a timing issue there]

    Tuesday, September 21, 2010 7:26 AM
  • User-234406897 posted

    Your comments seem well thought out and the details are thin on the ground from the Microsoft side of things.

    But if you are correct then if you don't use webresource.axd or viewstate then this vulnerability is not a concern?

    Tuesday, September 21, 2010 7:47 AM
  • User32459769 posted

    @Rovastar No, it is an issue because even though you may not actively use webresource.axd and ViewState: their HTTP handlers still are. This is why I suggest doing your tests by actually probing your application externally and looking the for 404/500, etc behaviour I outlined.

    Tuesday, September 21, 2010 7:53 AM
  • User2054773413 posted

    @Rovastar: It doesn't matter if you use it. The question is if an attacker could use it ;) If you don't rely on it, you could explitily remove the HttpHandler for WebResource.axd. This should disable the attack vector, but see my open questions on how ViewState and the FormsAuth cookie might act as a padding oracle as well. I'm not sure about this, but if it was an issue, the workaround suggested by Microsoft wouldn't help as well!

    @Duncan: Thank you, interesting detail on ScriptResource.axd.


    Tuesday, September 21, 2010 7:59 AM
  • User-234406897 posted

    Thnaks for the replies I thought it would be the case but with so much (mis)information flying around I needed to be sure.

    Tuesday, September 21, 2010 8:34 AM
  • User1311437028 posted

    what I've been trying to figure out is why the authors of the exploit, who in thier original paper don't even mention Asp.Net, came out with the the claim that Asp.Net was such an easy target. I'm assuming that is was because of the different error codes returned by WebResource.axd. As you have pointed out, other features of Asp.Net, such as forms authentication could be used as an oracle using a timing based approach. However, it would seem that once you get into the realm of timing based oracles, any platform would be vulnurable.

    Things brings up another point, trusting data sent from the client. Right now, when using forms authentication, Asp.Net is trusting that the data has not been tampared with, as evident in the poet vs. DNN video. It would seem that forms authentication itself needs a bit of a fix, possibly in the form of some type of digital signature or other server side validation. An alternative would be to code something yourself on the server side, like sending an extra bit of random information with the forms auth cookie that you can then verify upcon reciept, or sending your own digital signature.

    And of course, there is still the issue of being able to download the web.config file.

    So, in summary, the primary attack vector seems to be the WebResource.axd, which makes it easy to launch a padding oracle attack against asp.net sites and obtain the machine key. Once the machine key is obtained, the web.config file can be downloaded, and the forms authentication cookie modified. There may be other related attack vectors and Microsoft in an effort to keep things somewhat under control has not publically disclosed them. So as many people have already pointed out, follow thier work around for now.

    What I'd like to see from microsoft is a fix that makes WebResource.axd less of an oracle, add a whitelist setting which requires developers to explictly list the files that can be downloaded by these included handlers, and some type of server side validation that the encrypted data (e.g. forms authentication cookie) has not been compromised. I'd also like to see a white paper that goes into some of these details from Microsoft, once the fix has been made available.

    Thoughts?

    Tuesday, September 21, 2010 10:48 AM
  • User32459769 posted

    @Reklats - yes FormsAuth probably needs an HMAC.

    > Once the machine key is obtained, the web.config file can be downloaded, and the forms authentication cookie modified.

    Interesting point about forging forms auth cookies: If your user account names are not easy to guess (e.g. admin user is not called "administrator") then the attacker has a harder time forging the cookies.

    Tuesday, September 21, 2010 11:08 AM
  • User1311437028 posted

    Consider a fairly public site that hosts a forum where everyone's username is probably displayed.  Pretty easy to figure out who moderators and administrators are. I was looking at the Orchard CMS code and they put the UserId itself in the cookie and I would not be surprised to see other applications doing that as well.

    This has given me a lot to think about in terms of security. I saw another post on here where someone was asking how to remove the WebResource and Script handlers, and if there were any other ones he should be aware of (someone brought up trace.axd). I think that this would be a worthy topic for someone at microsoft to address.

    Tuesday, September 21, 2010 2:09 PM
  • User186142853 posted

    Regarding your comments on trusting tampered data from the client.  It depends on what data you are referring to, as you have among other things, the cookie, viewstate, and postback data. 

    Postback data "tampering" cannot be detected, because it is itself intended to be specified/provided by the client.  You as the programmer writing an ASP.NET application should handle postback data as though it could contain anything, meaning considering how you use that data and esnuring you are not enabling a CSRF, XSS, or SQL Injection vulnerability by mishandling that data.  Unfortunately there are lots of ASP.NET articles that say "always do this and you'll be safe", but generally that is not foolproof.  When you get into complex applications you end up passing user suppled text through many layers where it ends up in a database, and then later might get displayed to some web page.  In such a scenario it's easy to forget some weeks down the road when you are creating a webpage to display some data from the database, and forget that that particular database field contains some user supplied text(a comment on a blog for example) and you procede to display it verbatim, not checking for malicious javascript, etc.  I find many of the mechnism's MS provides for dealing with these vulnerabilities to be useless, as they are provided as magic bullets without accompaning detailed explanations of how they work to prevent the threat.  I mean really?  We are not stupid, give us the facts MS.

    Viewstate data tampering can be detected and/or encrypted, see the "View State and Security Implications" section here abou signing viewstate(there are more detailed articles but this is the jist of it):

    http://msdn.microsoft.com/en-us/library/ms972976.aspx#viewstate_topic12

    As far as cookies, MS's documentation as far as I've seen is pretty vague and useless.

    The amount of misunderstanding of this vulnerability and past vulnerabilities is testament to Microsoft's poor documentation of ASP.NET's security model.  In security communities I believe this lack of openess is considered poor because a few malicious hackers can figure out the details and use them to their advantage, while the masses of uneducated developers lack the understanding of the security principles such that they can implement them properly. 

    MS's documentation runs along the lines of "do it like this, don't worry about why it is safe, just trust us that it is".  Usually this statement is made in the context of ideal conditions.  Thus developers don't know how to assess each scenario they encounter and implement a solution that is secure for the set of threats that the scenario is exposed to.  When developers encounter a scenario like this vulnerability, suddenly they don't know what to do because no one is really sure exactly how the pieces fit together, so that they can't figure out what to fix when one is broken.  There are already lots of blog posts on this where the author seems ot think they understand the issue and are giving advice or opinions that reveal them to not understand.

    Not too long ago I saw a slashdot post get accepted that basically stated that there was an SQL injection vulnerability in ASP.NET itself.  This of course turned out to be completely false, as it turned out to be a misunderstanding on the part of the author who did not understand that SQL injection vulnerabilities are specific to the implementation of the web application, not of the ASP.NET framework across the board.  Of course there were lots of anti-microsoft commenters jumping on the board wagon, and this was fueled by ASP.NET developers who themselves didn't understand enough about security in ASP.NET applications such that they could reallize for themselves that the article was completely misleading. 

    It's a really sad state of afairs and very frustrating when you are trying to ensure the applications you work on are secure you run into the same ignorance with coworkers.  I personally feel ashamed that I don't understand more about how all the pieces work together.  I have implemented desktop C# applications and PHP applications using various cryptography standards, and I always invested the time in making sure I understood all the pieces of the puzzle and often I found that I was missing something and could make adjustments.  With ASP.NET I instead feel helpless.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Tuesday, September 21, 2010 4:11 PM
  • User-234406897 posted

    I agree the details are thin on the ground but if teh workaround works then it is real issue. The is no evidence at this stage that the workaround doesn't work. Also the workaround is not so complex that an average dev couldn't implement it.

    Also I think there could be more potential vulnerabilities rather then what we know how are more obvious routes and the timing issues for asp3.5.1 and 4.0 alude to this.

    Oh as you mentioned PHP if you have a php app and asp.net is installed on the server then likely/possibility you also effected.

    Thursday, September 23, 2010 9:28 AM
  • User-234406897 posted

    @schmidt.de - thanks. I too was a bit frustrated by the vagueness, but MS obviously think that the less specific info out there is better. Whether this is the right thing to do is arguable: they'll be damned if they do, damned if they don't.

    In my tests ScriptResource.axd appears to always return 404s (on .NET 3.5 SP1 at least), so doesn't appear to act as an oracle in that way, but once the key is compromised can be used to serve up arbitrary files in the web site (e.g. web.config, etc). 

    ViewState as padding oracle: maybe

    FormsAuthModule: in my tests it always seem to do a 302 redirect, [EDIT: yes: there may be a timing issue there]

    I have been studing this a bit and I find that ScriptResource.axd can produce 404 and 500 errors in the wide.

    So I would remove this too if not needed.

    Friday, September 24, 2010 3:02 PM
  • User1656178272 posted

    The problem with WebResourceHandler and ScriptResourceHandler  is that the solely rely on Page.EncryptString. Page.EncryptString does exactly what is says; it encrypts and does NOT add authentication (Message Authentication Code or MAC). This is one off the the main reasons why they are vulnerable for padding-oracle-attacks.

    The FormsAuthentication.Encrypt(FormsAuthenticationTicket ticket) DOES add authentication to the plain text before it is encrypted using the same algorithms as Page.EncryptString does. Therefore the forms-authentication cookie is NOT vulnerable for padding-oracle attacks by itself (first authenticate-->then encrypt prevents padding-oracle-attacks, but only IF one cannot differentiate between a padding failure or a message authentication failure. FormsAuthentication.Decrypt returns an Internal Server Error in both cases. I think (but not sure) this is also the case with ViewState encryption)

    I quess this is how POET does it's trick :

    - First use WebResource.axd to determine the servers encryptionkey. By now we all know how to do that.

    - POET is now able to decrypt an authentication cookie but is unable to change it (due to the last 20 bytes containing a MAC)

    - But POET now can use the same padding-oracle techniques to determine the servers validation key (the mac is appended to the authentication-tickets plaintext, last 20 bytes. So use the same techniques on the last 20 bytes. The authentication-cookie HAS a padding-oracle-exploit for the servers validation key)

    - Now knowing both encryption- and validation keys, POET is able to tamper with anything that is protected with these keys, including the authentication cookie and viewstate.

    Conclusion: it all starts with WebResource.axd (or ScriptResource.axd) but after that you're lost. Nevertheless I would never rely on just removing these handlers an always implement the Microsoft Workarounds asap! Next to that, Use Reflector just as the the authors of POET did. Start with methods like Page.EncryptString versus FormsAuthentication.Encrypt.

    Saturday, September 25, 2010 4:22 PM
  • User1656178272 posted

    I was wrong.

    Authentication-cookies are validated using a hash function, not a real MAC. So they don't use-, and therefore expose, the servers ValidationKey. The servers EncryptionKey (exposed through WebResource) is enough to forge authentication-cookies.

    It must be ViewState that exposes the  ValidationKey but I can't understand how.

     

    Sunday, September 26, 2010 5:52 AM
  • User-1828574268 posted

    @Rovastar, ScriptResource.axd swallows the HTTP 500 errors and generates 404 in their place.  It's not a padding oracle (unlike WebResource.axd) because an attacker can not distinguish between the two; he only sees 404s (except if he is using some timing mechanism).

    @rneinhuis, Using a padding oracle to determine the encryption key is really difficult.  It is less difficult to use a padding oracle to forge an encrypted request to ScriptResource to download a particular file (in this case, Web.config).


    Tuesday, September 28, 2010 3:53 PM