ViewStateUserKey: ViewStateMac Relationship

November 26, 2013 by · Comments Off on ViewStateUserKey: ViewStateMac Relationship
Filed under: Development, Security, Testing 

I apologize for the delay as I recently spoke about this at the SANS Pen Test Summit in Washington D.C. but haven’t had a chance to put it into a blog. While I was doing some research for my presentation on hacking ASP.Net applications I came across something very interesting that sort of blew my mind. One of my topics was ViewStateUserKey, which is a feature of .Net to help protect forms from Cross-Site Request Forgery. I have always assumed that by setting this value (it is off by default) that it put a unique key into the view state for the specific user. Viewstate is a client-side storage mechanism that the form uses to help maintain state.

I have a previous post about ViewStateUserKey and how to set it here: https://jardinesoftware.net/2013/01/07/asp-net-and-csrf/

While I was doing some testing, I found that my ViewState wasn’t different between users even though I had set the ViewStateUserKey value. Of course it was late at night.. well ok, early morning so I thought maybe I wasn’t setting it right. But I triple checked and it was right. Upon closer inspections, my view state was identical between my two users. I was really confused because as I mentioned, I thought it put a unique value into the view state to make the view state unique.

My Problem… ViewStateMAC was disabled. But wait.. what does ViewStateMAC have to do with ViewStateUserKey? That is what I said. So I started digging in with Reflector to see what was going on. What did I find? The ViewStateUserKey is actually used to modify the ViewStateMac modifier. It doesn’t store a special value in the ViewState.. rather it modifies how the MAC is generated to protect thew ViewState from Parameter Tampering.

So this does work*. If the MAC is different between users, then the ViewState is ultimately different and the attacker’s value is different from the victim’s. When the ViewState is submitted, the MAC’s won’t match which is what we want.

Unfortunately, this means we are relying again on ViewStateMAC being enabled. Don’t get me wrong, I think it should be enabled and this is yet another reason why. Without it, it doesn’t appear that the ViewStateUserKey doesn’t anything. We have been saying for the longest time that to protect against CSRF set the ViewStateUserKey. No one has said it relies on ViewStateMAC though.

To Recap.. Things that rely on ViewStateMAC:

  • ViewState
  • Event Validation
  • ViewStateUserKey

It is important that we understand the framework features as disabling one item could cause a domino effect of other items. Be secure.

Bounties For Fixes

October 11, 2013 by · Comments Off on Bounties For Fixes
Filed under: Security 

