ViewState: Still Mis-understood

April 22, 2013 by · Comments Off on ViewState: Still Mis-understood
Filed under: Development, Security 

Here we are in 2013 and we are still having discussions about what ViewState is and how it works.  For you MVC guys and gals, you are probably even wondering who is still using it.  Although I do find it interesting that we have ViewState in Webforms but not in MVC even though MVC has the Views.   Does that make anyone else wonder? 

A few weeks ago, I was in the midst of a Twitter discussion where there was some different ideas about ViewState floating around.  It really started when the idea came across to use Encryption for your ViewState to prevent tampering.  While I do agree 100% that encrypting your ViewState will prevent someone from tampering it, I feel that it adds quite a bit of overhead when it shouldn’t be needed.  A general rule of thumb that I use with ViewState is that you shouldn’t be storing anything sensitive in it.  There are other mechanisms for storing sensitive information, and the client is your last, last, last choice (or shouldn’t be a choice at all). 

My response, why not just use ViewStateMac?  The whole point of ViewStateMac is to protect the ViewState from tampering.  It is on by default, and doesn’t require encrypting all of your ViewState and then decrypting it.

For those of you who don’t know, ViewState is a .Net specific client-side storage mechanism.  By default, it is used to store the state of your view.  I know, webforms don’t have views per se..  But that is what it does.  It stores the values for your label controls, the items in your drop down lists, data in your datagrid, etc.  This data is then used on a postback to re-populate the server-side controls.  For example, if there is a label on the form (say copyright), when the form is submitted and re-displayed the text for that label is populated automatically from the ViewState.   This saves the developer from having to reset the value on every response. 

Another example is with a drop down list.  All of the values are stored in the ViewState.   When the user submits the form, the drop down list is re-populated from the ViewState.  This does a few things.  First, it keeps the developer from having to populate the list from the original data source for every response and request.  Of course, there are other ways to save the hit to the original data source and store it in session or some other quick storage.  Second, it is basically a version of a reference map.  When done correctly, it is not possible for an attacker to submit a value that didn’t exist in the drop down list.  This really helps when it comes to parameter tampering on these fields.   Of course there are ways to program this where it doesn’t protect you but that is beyond this post. 

So far, everything we have looked at in ViewState is visible anyway.  Why encrypt it?

I have seen some really bad things stored in ViewState.   I have seen RACF usernames and passwords, full connection strings, and lots of other stuff.  To be blunt, those should never be in there.

So again, if we are not storing this sensitive information in ViewState, why encrypt it?   If the answer is just tamper protection, my opinion is to just go with the ViewStateMac.

When I do an assessment on a web application, one of my favorite things to do is look at the ViewState.  Of course, I love to see when MAC is not enabled.  Most of the time, ViewStateMac is enabled and I don’t get much from the ViewState.  I get confirmation, that the developers aren’t storing sensitive information in there and they are properly protecting it.  When I see that the ViewState is encrypted, it sends off some bells in my head.  Why are they encrypting this ViewState?   Maybe they do have something to hide.  Maybe there is a reason for me to dig into it and see if I can’t break the encryption to see what it is. 

One additional point I would like to make is that ViewState is not meant to be storage across pages.  It is meant to be storage for a single web form. 

I was called out on the Twitter chat as loving ViewState.  I wouldn’t go that far, but I don’t have much ill will toward it.  It has a purpose and can be quite useful if used properly.  Of course, it can be a great help to an attacker if not used properly. 

I enjoyed the discussion on Twitter, unfortunately sometimes 140 characters is not really enough to get ideas across.  I would be curious if anyone has any other thoughts on this topic on how ViewState should work and pros and cons for encrypting ViewState over just setting ViewStateMac.  Feel free to reach out to me.

Hidden Treasures: Not So Hidden

April 5, 2013 by · Comments Off on Hidden Treasures: Not So Hidden
Filed under: Development, Security, Testing 

For years now, I have run into developers that believe that just because a request can’t be seen, it is not vulnerable to flaws.  Wait, what are we talking about here?   What do you mean by a request that can’t be seen?  There are a few different ways that the user would not see a request.  For example, Ajax requests are invisible to users.   What about framed pages?  Except for the main parent, all of the other pages are hidden from the user’s view.  These are what I would call hidden requests. 

Lets use a framed site as an example.  Lets say that a page has multiple frames embedded in it, each leading to a different page of content.  From a user perspective, I would normally only see the URL in the Address Bar of the parent page that contains the other frames.  Although each frame has its own URL, I don’t see it natively.  This type of out-of-site out-of-mind thought process often leads us to over look the security of these pages. 

