Two months ago I tried testing a REST API that used OAuth 1.0 for authentication and I prefer to use Burp Suite for such tasks. My only problem was that OAuth 1.0 requires signing each request with a different nonce, so using the built-in scanner of Burp would've been impossible without Burp learning how to do it.
I tried solving the problem by setting an oauth-proxy as an upstream proxy in Burp, and I even sent a patch to make it work with Burp, but I had some problems with it, and since I wanted to try Burp Extender since the day it was announced, I decided to write a Burp plugin. Although it's possible to write such plugins in Python and Ruby as well, I found that they required Jython and JRuby, which I consider worst of both worlds, so in the end, I did it using Java, the lesser of two (three) evils.
I searched the web for sensible Java OAuth implementations, and chose
Signpost since it had a pretty straightforward API and depended only on
the Apache Commons Codec library. To meet the deadlines, I hand-crafted
the HTTP parsing and generator class called BurpHttpRequestWrapper
that
wraps an object that implements the IHttpRequestResponse
interface of Burp,
and itself implements the HttpRequest
interface that Signpost uses to
read and manipulate HTTP requests. I also created a simple test suite using
JUnit 4 that makes sure that my code doesn't break HTTP requests in any
unexpected ways. Later I found out about the IRequestInfo interface
that would've made it possible to use the internals of Burp to do at least
the parsing part, so I started a branch with a matching name to do
experimentation, although as of 12th June 2013, it doesn't work.
The working version can be found in my GitHub repo, the instructions
for building and configuring can be found in the README. Below is an example
demonstrating the verify_credentials method of the Twitter API 1.1 using
the repeater module of Burp. Although the request at the top doesn't have
an Authorization
header, Twitter responded with 200 OK
, so the plugin
inserted the appropriate headers correctly. The actual header can be seen if
the logging of HTTP requests is enabled in the Options
> Misc
tab.
======================================================
19:52:27 https://api.twitter.com:443 [199.16.156.40]
======================================================
GET /1.1/account/verify_credentials.json HTTP/1.1
Host: api.twitter.com
Authorization: OAuth oauth_consumer_key="xxx",
oauth_nonce="-181747806056868046",
oauth_signature="QZDwnam9I%2FrCdXzj4l3mnPSgRlY%3D",
oauth_signature_method="HMAC-SHA1",
oauth_timestamp="1371059545",
oauth_token="xxx", oauth_version="1.0"