It was just recently announced that Google will pay for open-source code security fixes (http://www.computerworld.com/s/article/9243110/Google_to_pay_for_open_source_code_security_fixes). Paying for stuff to happen is nothing new, we have seen Bug Bounty programs popping up in a lot of companies. The idea behind the bug bounty is that people can submit bugs they have found and then possibly get paid for that bug. This has been very successful for some large companies and some bug finders out there.

The difference in this new announcement is that they are paying for people to apply fixes to some open source tools that are widely used. I personally think this is a good thing because it will encourage people to actually start fixing some of the issues that exist. Security is usually bent on finding vulnerabilities, which doesn’t really help fix security at all. It still requires the software developers to implement some sort of change to get that security hole plugged. Here, we see that the push to fix the problem is now being rewarded. This is especially true in open-source projects as many of the people that work on these projects do so voluntarily.

Is there any concern though that this process could be abused? The first thought that comes to mind is people working together where one person plants the bug and the other one fixes it. Not sure how realistic that is, but I am sure there are people thinking about it. What could possibly be more challenging is verifying the fixes. What happens if someone patches something, but they do it incorrectly? Who is testing the fix? How do they verify that it is really fixed properly? If they find later that the fix wasn’t complete, does the fixer have to return the payment? There are always questions to be answered when we look at a new program like this. I am sure that Google has thought about this before rolling it out and I really hope the program works out well. it is a great idea and we need to get more people involved in helping fix some of these issues.

Your Passwords Were Stolen: What’s Your Plan?

May 29, 2013 by · Comments Off on Your Passwords Were Stolen: What’s Your Plan?
Filed under: Development, Security 

If you have been glancing at many news stories this year, you have certainly seen the large number of data breaches that have occurred. Even just today, we are seeing reports that Drupal.org suffered from a breach (https://drupal.org/news/130529SecurityUpdate) that shows unauthorized access to hashed passwords, usernames, and email addresses. Note that this is not a vulnerability in the CMS product, but the actual website for Drupal.org. Unfortunately, Drupal is just the latest to report this issue.

In addition to Drupal, LivingSocial also suffered a huge breach involving passwords. LinkedIn, Evernote, Yahoo, and Name.com have also joined this elite club. In each of these cases, we have seen many different formats for storing the passwords. Some are using plain text (ouch), others are actually doing what has been recommended and using a salted hash. Even with a salted hash, there are still some issues. One, hashes are fast and some hashes are not as strong as others. Bad choices can lead to an immediate failure in implementation and protection.

Going into what format you should store your passwords in will be saved for another post, and has been discusses heavily on the internet. It is really outside the scope of this post, because in this discussion, it is already too late for that. Here, I want to ask the simple question of, “You have been breached, What do you do?”

Ok, Maybe it is not a simple question, or maybe it is. Most of the sites that have seen these breaches are fairly quick to force password resets by all of their users. The idea behind this is that the credentials were stolen, but only the actual user should be able to perform a password reset. The user performs the reset, they have new credentials, and the information that the bad guy got (and everyone else that downloads the stolen credentials) are no good. Or maybe not?? Wait.. you re-use passwords across multiple sites? Well, that makes it more interesting. I guess you now need to reset a bunch of passwords.

Reseting passwords appears to be the standard. I haven’t seen anyone else attempt to do anything else, if you have please share. But what else would work? You can’t just change the algorithm to make it stronger.. the bad guy has the password. Changing the algorithm doesn’t change that fact and they just log in using a stronger algorithm. I guess that won’t work. Might be nice to have a mechanism to upgrade everyone to a stronger algorithm as time goes on though.

So if resetting passwords in mass appears to work and is the standard, do you have a way to do it? if you got breached today, what would you need to do to reset everyone’s password, or at least force a password reset on all users? There are a few options, and of course it depends on how you actually manage user passwords.

If you have a password expiration field in the DB, you could just set all passwords to have expired yesterday. Now everyone will be presented with an expired password prompt. The problem with this solution is if an expired password just requires the old password to set the new password. It is possible the bad guy does this before the actual user. Oops.

You could Just null out or put in a 0 or some false value into all of the password fields. This only works for encrypted or hashed passwords.. not clear text. This could be done with a simple SQL Update statement, just drop that needless where clause ;). When a user goes to log in, they will be unsuccessful because when the password they submit is encrypted or hashed, it will never match the value you updated the field to. This forces them to use the forgot password field.

You could run a separate application that resets everyone password like the previous method, it just doesn’t run a DB Update directly on the server. Maybe you are a control freak as to what gets run against the servers and control that access.

As you can see, there are many ways to do this, but have you really given it any thought? Have you written out your plan that in the event your site gets breached like these other sites, you will be able to react intelligently and swiftly? Often times when we think of incidence response, we think of stopping the attack, but we also have to think about how we would protect our users from future attacks quickly.

These ideas are just a few examples of how you can go about this to help provoke you and your team to think about how you would do this in your situation. Every application is different and this scenario should be in your IR plan. If you have other ways to handle this, please share with everyone.

The Watering Hole: Is it Safe to Drink?

May 7, 2013 by · Comments Off on The Watering Hole: Is it Safe to Drink?
Filed under: Security 

How many times have you been told you have a vulnerability that you just don’t understand  its relevancy?  Cross-Site scripting comes to mind for many people.   Sure, they get the fact that you can execute script in the user’s browser, but often times they really don’t fully understand the impact.  Of course, we determine that impact through risk analysis.  What is the true impact and how much risk does it pose to the affected parties?

Over the years, I have heard numerous companies and previous employers state that no one would attack them because they are too small or that they didn’t have anything that the attackers would want.  I have always disagreed with this statement or theory.  Maybe you are a company that doesn’t contain financial data, or health information.  Maybe you don’t deal with sensitive information at all.  So what is the risk? 

We have to start thinking about more than just the type of data that we hold.  We have to look at the bigger picture.  Who are our clients or users?  Who do we do business with that may have something of interest to an attacker.  Of of the big concerns that have been directed toward these smaller companies is the idea of pivoting.   If I wanted to attack a major bank, would it make sense to attack the bank directly?  Very large banks usually have bigger budgets and theoretically would have stronger security controls in place.  That could be a lot of work to get through that entry point.   But what about that small company, that has a smaller budget, and probably (not always) fewer security controls that does business with that big bank?   Is there an opportunity to compromise the small company and pivot into the larger bank through a B2B channel they have set up?   This is certainly a possibility.

Something newer we are seeing is this idea of a Watering Hole attack.  This focuses more on the “WHO” visits your site.  The idea behind a watering hole attack is that it is a targeted drive by malware type of attack.  Rather than put a malicious payload on a site that EVERYONE accesses, why not target a site that the victim you are tracking frequents.  Think of this as similar to the difference between phishing and spear phishing.  In a phishing attack we send out the attack email in mass, but in spear phishing, we are much more refined in who receives the message.   The same goes for this watering hole attack.

As always, we are witnessing the evolution of these attacks.   Migrating from a broad spreading mechanism to a more targeted one has a lot of benefits.  One is that your specific target is more likely to fall prey.  Two, there is less chance of the attack getting noticed if fewer users actually see it.  We have seen other situations where the attackers have actually built their delivery mechanism to not deliver to know security professionals or researchers based on their IP address to avoid getting noticed as quickly. 

The watering hole is just another example of why security does matter to every website, no matter what your content may be.  Even if the attack isn’t against our servers, but against our users, that can have a serious effect on our businesses.   The next time you hear someone say that they are too small or don’t have any data that attackers may want, think about the watering hole concept and see if you are still a nobody in this world.

Authentication Failure: Bank Transactions in Person

May 3, 2013 by · Comments Off on Authentication Failure: Bank Transactions in Person
Filed under: Security 

Usually I write about the security flaws that I have seen over the years both as a developer and a security professional.  Recently, however, I was in a situation where I realized after the transaction, that there was no authentication to who I was.  Of course, when we talk about technology, we discuss authentication a lot.  Making sure that we are proving that the entity that we are dealing with is really that entity, and not some other impersonator. 

I recently had the need to wire some money from my bank to another bank.  My bank has many options for requesting the wire, but I chose the one where I actually walk into the local branch office and sit down with someone to complete the transaction.  When I entered the branch, I was greeted by the information desk asking if they could help me.   I told them that I needed to perform a wire transfer.  They asked for my name and sent me to the waiting area. 

After just a few minutes in the waiting area, a representative walked over and brought me back to her cubicle/office.  I have never done a wire before this, but had instructions from the receiving bank all ready to go.  I sat down and explained my situation and that I had this document that had all the information on it that I needed. 

The representative asked me to verify my information.  This is good right?   Wrong!!   She proceeded to say “your address is still….” and I just said “yes”.  Then she asked who my employer was.  I told her and she just entered it into the system.  I guess that had never been updated.   Then she confirmed my phone numbers, but again, she read them to me, I just had to say yes. 

She asked which account I wanted to transfer from, but not the number, just asking if I wanted my sole account.   Again, I didn’t have to know anything about this account to perform the transaction.   I did have to sign the confirmation, but I could sign anyone’s name, couldn’t I?   Never once did I get asked for my Driver’s license or any other type of identification. 

Although this sounds like the story of a contracted penetration test, I can assure you it was not.  I wish it had been, then it would have been a really great test and I would be excited for the easy win.  Unfortunately, it was not and I was far less than excited that it was a big fail on my bank’s part.  

We spend so much time analyzing and testing the technology side of security, that we often overlook the human and process side of it.  At Secure Ideas, we perform physical assessments that are just like this scenario.  Unfortunately, as I stated, this was not a test, but a real transaction.

My first instinct was to switch banks.  I went home and was telling my wife about it all and hastily said, we are switching banks.  Unfortunately, I have so much stuff set up using that bank, that switching would be a headache.  I know, that shouldn’t be any reason to not switch, but this seems to be the trend that we are seeing these days.  I guess I am getting lazy.  Just look at all of the breaches that we have seen in the past.  Are people really not using companies any more just because they had a breach??   And this bank didn’t even get breached.. I just happened to notice that their security was not so good when they completed my transaction. 

This will definitely be a story that I throw into all of my classes as it is a perfect example of authentication, or lack there of.  Please everyone, be aware of what you are doing and what security may be missing in everything you do.  It is not just the web sites or the networks that are vulnerable.

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.

Brute Force: An Inside Job

March 20, 2013 by · Comments Off on Brute Force: An Inside Job
Filed under: Development, Security, Testing 

As a developer, we are told all the time to protect against brute force attacks on the login screen by using a mechanism like account lockouts.  We even see this on our operating systems, when we attempt multiple incorrect logins, we get locked out.   Of course, as times have changed, so have some of the mitigations.  For example, some systems are implementing a Captcha or some other means to slow down automated brute force attacks.  Of course, the logistics are different on every system, how many attempts until lockout, or is there an auto-unlock feature, but that is outside the scope of this post.

As a penetration tester, brute force attacks are something I test for on every application.  Obviously, I test the login forms for this type of security flaw.  There are also other areas of an application that brute force attacks can be effective.  The one I want to discuss in this post is related to functionality inside the authenticated section of the application.  More specifically, the change password screen.  Done right, the change password screen will require the current password.  This helps protect from a lot of different attacks.  For example, if an attacker hijacks a user’s valid session, he wouldn’t be able to just change the user’s password.  It also helps protect against cross-site request forgery for changing a user’s password.  I know, I know, it can be argued with cross-site scripting available, cross-site request forgery can still be performed, but that gets a little more advanced. 

What about brute forcing the change password screen?   I rarely see during an assessment where the developers, or business has thought about this attack vector.  In just about every case, I, the penetration tester, can attempt password changes with a bad password as much as I want, followed by a valid current password to change the password.  What if an attacker hijacks my session?  What if someone sits down at my desk while I have stepped away and I didn’t lock my computer (look around your office and see how many people lock their computer when they walk away)? 

It is open season for an attacker to attempt a brute force attack to change the user’s password.  You may wonder why we need to change the password if we have accessed the account.  The short answer is persistence.  I want to be able to access the account whenever I want.   Maybe I don’t want the user to be able to get back in and fully take over the account.

So how do we address this?  We don’t want to lock the account do we?  My opinion is no, we don’t want to lock the account.  Rather, lets just end the current session in this type of event.  If the application can detect that the user is not able to type the correct current password three or five times in a given time frame (sounds familiar to account lockout procedures) then just end the current session.  The valid user should know their password and not be mis-typing it a bunch of times.  An invalid user should rightfully so get booted out of the system.  If the valid user’s session ends, they just log back in, however the attacker shouldn’t be able to just log back in and may have to hijack the session again which may be difficult.

Just like other brute forcible features,there are other mitigations.  A Captcha could also be used to slow down automation.  The key differentiator here is that we are not locking the account, but possibly just ending the session.  This will have less impact on technical support as the valid user can just log back in.   Of course, don’t forget you should be logging these failed attempts and auditing them to detect this attack happening.

This type of security flaw is common, not because of lazy development, but because this is fairly unknown in the development world.   Rarely are we thinking about this type of issue within the application, but we need to start.  Just like implementing lockouts on the login screens, there is a need to protect that functionality on the inside. 

Developers, Security, Business – Lets All Work Together

January 10, 2013 by · Comments Off on Developers, Security, Business – Lets All Work Together
Filed under: Development, Security 

A few years ago, my neighbors ran into an issue with each other. Unfortunately for one neighbor, the other neighbor was on the board for the HOA. The first neighbor decided to put up a fence, got the proper approvals and started work on it. They were building the fence them selves and it took a while to complete. The other neighbor, on the board of the HOA, noticed that the fence was being built out of compliance. Rather than stopping by and letting the first neighbor know about this, they decided it would be better to let them complete the fence and then issue a citation about the fence being out of compliance, requiring them to rebuild it. At times, I feel like I see the same thing in application security which leads into my post below.

There have been lots of great blogs lately talking about application security and questioning who’s responsibility the security of applications is (Matt Neely – Who is Responsible for Application Security?) and why we are still not producing secure applications (Rafal Los – Software Security – Why aren’t the enterprise developers listening?). I feel a little late to the party, even though I have been thinking about this post for over a week. At least I am not the only one thinking about this topic as the new year starts off.

There has been a great divide between security personnel and the development teams. This has been no secret. They don’t hang out at the same conferences and honestly, it looks similar to a high school dance where, in this case, the security people are on one side of the gym and the developers are on the other. Add in the chaperones (the business leadership) enforcing space between the two groups. We need to find a way to fix this and work together.

The first thing we have to do is realize that security is everyone’s responsibility. This is because building applications involves so many more people than just some developers. Is SQL Injection the outcome of insecure coding, most definitely yes it is. However, that is why development teams have layers. There are those writing code, but there are also testers involved with verifying that the developer didn’t miss something. People make mistakes, and that is why we put a second and third pair of eyes on things. If developers were perfect and did everything right the first time, would there even be a need for QA? QA is a big part to this puzzle, lets get them involved.

I don’t know if anyone else feels this, but I feel as though there is this condescending tone that comes from both sides. Developers don’t think they need security to come in and test and security has this notion that because they found a vulnerability that “I win” and “you lose.” We start security presentations off with “developers suck” or “we are going to pick on you today”, but why does it have to be that way. Constructive criticism is one thing, but lets be somewhat civil about it. Who wants to go the extra mile to fix applications when it comes across as a put down to the developers. This isn’t boot camp where we need to destroy all morale and then build them up the way we want.

I challenge the security guys to think about this when they are getting ready to criticize the developers. What if the situation were reversed, and you were required to find EVERY security issue in an application? Would you feel any pressure? How would you feel if you missed just one simple thing because you were under a time crunch to get the assessment done? I know, the standard response is that is why you chose the security field, so you didn’t have that requirement. I accept that response, but just want to encourage you to think about it when working with the teams that are fixing these issues. Fortunately, security practitioners don’t have this pressure, they just have to find something and throw a disclaimer that they don’t verify that the app doesn’t have other issues that were not identified during the test. Not everyone can choose to be in security, if they did, we wouldn’t have anyone developing. Don’t tell anyone… but if no one develops, there isn’t a whole lot left to manage security on. Interesting circle of life we have here.

This is not all about attitude coming from security. It goes both ways, and many times it can be worse from the dev side. I can’t tell you how many times I have seen it where the developers are upset as soon as they hear that their application is going through a penetration test. People mumbling about how their app is secure and how they don’t need the test. Unfortunately, there are many reasons why applications need to be tested by a third party. It is a part of development, get used to it. The good news is that these assessments are beneficial in multiple ways. First, you get another pair of eyes reviewing your app for stuff probably no one else on your team is thinking of. Second, you are given a chance to learn something new from the results of the test. Take the time to understand what the results are and incorporate the education into your programming. There are positives that come out of this.

Developers also need to start taking responsibility to understand and practice secure coding skills. This is paramount because so many vulnerabilities are due to just insecure coding. This involves much more than just the developers though. As I mentioned in a previous post, we need to do a better job of making this information available to the developers. Writing a book or tutorial, include secure coding examples, rather than short examples that are insecure. Making easier resources for developers to find when looking for secure coding principles. Many times, it is difficult to find a good example of how to do something because everyone is afraid if they give you something and it later becomes vulnerable they will be liable (blog post for another lifetime). Even intro to programming courses should demonstrate how to do secure programming. How difficult is it for an intro course to show using parameterized queries instead of dynamic queries? Same function, however one is secure. Why even show dynamic queries, that should be under the advanced section. Lets start pushing this from the start.

Eoin Keary recently posted XSS = SQLI = CMDi=? talking about the terminology used in security and how we look at the same type of vulnerability in so many different ways. I couldn’t agree more with what he wrote and I talk about this in the SANS Dev544: Secure Coding in .Net course. I can’t count how many times I point out that the resolution for so many of these different vulnerabilities is the same. Encode your output when sending to a different system. I understand that everyone wants to be the first to discover a new class of vulnerability, but we do need to start getting realistic when we work with the “builders” as Eoin refers to them as to what the vulnerabilities really are. If as a developer I don’t have 24 vulnerabilities I have to learn and understand, but realize that is really just 5 vulnerabilities, that makes it easier to start protecting against them. We need to get better at communicating what the problem is without over complicating it. I understand that the risk may be different for SQL Injection or Cross Site Scripting, but to a developer they are encoding untrusted data used for output in another system.

I think this year is off to a good start with all the conversations being held. There are some really smart people starting to think harder about how we can solve the problem. As you can hopefully see from the large amount of ranting above, this is not any one groups fault for this not working. There is contention from both sides. And don’t get me wrong, there are a lot of folks from both sides that are doing things right. Developers that are happy to see a pen test and security folks supporting the development side. We need to stay positive with each other and each think about how we interact with each other. We all have one goal and that is to improve the quality and security of our systems. Lets not lose focus of that.

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.

« Previous PageNext Page »