There are all sorts of vulnerabilities that can be present in the scenario above.  I have seen SQL injection, Direct Object Reference and Authorization issues.  BUT THEY ARE HIDDEN??

To the naked eye, yes, they are hidden.  Unfortunately, there are numerous tools available to see these requests.  Web Proxies are the most popular, although there are some browser add-ins that also may do the trick.  The two proxies I used the most are Burp and Fiddler.  Both of these tools are used to intercept and record all of the HTTP/HTTPS traffic between your browser and the server.  This means that even though I might not see the URL or the request in the browser, I will see it in the proxy. 

Many years ago, I came across this exact scenario.  We had a website that used frames and one of the framed pages used parameters on the querystring.  This parameter just happened to be vulnerable to SQL Injection.  The developer didn’t think anything of this because you never saw the parameters.  All it took was just breaking the page out of the frame and directly modifying the value in the address bar, or using a proxy to capture and manipulate the request to successfully exploit the flaw. 

It was easy to fix the problem, as the developer updated his SQL to use parameterized queries instead of dynamic SQL, but this just shows how easy it is to overlook issues that can’t be seen.

In another instance, I saw a page that allowed downloading files based on a querystring value.  During normal use of the application you might never see that request, just the file downloading.  Using a proxy, it was easy to not only identify the request, but identify that it was a great candidate for finding a security flaw.  When we reported the flaw, I was asked multiple times about how I found the flaw.  It was another case where the developer thought that because the request wasn’t displayed anywhere, no one would find it.

There are many requests that go unseen in the address bar of the web browser.  We must remember that as developers, it is our responsibility to properly secure all of our code, whether or not they appear in the address bar.  I encourage all developers to use web proxies while testing and developing their applications so they can be aware of all the transactions that are actually made. 

ASP.Net and CSRF

January 7, 2013 by · Comments Off on ASP.Net and CSRF
Filed under: Development, Security 

Cross-site request forgery (CSRF) is a very common vulnerability today.  Like most frameworks, ASP.Net is not immune by default.  There are some features that are built-in that can be enabled to help reduce the surface area of this attack, however we need to be aware of how they work and what situations they may not work in.  First, lets provide a quick review of what CSRF is.

CRSF Overview

CSRF is really a result of the browser’s willingness to submit cookies to the server they are associated with.  Of course, this has to happen so that your sessions stay active and you don’t have to enter your credentials on every request.  The problem is when the request to one site (say site A) is made by a second site (say site B) without your permission or interaction.  Lets take a look at a quick example of what we are talking about. 

Say we have a site that allows deleting users by the administrator.   The administrator is provided with a table listing all the users and a link to delete each one.   That link looks something like this:

http://www.jardinesoftware.com/delete.aspx?userid=6

When an administrator clicks this link, the application first checks to see if he is authenticated (using the session or authentication cookie) and authorized.  It then calls the functions responsible to delete the user with the id of 6.

The issue here, is that there is nothing unique in this request.  If another users (without administrative rights) learns of this URL then it may be possible to get an administrator to run it for him.  Here is how that works:

  1. The attacker crafts the request he wants to be executed by the administrator.  In this case, it could be http://www.jardinesoftware.com/delete.aspx?userid=8
  2. The attacker sends the administrative email an email containing this link (probably obfuscated so they don’t realize it is calling the delete function on the website.  The attacker could also send a link to a seemingly innocent site, but contain an image tag containing a src attribute pointing to the delete link above.
  3. The victim (administrator) MUST already be logged into the application when he clicks the link. 
  4. The browser sees the request for JardineSoftware.com and kindly appends the cookies for that domain.
  5. The server receives the cookies (for authentication) and the request and processes it.  The server has no way of knowing that the user didn’t actually initiate the request on purpose.
  6. The user is deleted and the admin is none the wiser.

To resolve this, we need something to make the request unique.  When the request is unique, it is difficult for the attacker to know that unique value for the victim so the request will fail.  With the presence of XSS, many times this can be bypassed.  There are many different ways to do this, which we will cover next.  Keep in mind that each solution described below has its pros and cons that we must be aware of.

ViewState

.Net web forms have a feature called ViewState which allows storing state information on the client.  You typically don’t see this, because it is a hidden field (unless you view source).  ViewState is not guaranteed to be unique across users.  At times, there may be unique values in there that we don’t think about (the user name), but for the most part, ViewState is not sufficient to protect against CSRF.  Enter ViewStateUserKey.  ViewStateUserKey provides a unique value within the Viewstate per user session.  ViewStateUserKey is not enabled by default, and must be set by the developer.  This property can be set in the Page_Init event on each page or in the master page.  The following is an example of how this can be set:

protected void Page_Init(object sender, EventArgs e)
{
        Page.ViewStateUserKey = Session.SessionId;
}

Microsoft has made some changes in Visual Studio 2012.  If you create a new Web Forms application, it will include some additional CSRF changes to help mitigate the issue out of the box.  The following shows an example of the new Master Page Init method (non-relevant code has been removed):

protected void Page_Init(object sender, EventArgs e)
{
    // The code below helps to protect against XSRF attacks
    var requestCookie = Request.Cookies[AntiXsrfTokenKey];

    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;
    }
}

