Skip to main content

How Not To Prevent CSRF in a RESTful Service

May 04, 2015

On a recent client engagement, I was given a RESTful service as a target of an application penetration test.  Its target consumer was both a web app and a mobile app.  Like many RESTful services, it was also stateless and vulnerable to Cross Site Request Forgery (CSRF) out of the gate.

The client’s developers got right on fixing the CSRF vulnerability.  Their second iteration of the service was quite complicated with a new anti-CSRF security strategy: hash-based message authentication code (HMAC) tokens in custom HTTP request headers.  Thanks to teammate Johnny Yu’s example burp extension to edit HTTP headers written in python, whipping up a burp extension to build these custom HMAC headers was quick and easy.  The following is an example request with the new HMAC headers:

GET /api/some/endpoint?id=0 HTTP/1.1

Host: [redacted]

time: 2015-03-19T16:45:08Z

userid: jsmith1

hmac: wiRs8BfHGWqpNBFXieVxwDQ9%2Bbbsv0cuiwpNDFiUW40%3D


The HMAC in this example is simply the relative URL with query string parameters for GET requests (POST requests included the JavaScript object notation (JSON) encoded message body) concatenated with the timestamp and user ID of the request (“time” and “userid” above).  The application generates a keyed SHA256 hash from the concatenated string and places the result into the “HMAC” header.  The following python snippet demonstrates this process:

import hashlib

import hmac

import base64

key = 'ufS01i0TK2DfKe4uiduBSyEjX+Os62ojBGk9KxXN5qc='

url = '/api/some/endpoint?id=0'

date = '2015-03-19T16:45:08Z'

userid = 'jsmith1'

expected = 'wiRs8BfHGWqpNBFXieVxwDQ9+bbsv0cuiwpNDFiUW40='

calculated = base64.b64encode(, url + date + userid, hashlib.sha256).digest())

print url

print date

print userid

print "Calculated: %s" % calculated

print "Expected: %s" % expected

if calculated == expected:

    print "Successful Match"

At first glance this appears like a decent solution.  After all, the server can generate the same HMAC by disassembling each request that comes in, concatenating the various pieces together, and applying the same key to the SHA256 hash.  To make really sure these requests couldn’t be replayed, the client’s developers setup a very short time to live (30 seconds) timeout policy to these messages, enforced on the server.  The messages themselves appear to be unpredictable due to these custom HMAC headers, which can be easily set on any requests initiating from a mobile app consumer and can also still be set in the browser when using XmlHttpRequest in JavaScript.

The following is an excerpt of JavaScript similar to what was in the consumer web app:

function generateHmac(data) {

      var hash = CryptoJS.HmacSHA256(data, CryptoJS.enc.Base64.parse(hmacKey));

      hash = hash.toString(CryptoJS.enc.Base64);


      return hash;



function ajaxGetReq(uri) {

      var headers = authHeaders;

      var date = new Date();

      headers.hmacTime = date;

      headers.hmac = generateHmac(uri+date+userid);


            type : "GET",

            url : domain + uri,

            headers : headers,

            async : true,

            dataType : 'json',



Note the highlighted reference to a global variable containing an HMAC key.  In this case, the client shared the key across all service consumers, from the web app to the mobile app.  Since this key was shared, there are plenty of opportunities to grab a copy of it: from the browser, the raw HTTP server response, the mobile app’s configuration or local storage, etc.  If a web app can generate these HMACs, then a third-party web app can also forge them as part of a dynamically created CSRF attack. 

The moral of the story is that it’s risky business to build your own security features.  This problem is draped in new-ish technology (RESTful services), but at the end of the day it’s the same problem crypto implementers have had forever: where is the key and who has a copy of it?  Improperly implemented HMAC header authentication is not an automatic talisman against CSRF. 

If you or your team is building something similar, have you considered all the angles?  Let us review your RESTful services to find out.

Related Blogs

June 07, 2018

Quick Tips for Building an Effective AppSec Program – Part 3

This is the last post in my series on creating an effective AppSec program within your organization. In my last post, we discussed the importance of t...

See Details

May 10, 2018

Observations on Smoke Tests – Part 3

While attending one of our technology partner’s security training courses, the instructor presented on their product’s various features and capabiliti...

See Details

May 03, 2018

Getting Started with Postman for API Security Testing: Part 1

Postman is a useful tool used by many developers to document, test and interact with Application Programming Interfaces (APIs). With the ubiquity of A...

See Details

How Can We Help?

Let us know what you need, and we will have an Optiv professional contact you shortly.

Privacy Policy


May 09, 2018

Application Security

Learn how Optiv can help protect your most critical enterprise applications from both internal and external threats.

See Details

July 21, 2015

Network Security Solutions

Learn how we help protect your environment while maintaining connectivity.

See Details

September 25, 2017

DDoS Threats: Are Your Third Parties Protecting You?

There’s evidence that ransomware may be evolving beyond holding data hostage. In recent news, DDoS attacks were used as a threat against organizations...

See Details

Stay in the Know

For all the latest cybersecurity and Optiv news, subscribe to our blog and connect with us on Social.


Join our Email List

We take your privacy seriously and promise never to share your email with anyone.

Stay Connected

Find cyber security Events in your area.