While OWASP has been around for a long time, and many security experts are aware of their top 10 web vulnerability report, I thought it would be beneficial to elaborate and share a bit more color on each one. So this blog series will focus on some of the most common web attack vectors, how they are exploited, some examples, and finally how to prevent the exploit on your own applications.
For those who are not familiar, OWASP (Open Web Application Security Project) is an organization that helps web developers and security researchers understand the types of attacks that a site can expect to receive. They have done a great job categorizing the various attacks and providing information on what they are. Every web developer would benefit greatly from reviewing this information so it is at the forefront of their minds while designing and coding for the web.
CSRF: What Is It?
So let’s start with one of my favorite attack vectors. Cross-Site-Request-Forgery (CSRF). CSRF is an attack that exploits the trust a website has for its users. It all starts with authentication. When you visit a website that requires a login, generally you are issued a session cookie. This cookie is used to track you around the site after you login. If it weren’t for this cookie, the site would likely require that you enter a username and password on every page (which isn’t practical).
Another OWASP vector is called “session hijacking.” I’ll elaborate on this in another post, but for now, session hijacking is basically when an attacker somehow steals your session cookie and uses it for himself. Since that is the only way most sites generally track their users, if an attacker starts using your cookie, the site can’t tell the difference between you and the attacker. Both users basically get the same level of access to the same data. Stealing a session cookie isn’t always achievable, and that’s where CSRF comes into play.
In a CSRF attack, the attacker doesn’t need to actually obtain your session cookie. Instead, he just needs to trick your browser into making a request to a site where you are already logged in, which will consequently also carry your session cookie.
CSRF: Example Attack
Let’s take a theoretical bank, “Insecure Bank International,” which provides a convenient web interface for managing your bank accounts. One day, you decide to log in to your account so you can send an electronic payment to your friend. Once you log in, you now have a session cookie for the bank website, and are not required to log in again until some period of time later. You then issue a transaction to send funds to your friend. In the background, a request is made to the server that looks like this:
There are two interesting pieces of data in that request. The destination account number, and the amount. Note that this is a fairly simplistic example, and the viability of a CSRF attack relies on the target URL being relatively static in nature (predictable), which this one is.
Now if an attacker wishes to force you to send them $1,000 from your savings account, she could spend a lot of time trying to steal your session cookie so she can do whatever she wants. Or, she can launch a CSRF campaign to explicitly force a single transaction and nothing else. To do this, all she needs to do is get your browser to make a crafted request to the bank that looks as though you just asked it to transfer money. So in this case, the attacker wants to get you to visit:
As you can see in this version of the URL, the attacker has replaced the destination account with her own account, and the amount with $1,000. Because any request the user makes to “fakebank.com” will carry the session cookie along with it (and thus be authenticated), all the victim would need to do is type that URL into his browser and hit enter, which would cause the money to be transferred to the attacker. Of course most users are smart enough not to follow such a link.
The easiest way to get a user to visit that URL unknowingly is to embed a resource in an unrelated page that points to it. For example, let’s say the attacker knows you visit a forum on car restoration. They could sign up for an account, and reply to one of your posts, including an image of a cool new exhaust system. Unfortunately, the image doesn’t point to a picture of an exhaust system, but instead points to your bank and its transfer money URL.
So after sending your friend some money, you decide to go check up on your car forum posts. You discover that someone replied to your post and quickly go take a look. The reply loads up, and you read it, slightly disappointed that the image of this revolutionary exhaust system didn’t load.
What you don’t realize, is that the image isn’t intended to load, it’s intended to steal money behind your back. The browser attempted to go fetch the image, but unintentionally told your bank to send the attacker money. Since the resulting response from the bank was likely HTML, the image didn’t render.
CSRF: Flavors of Exploitation
There are tons of different flavors of this attack designed to overcome various limitations in the way a site initiates actions. For example, some sites won’t accept all the parameters in the query string (which is a good thing). This means that an attacker needs to actually force a hidden form to post to a hidden iframe to launch the attack.
The most commonly practiced solution to preventing CSRF attacks is something called a “CSRF Token.” As mentioned before, the critical requirement for a CSRF attack to work is having a predictable URL to attack. You need to know exactly how to craft the fake request (within a few unknown bits) so that the server will accept it and perform the desired action. Embedding a large unknown unpredictable value in the URL makes it impervious to CSRF attacks by themselves.
Generally to pull this off, you issue a second cookie along with the session cookie that contains a randomly generated string of characters. You then have your webapp embed that cookie’s value in the URL and forms. When you receive a request, you verify that the random string in the parameters matches the one in the cookies. Since the attacker can’t read the cookie value, they won’t be able to predict the URL, and won’t be able to launch a CSRF attack. For example:
The attacker doesn’t know the value of the “csrf” parameter and, therefore, can’t create code to fake it. The only way for the attacker to obtain the CSRF token would be by using a cross-site-scripting (XSS) vector to extract it from the source, which obviates the need for CSRF in the first place. If you can launch XSS, you don’t need to use CSRF.
Adding CSRF tokens throughout the application on every URL that takes an action on the user’s account is a great defense. The problem is that it is extremely time consuming and painful to integrate into a large application. Fortunately, many browsers are now adding native protection for CSRF attacks, but it may be a while before they are extremely effective at it.
Bottom line, if you have a web app, it would be wise to consider how you will protect it against CSRF attacks until they are fully handled by the browser. Alternately, solutions such as Junos WebApp Secure have built-in protection for such attacks and can help make protecting your applications from common attack vectors far easier.