In the code above, we can see that the ViewStateUserKey is now being set in the Master Page by default.  What a great addition.  So what are the limits here?

For starters, and hopefully this is obvious, this technique doesn’t work on requests that don’t use ViewState.  Remember the example we used earlier in the post?  There is no ViewState there, so this doesn’t offer any protection for that situation.  There are also some other situations that could lead to this not working.  In .Net 2.0, with EventValidation disabled, ViewStateUserKey would not get validated if the ViewState is empty.   I have discussed the ability to pass an empty viewstate before, and this is one of the perks.  Many times, ViewState may be present, but the developers do not need it for the processing of the request.   If we pass it as __VIEWSTATE=   with no content then in 2.0, ViewStateUserKey will not get checked.   This was changed in .Net 4.0 where the framework now checks if ViewStateUserKey was set and will check it even if the ViewState is empty.  This doesn’t effect requests that don’t use ViewState like the example above.

Nonce or Anti-Forgery Token

Another technique that can be used to protect requests from CSRF is what is called a ‘Nonce’.  A Nonce is a single use token that gets included with every request.  This token is only known to the user and changes for each request.  The idea is that only the requestor of the page with have a valid token to submit the action.  In our example above, a new parameter would need to exist such as this:

http://www.jardinesoftware.com/delete.aspx?userid=6&antiforgery=GJ38r4Elke7823SERw

Yes, that value for the antiforgery parameter is just made up.  It should be random so it is not guessable by an attacker.  This would limit an attacker’s ability to know what YOUR request is to the resource.  This is a great way to mitigate CSRF, but can be tricky to implement.  ASP.Net MVC has built in functionality for this.  For Web forms, you either have to build it, or you can look to OWASP at their CSRFGuard project.   I am not sure how stable it is for .Net, but it could be a good starting point.

In Visual Studio 2012, the default WebForm application template attempts to add anti-csrf functionality in to the master page.  The following code snippet shows some of the code that does this. (Code has been removed that is not relevant and there is supporting code that is not present from other functions):

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;
    }
    else
    {
        // Generate a new Anti-XSRF token and save to the cookie
        _antiXsrfTokenValue = Guid.NewGuid().ToString("N");

        var responseCookie = new HttpCookie(AntiXsrfTokenKey)
        {
            HttpOnly = true,
            Value = _antiXsrfTokenValue
        };
        if (FormsAuthentication.RequireSSL && Request.IsSecureConnection)
        {
            responseCookie.Secure = true;
        }
        Response.Cookies.Set(responseCookie);
    }
}

In the code above, we can see the anti-csrf value being generated and stored in the cookies collection.  Not shown, the anti-csrf value is also stored in the ViewState as well.  This does show that Microsoft is making an attempt to help developer’s protect their applications by providing default implementations like this.

Require Credentials

Another technique that is often employed is to require the user to re-enter their credentials before performing a sensitive transaction.  In the example above, when the administrator clicked the link, he would need to enter his password before the delete occurred.  This is a fairly effective approach because the attacker doesn’t know the administrator’s password (I hope).  The downside to this technique is that users may get upset if they constantly have to re-enter their credentials.  By placing too much burden on the users, they may decide to use something else. This must be used sparingly. 

CAPTCHA

CAPTCHAs can also be used to help protect against CSRF.  Again, this is a unique value per user that the attacker should not know.  Like the Credentials solution, it does require more work by the user.  Check out Rafal Los’ post on Is unusable the same as ‘secure’? Why security is borked.  where he points out the difficulties with a CAPTCHA system when human’s can’t read them.

Use POST Requests

This is not really a mitigation, but more of a recommendation.  CSRF can be performed on POST requests too.  I just wanted to mention this here to cover it, but this really doesn’t have much weight.  All an attacker needs to do is get the victim to visit a page with a hidden form containing the attack request and use JavaScript to auto-submit that form behind the scenes.

Check the Referrer

This is similar to the use of POST requests.  It can be bypassed with the proper technologies and isn’t a full solution.  This is another item that needs to be implemented properly.  I have seen situations where this has been implemented on pages that were ok to access directly and it caused issues. 

Conclusion

