Showing posts with label application security. Show all posts
Showing posts with label application security. Show all posts

Jan 6, 2012

Stateless CSRF Protection

In the era of RESTful services and rich internet applications it's important to find security solutions that don't impose unnecessary state or computation on servers. I previously wrote a post on stateless session ids. Let's have a look at how we can protect against cross-site request forgeries (CSRF) without server-side state.

CSRF Basics
Forged requests are nasty attacks. They rely on the fact that your browser automatically adds cookies to HTTP requests if it has cookies associated with the target domain and path. That includes session cookies.

Let's say you're currently authenticated to twitter.com. If you visit another site on another domain that site can issue requests to twitter.com and your Twitter session cookie will be added to those requests.



How can domain B issue requests to domain A, formally doing a cross-site HTTP request? Well, there are some obvious cases – images, JavaScript, and CSS.

<img src="whatever.domain.org/path/logo.png" />

… is allowed from any site, which means a malicious site can contain tags like …

<img src=”https://secure.bank.com/checkAccounts" height=0 width=0 />

Such a tag will issue an HTTP GET to secure.bank.com/checkAccounts including the victim's session cookie for *.bank.com should he or she be logged in. The browser doesn't know if there's an image on that URL or not. It just fires the request. And by setting the image size to 0x0 the victim will see nothing.

CSRF With POST
Most sensitive stuff require an HTTP POST since a GET should be idempotent and not change any state server-side. So can a malicious page issue an HTTP POST to any domain? Yes.



The CSRF code from the image above ($ is jQuery):

<form id="target" method="POST" 
 action="https://1-liner.org/form">
  <input type="text" value="I hate OWASP!" name="oneLiner"/>
<input type="submit"
 value="POST"/>
</form>


<script>
  $(document).ready(function() {
     $('#target').submit();
  });
</script>

CSRF Against RESTful Services
But maybe you've left HTML forms behind and go with rich clients, a RESTful backend and communication via JSON? Can a malicious page issue an HTTP POST targeting such services? Yes.

You can change the encoding of HTML forms to text/plain and do some tricks to produce parseable JSON in the request body. Here's an example that I got working with a Java JAXRS backend:

<form id="target" method="POST" 

action="https://vulnerable.1-liner.org:
8444/ws/oneliners" 

style="visibility:hidden"
 enctype="text/plain">
  <input type="text"

   name='{"id": 0, "nickName": "John",
          "oneLiner": "I hate OWASP!",

          "timestamp": "20111006"}//'
   value="dummy" />
  <input type="submit" value="Go" />

</form>

Notice the enctype and that the JSON is in the input name, not the value. The above form produces a request body looking like this:

{"id": 0, "nickName": "John","oneLiner": "I hate OWASP!","timestamp": "20111006"}//=dummy

… which is accepted by for instance the Jackson parser.

CSRF Protection With Double Submit
Traditional anti-CSRF techniques use tokens issued by the server that the client has to post back. The server validates the request by comparing the incoming token with it's copy. But that small word "copy" means server-side state. Not good.

Double submit is a variation of the token scheme where the client is required to submit the token both as a request parameter and as a cookie.



A malicious page on another domain cannot read the anti-CSRF cookie before its request and thus cannot include it as a request parameter.



Two Misconceptions About Double Submit
There are two common misconceptions about the double submit CSRF protection.

First, it has been suggested that the session cookie should be used for this purpose. Since you have to use JavaScript to pick up the cookie value and add it as a request parameter the cookie cannot have the HTTPOnly attribute. And you want HTTPOnly on your session cookie to prevent session hijacking via cross-site scripting.

But you should not use the session cookie as anti-CSRF cookie. Instead add a specific anti-CSRF cookie which does not have the HTTPOnly attribute and keep your session cookie protected.

Second, people have stuck with server-generated, stateful anti-CSRF cookies. But double submit cookies can be generated client-side and don't have to be saved by the server at all.

Stateless CSRF Protection with Double Submit
The protective measure of double submit lies in the fact that a malicious site cannot read the cookie and include it as request parameter. That condition still holds if the cookie is generated by the client and never saved by the server.

So let the client generate the anti-CSRF value and only compare and check format of cookie and request parameter on the server. Ergo, stateless CSRF protection!



Hardening the Double Submit Protection
Double submit protection breaks down if the attacker somehow can read or set the anti-CSRF value. We can harden double submit against malicious reads.

First of all we make the client change the anti-CSRF value upon every request. This is typically done by centralizing backend calls to a custom AJAX proxy, possibly inherited.

Second, we zero the anti-CSRF cookie directly after each backend call. This will allow for accurate server-side detection of forged requests. A zeroed double submit cookie is a clear signal of either a client-side bug or a forged request. With zeroed anti-CRSF cookies the attacker has to issue his/her attack to exactly when the cookie is set by the client.

Drawbacks of Double Submit
You typically hear two drawbacks of the double submit protection – it's reliance on JavaScript to add the cookie value as request parameter, and the possibility to read the anti-CSRF cookie via cross-site scripting.

The issue with JavaScript is diminishing as JavaScript is becoming a requirement for more and more sites anyway.

The cross-site scripting critique is invalid. If you can script the site you already own all of it and can setup your own AJAX proxy, read any tokens in the DOM etc.

Mar 21, 2011

The 5 Complexity Dimensions of Software

I've used this image on countless occasions in my talks on software and on application security. I got it from an academic research presentation back in 2004 or so.

The 5 Complexity Dimensions of Software
 
Complexity in this regard means complex for humans to understand and contribute to.
  1. Scale. The larger the system, the more complex.
  2. Diversity. The more frameworks, languages, integration techniques, tools, platforms, and design patterns used, the more complex.
  3. Connectivity. The more connections, the more complex. This relates to coupling.
  4. Dynamics. The more number of states or the larger state space, the more complex.
  5. Refinement. Over time every living piece of software is refined, optimized, and polished. Corner cases are found and handled, and regression test suites grow. Refinement drives complexity.
In the context of application security there's always a relation between security and complexity. The more complex a system gets, the higher the risk of security vulnerabilities. Therefore managing application security is partly about managing the five dimensions above.

Sadly, computer science undergraduates rarely meet or learn about this kind of software complexity. That's why industry is reluctant to hire them. Solving 100 coding assignments comprising 200 lines of code each, just doesn't equal developing a system of 20,000 lines of code.

Tomorrow I will give a talk on why and how CS undergrads at Linköping University should learn about software complexity.

Nov 21, 2010

AppSec Manifesto

To start this blog off I want to publish my personal AppSec Manifesto.

AppSec Manifesto
  • Developers are not lazy, rather quality oriented ⇒ Insecure applications do not stem from laziness.
  • Features and functions are always more important than security ⇒ Security should enable more features and functions.
  • Responsible disclosure is a good way of achieving more secure applications ⇒ Hackers are needed.
  • Technology is a crucial part of security ⇒ Therefore I keep coding.

This manifesto will most probably evolve along with my future insights.