As you can see, there are many different ways, including more than listed, to protect against CSRF.  Microsoft has implemented some nice new changes into the default Visual Studio 2012 Web Form template to help protect against CSRF by default.  It is important to understand what the implementation is and its limits of protection.  Without this understanding it is easy to overlook a situation where your application could be vulnerable.

SQL Injection in 2013: Lets Work Together to Remediate

January 4, 2013 by · Comments Off on SQL Injection in 2013: Lets Work Together to Remediate
Filed under: Development, Security 

We just started 2013 and SQL Injection has been a vulnerability plaguing us for over 10 years.  It is time to take action.  Not that we haven’t been taking action, but it is still prevalent in web applications.  We need to set attainable goals.  Does it seem attainable that we say we will eradicate all SQL Injection in 2013?  Probably not.  This is mostly due to legacy applications and the difficulty in modifying their code. There are some goals we can do to stop writing new code vulnerable to SQL Injection.  Fortunately, this is not a vulnerability that is not well understood.  Here are some thoughts for moving forward.

Don’t write SQL Injection Code

OK, this sounds like what everyone is saying, and it is.  Is it difficult to do? No.   Like anything, this is something we need to commit to and consciously make an effort to do.  Proper SQL Queries are not difficult.  Using parameterized queries is easy to do in most languages now.  Here is a quick example of a parameterized query in .Net:

using (SqlConnection cn = new SqlConnection())
{
    using (SqlCommand cmd = new SqlCommand())
    {
        string query = "SELECT fName,lName from Users WHERE fName = @fname";
        cmd.CommandText = query;
        cmd.CommandType = System.Data.CommandType.Text;
        cmd.Parameters.AddWithValue("@fname", untrustedInput);
        cmd.Connection = cn;
        cmd.Connection.Open();
        cmd.ExecuteNonQuery();
    }
}

What about stored procedures?  Stored procedures are good, but can be vulnerable to SQL Injection.  This is most common when you generate dynamic queries from within the stored procedure.  Yes, the parameters are passed to the procedure properly, but then used in an insecure way inside the procedure.  If you are unsure if your procedures are vulnerable, look for the use of EXEC or other SQL commands that run SQL code and make sure parameters are handled properly.

Often overlooked is how a Stored Procedure is called.  You are using a stored procedure but calling it like so:

string query = "EXEC spGetUser '" + untrustedinput + "'";

The above query can still be vulnerable to SQL Injection by chaining onto the EXEC statement.  So even though the stored procedure may be secure, an attacker may be able to run commands (just not see the output). 

The key to not writing vulnerable code is to not write it ever.  Whether it is a proof of concept, just some test code, or actual production code, take the time to use secure methods.  This secure way will be second nature and SQL injection reduction will be on its way.

Supportively Spread the Word

The key here is Supportively!!  Yes, we have been talking about SQL injection for years, but have we been doing it the right way, to the right people?  First, enough with the “Developers Suck”, “Your code sucks!” nonsense.  This is not productive and is probably much more destructive to the relationship between security and developers.  Second, security practitioners meet up at their cons and talk about this all year long.  This may sound crazy, but it is not the security practitioners that are writing the code.  We need to get the information into the developer’s hands and minds.  Just throwing the information on a blog (like this) or on a website like OWASP or SANS is not enough to get developers the information.  I don’t even want to guess at the number of developers that have never even heard of OWASP, but I would venture it is higher than you think.  Everyone needs to help spread the word.  Security is talking about it, developers need to be talking about it.  Major development conferences rarely have any content that is security related, that needs to change.  It needs to be thrown in everyone’s lap.   If you see someone writing something insecure, let them know so they can learn.  We can’t assume everyone knows everything.

Lets start including the secure way of writing SQL Queries in our tutorials, books, classes so all we see is the right way to do it.  I mentioned this a year or so ago and everyone cried that it would make the code samples in books and tutorials too long and impossible to follow.  First, I disagree that it would be that detrimental.  Second, where do developers get a lot of their code? From tutorials, samples, books, classes.  We don’t reinvent the wheel when we need to do something.  We look for someone that has done it, take the concept, make modifications to work in our situation and run with it.  All too often, this leads to a lot of vulnerabilities because we refuse to write secure code that is put out for anyone to use. We all need to get better at this.  And if you are the author, maybe it adds a few pages to your book ;).  

Take Responsibility

We can no longer blame others for the code we write.  Maybe the code was copied from an online resource.  As soon as it is in your paws, it is your code now.  It is not the fault of MSSQL or Oracle because they allow you to write dynamic  SQL queries.  This is the power of the system, and some people may just use it.  It is our responsibility to know how to use the systems we have. Many frameworks now try to help stop SQL Injection by default.  If you are relying on frameworks, know how they work, and keep them patched.  We just saw Ruby release a patch to fix a SQL Injection issue. 

Conclusion

So maybe this was a lot of rambling, or maybe it will mean something and get a few people thinking about defending against SQL Injection.  I apologize for some small tangents, those are part of another post that will be coming soon.  The purpose of this post is to start setting some goals that we can achieve in 2013.   Not everyone can eat an entire apple in one bite, so lets take some small bites and really chew on them for the year.  Lets focus on what we can do and do it well.

Authorization: Bad Implementation

January 3, 2013 by · Comments Off on Authorization: Bad Implementation
Filed under: Development, Security, Testing 

A few years ago, I joined a development team and got a chance to poke around a little bit for security issues.  For a team that didn’t think much about security, it didn’t take long to identify some serious vulnerabilities.  One of those issues that I saw related to authorization for privileged areas of the application. Authorization is a critical control when it comes to protecting your applications because you don’t want unauthorized users performing actions they should not be able to perform. 

The application was designed using security by obscurity: that’s right, if we only display the administrator navigation panel to administrators, no one will ever find the pages.   There was no authorization check performed on the page itself.  If you were an administrator, the page displayed the links that you could click.  If you were not an administrator, no links.

In the security community, we all know (or should know), that this is not acceptable.  Unfortunately, we are still working to get all of our security knowledge into the developers’ hands.  When this vulnerability was identified, the usual first argument was raised: "No hacker is going to guess the page names and paths."   This is pretty common and usually because we don’t think of internal malicious users, or authorized individuals inadvertently sharing this information on forums.  Lets not forget DirBuster or other file brute force tools that are available.  Remember, just because you think the naming convention is clever, it very well can be found.

The group understood the issue and a developer was tasked to resolve the issue.  Great.. We are getting this fixed, and it was a high priority.   The problem….  There was no consultation with the application security guy (me at the time) as to the proposed solution.  I don’t have all the answers, and anyone that says they do are foolish.  However, it is a good idea to discuss with an application security expert when it comes to a large scale remediation to such a vulnerability and here is why.

The developer decided that adding a check to the Page_Init method to check the current user’s role was a good idea.  At this point, that is a great idea.  Looking deeper at the code, the developer only checked the authorization on the initial page request.  In .Net, that would look something like this:

protected void Page_Init(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        //Check the user authorization on initial load
        if (!Context.User.IsInRole("Admin"))
        {
            Response.Redirect("Default.aspx", true);
        }
    }
}

What happens if the user tricks the page into thinking it is a postback on the initial request?  Depending on the system configuration, this can be pretty simple.  By default, a little more difficult due to EventValidation being enabled.  Unfortunately, this application didn’t use EventValidation. 

There are two ways to tell the request that it is a postback:

  1. Include the __EVENTTARGET parameter.
  2. Include the __VIEWSTATE parameter.

So lets say we have an admin page that looks like the above code snippet, checking for admins and redirecting if not found.  By accessing this page like so would bypass the check for admin and display the page:

http://localhost:49607/Admin.aspx?__EVENTTARGET=

This is an easy oversight to make, because it requires a thorough understanding of how the .Net framework determines postback requests.  It gives us a false sense of security because it only takes one user to know these details to then determine how to bypass the check. 

Lets be clear here, Although this is possible, there are a lot of factors that tie into if this may or may not work.  For example, I have seen many pages that it was possible to do this, but all of the data was loaded on INITIAL page load.  For example, the code may have looked like this:

protected void Page_Load(object sender, EventArgs e)
{
    if (!Page.IsPostBack)
    {
        LoadDropDownLists();
        LoadDefaultData();
    }
}

In this situation, you may be able to get to the page, but not do anything because the initial data needed hasn’t been loaded.  In addition, EventValidation may cause a problem.  This can happen because if you attempt a blank ViewState value it could catch that and throw an exception.  In .Net 4.0+, even if EventValidation is disabled, ViewStateUserKey use can also block this attempt. 

As a developer, it is important to understand how this feature works so we don’t make this simple mistake.  It is not much more difficult to change that logic to test the users authorization on every request, rather than just on initial page load.

As a penetration tester, we should be testing this during the assessment to verify that a simple mistake like this has not been implemented and overlooked.

This is another post that shows the importance of a good security configuration for .Net and a solid understanding of how the framework actually works.  In .Net 2.0+ EventValidation and ViewStateMac are enabled by default.  In Visual Studio 2012, the default Web Form application template also adds an implementation of the ViewStateUserKey.  Code Safe everyone.

2012 in Review

December 31, 2012 by · Comments Off on 2012 in Review
Filed under: Development, Security, Testing 

Well here it is, 2012 is coming to an end and I thought I would wish everyone happy holidays, as well as mention some of the topics covered this year on my blog.

The year started out with a few issues in the ASP.Net framework. We saw a Forms Authentication Bypass that was patched at the very end of 2011 and an ASP.Net Insecure Redirect issue. Both of these issues show exactly why it is important to keep your frameworks patched.

Next, I did a lot of discussions about ViewStateMAC and EventValidation. This was some new stuff mixed in with some old. We learned that ViewStateMAC also protects the EventValidation field from being tampered with. I couldn’t find any MSDN documentation that states this fact. In addition, I showed how it is possible to manipulate the EventValidation field (when ViewStateMAC is not enabled) to tamper with the application. Here are some links to those posts:

I also created the ASP.Net Webforms CSRF Workflow, which is a small diagram to determine possible CSRF vulnerabilities with an ASP.Net web form application.

The release of .Net 4.5 was fairly big and some of the enhancements are really great. One of those, was the change in how Request Validation works. Adding the ability for lazy validation increases the ability to limit what doesn’t get validated. In addition, ModSecurity was released for IIS.

The release of the Web.Config Security Analyzer happened early on in the year. It is a simple tool that can be used to scan a web.config file for common security misconfigurations.

Some other topics covered included .Net Validators (lets not forget the check for Page.IsValid), Forms Authentication Remember Me functionality, how the Request Method can matter, and a Request Validation Bypass technique.

I discussed how XSS can be performed by tampering with the ViewState and the circumstances needed for it to be possible. This is commonly overlooked by both developers and testers.

In addition, I have created a YouTube channel for creating videos of some of these demonstrations. There are currently two videos available, but look forward to more coming in 2013.

There is a lot to look forward to in 2013 and I can’t wait to get started. Look for more changes and content coming out of Jardine Software and its resources.

I hope everyone had a great year in 2012 and that 2013 brings better things to come.

Another Request Validation Bypass?

August 29, 2012 by · Comments Off on Another Request Validation Bypass?
Filed under: Development, Security 

I stumbled across this BugTraq(http://www.securityfocus.com/archive/1/524043) on Security Focus today that indicates another way to bypass ASP.Net’s built in Request Validation feature. It was reported by Zamir Paltiel from Seeker Research Center showing us how using a % symbol in the tag name (ex. <%tag>) makes it possible to bypass Request Validation and apparently some versions of Internet Explorer will actually parse that as a valid tag. Unfortunately, I do not have the specifics of which versions of IE will parse this. My feeble attempts in IE8 and IE9 did not succeed (and yes, I turned off the XSS filter). I did a previous post back in July of 2011 (which you can read here: https://jardinesoftware.net/2011/07/17/bypassing-validaterequest/) which discussed using Unicode-wide characters to bypass request validation. 

I am not going to go into all the details of the BugTraq, please read the provided link as Zamir has done a great write up for it.  Instead, I would like to talk about the proper way of dealing with this issue.  Sure, .Net provides some great built in features, Event Validation, Request Validation, ViewStateMac, etc., but they are just helpers to our overall security cause.  If finding out that there is a new way to bypass Request validation opens your application up to Cross-Site Scripting…  YOU ARE DOING THINGS WRONG!!!  Request Validation is so limited in its own nature that, although it is a nice-to-have, it is not going to stop XSS in your site.  We have talked about this time and time again.  Input Validation, Output Encoding.    Say it with me:  Input Validation, Output Encoding.  Lets briefly discuss what we mean here (especially you.. the dev whose website is now vulnerable to XSS because you relied solely on Request Validation).

Input Validation

There are many things we can do with input validation, but lets not get too crazy here.  Here are some common things we need to think about when doing input validation:

  • What TYPE of data are we receiving.  If you expect an Integer, then make sure that the value casts to an Integer.  If you expect a date-time, then make sure it casts to a date time. 
  • How long should the data be.  If you only want to allow 2 characters (state abbreviation?) then only allow 2 characters.
  • Validate the data is in a specific range.  If you have a numeric field, say an age, then validate that it is greater than 0 and less than 150, or whatever your business logic requires.
  • Define a whitelist of characters allowed.  This is big, especially for free-form text.   If you only allow letters and numbers then only allow letters and numbers.  This can be difficult to define depending on your business requirements.  The more you add the better off you will be.

Output Encoding

I know a lot of people will disagree with me on this, but I personally believe that this is where XSS is getting resolved.  Sure, we can do strict input validation on the front end.  But what if data gets in our application some other way, say a rogue DBA or script running directly against the server.   I will not get into all my feelings toward this, but know that I am all for implementing Input Validation.  Now, on to Output Encoding.  The purpose is to let the client or browser be able to distinguish commands from data.  This is done by encoding command characters that the parser understands.  For Example, for HTML the < character gets replaced with &lt;.  This tells the parser to display the less than character rather than interpret it as the start of a tag definition. 

Even with all the input validation in the world, we must be encoding our output to protect against cross site scripting.  It is pretty simple to do, although you do have to know what needs encoding and what does not.  .Net itself makes this somewhat difficult since some controls auto encode data and others do not.

Can We Fix It?

With little hope that this will get resolved within the .Net framework itself, there are ways that we can update Request Validation ourselves, if you are using 4.0 or higher.  Request Validation is Extensible, so it is possible to create your own class to add this check into Request Validation.  I have included a simple PROOF OF CONCEPT!!! of attempting to detect this.  THIS CODE IS NOT PRODUCTION READY and is ONLY FOR DEMONSTRATION PURPOSES..  USE AT YOUR OWN RISK!.  ok enough of that.  Below is code that will crudely look for the presence of the combination of <% in the request parameter.  There are better ways of doing this, I just wanted to show that this can be done.  Keep in mind, that if your application allows the submission of this combination of characters, this would probably not be a good solution.   Alright..  the code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Util;

namespace WebTester
{
    public class NewRequestValidation : RequestValidator
    {
        public NewRequestValidation() { }

        protected override bool IsValidRequestString(
            HttpContext context, 
            string value, 
            RequestValidationSource requestValidationSource, 
            string collectionKey, 
            out int validationFailureIndex)
        {
            validationFailureIndex = -1;

            // This check is not meant to be production code...
            // This is just an example of how to set up 
            // a Request Validator override.  
            // Please pick a better way of searching for this.
            if (value.Contains("<%")) // Look for <%...  
            {
                return false;
            }
            else // Let the default Request Validtion take a look.
            {
                return base.IsValidRequestString(
                    context, 
                    value, 
                    requestValidationSource, 
                    collectionKey, 
                    out validationFailureIndex);
            }
        }
    }
}

In order to get a custom request validation override to work in your application, you must tell the application to use it in the web.config.  Below is my sample web.config file updated for this:

  <system.web>
    <httpRuntime requestValidationType="WebTester.NewRequestValidation"/>
  </system.web>

 

Conclusion

We, as developers, must stop relying on built in items and frameworks to protect us against security vulnerabilities.  We must take charge and start practicing secure coding principles so that when a bug like this one is discovered, we can shrug it off and say that we are not worried because we are properly protecting our site. 

Hopefully this will not affect many people, but I can assure you that you will start seeing this being tested during authorized penetration tests and criminals.  The good news, if you are protected, is that it is going to waste a little bit of the attacker’s time by trying this out.  The bad news, and you know who I am talking about, is that your site may now be vulnerable to XSS.  BTW, if you were relying solely on Request Validation to protect your site against XSS, you are probably already vulnerable. 

ASP.Net 4: Change the Default Encoder

July 9, 2011 by · Comments Off on ASP.Net 4: Change the Default Encoder
Filed under: Development, Security 

In ASP.Net 4.0, Microsoft added the ability to override the default encoder.  This is specifically focused on the HTMLEncode, HTMLAttributeEncode, and URLEncode functionality.  These functions are used, in the eyes of security, to help mitigate cross-site scripting (XSS).  The problem with the built in .Net routines is that they are built on a black-list methodology, rather than a white-list methodology.  The built in routines use a very small list of characters that get encoded.  For example, the .Net version of HTMLEncode encodes the following characters: <,>,”,&.   The Microsoft Web Protection Library (previously known as the Anti-XSS Library) instead determines all characters that don’t need encoding, a-z0-9 for example, and then encodes all the rest.  This is a much safer approach to encoding. 

In this post, I will show you how to use the Web Protection Library as the default encoder for an ASP.Net 4.0 application.  The first step is to download the Web Protection Library.  In this example, I use version 4.0 which can be found at: http://wpl.codeplex.com/

Next, you will need to have an application to implement this.  You can use an existing application, or create a new one.  Add a reference to the AntiXSSLibrary.dll found in” Program Files\Microsoft Information Security\AntiXSS Library v4.0”.

To use the library, it is time to create a new class.  You can see the code in my class in Figure 1.  I named the class “MyEncoder” and this is just a sample. (THIS IS NOT PRODUCTION CODE)  There are two important factors to this class:

1.  The class must inherit from System.Web.Util.HttpEncoder.

2.  You must override each Encode Method you want to change.

If you only wanted to update the HTMLEncode and leave the other methods alone, just leave them out of the class.

Figure 1

using System;
using System.Web;

public class MyEncoder : System.Web.Util.HttpEncoder
{
  public MyEncoder(){}

    protected override void HtmlEncode(string value, System.IO.TextWriter output)
    {
        if (null == value)
            return;

        output.Write(Microsoft.Security.Application.Encoder.HtmlEncode(value));
    }
    protected override void HtmlAttributeEncode(string value, System.IO.TextWriter output)
    {
        if (null == value)
            return;

        output.Write(Microsoft.Security.Application.Encoder.HtmlAttributeEncode(value));
    }
}

The final step to implementing this custom encoding is to update the web.config file. To do this, modify your httpRuntime element to have the “encoderType” attribute set, as seen in Figure 2.  Change “MyEncoder” to the name of the class you created.  If you do not have the httpRuntime element, just add it in.

Figure 2

  <system.web>
    <compilation debug="true" targetFramework="4.0"/>
    <httpRuntime encoderType="MyEncoder"/>
    .....

Although it would be really nice if the .Net Framework would just start using the Web Protection Library, they are just not ready for that yet.  It is important that plenty of testing is always done when working with output encoding.  Different encoders produce different outputs and may cause display defects.  It is also important to note that this only effects items that get auto-encoded by the framework.  For example, a text property of a textbox.

This is just a small example of modifying the default encoding type of your application.  There is much more that you could potentially do with this.  This is just a sample and this code is NOT FOR PRODUCTION USE. 

SQL Injection: Common Mistake

September 1, 2010 by · Comments Off on SQL Injection: Common Mistake
Filed under: Security 

One of the most common suggestions for remediating SQL Injection vulnerabilities is to use stored procedures.  Using stored procedures can help decrease the risk of SQL Injection, but if implemented incorrectly, it can create a false sense of security.  For example, look at the created stored procedure below:

CREATE PROCEDURE dbo.usp_IsValidUser
(
  @UserName varchar(50),
  @Password varchar(50)
)
AS
    SET NOCOUNT ON
    SELECT  MemberId
    FROM    Member
    WHERE   UserName = @UserName
    AND     Password = @Password
    RETURN

This looks like a pretty secure stored procedure.  It does not use any dynamic SQL, or the dreaded EXEC command.   It is still recommended that you validate your inputs, but the parameters should not execute as SQL code, but instead just as strings.

Lets take a look at the wrong way to call a stored procedure below:

_command.CommandType = CommandType.Text;
_command.CommandText = "EXEC usp_IsValidUser '" +
                       UserName + "', '" +
                       Password + "'";

In this example, although calling a stored procedure, is still vulnerable to SQL Injection (if proper input validation is not performed).  The stored procedure may be safe, but the developer has just created an inline query to call the stored procedure.   A malicious user could append SQL queries to the end of this query to run their own queries.

For example, if the user passes in a Password value that contains the single quote (‘), then they can dump out of the password parameter and append on their own queries.  It is beyond this post to show detailed examples of exploiting this type of statement.

It is important for developers to keep this scenario in mind when developing and doing peer code reviews.  Any time the code is appending data to send to the data store you should investigate further.  Always validate the input received from un-trusted sources.  Use Parameterized queries instead of string building to create database queries.

Frame Busting

July 19, 2010 by · Comments Off on Frame Busting
Filed under: Security 

An often overlooked security feature for a web application is to not allow the application (especially the login screen) to be embedded in a frame.  This is often referred to “frame busting”.  In some browsers, it is possible to capture the keystrokes in one frame, from the parent window.  This would be a problem with an embedded login form where the malicious attacker embeds a login screen in a different domain and tricks a user to attempting to login.  The attacker could then capture the user name and password for that user to log in at a later time. 

Pages that can be captured in any frame set may also be susceptible to click jacking.  Click jacking is beyond the scope of this post, but more information can be found at http://www.owasp.org/index.php/Clickjacking.

There are a few possibilities to a layered approach to protecting against both of these attacks.  Internet Explorer 8 supports the X-FRAME-OPTIONS response header.   Unfortunately, this is not supported by all browsers.   Mozilla is working on their own directives to do the same thing, with a more robust approach.  Both of these approaches are limited because they are targeted at specific browsers.

Another approach is to add JavaScript to the pages that checks the content against the parent location.  If they are not the same, it breaks out of the frame and loads the content in the main window.  There is a great document discussing research about this topic at Http://seclab.Stanford.edu/websec/framebusting/framebust.pdf

It is important for application developers to assess their designs to make sure frame busting and click jacking are addressed. 

« Previous PageNext Page »