Skip to main content
Whats custom cryptography?

Occasionally, you’ll run into webapps (and mobile apps, and thick clients) that use some kind of custom cryptography over and above the standard TLS. Often, this is used to frustrate and slow down attackers, as a form of security through obscurity. While we suggest you never rely on obscurity to keep you secure, it can be effective at slowing down attackers — as well as security testers.

For example, when using an intercepting proxy for a web application implementing custom crypto, you might see a request that looks like this:

POST /login HTTP/1.1
Host: localhost:5000
Content-Length: 466
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Referer: http://localhost:5000/
Connection: close
​
mac=iF9z1rkwF%2FZm1ks%2BKxI7ut%3D%3D&data=9IM4B3nHzL%2B7UUMt6eKDCvRmND6fuYxA%2FJhqmKv
Mhy8%3D&sign=W0cgfjlcEaT5yIEeeOAQaSIT6zIKIwpTmjnGmHFp4QPwtOogx9rYMLbw2YUtIvno%2FUdZvl
gCHTgGk2rUR2D385T%2BwxudllIMW1zJPRbNlG4l8eoewQCa%2B1iG4v334ZVEMCe8za4tnuQltyKDp9E%2Bm
vJch3MMyCKg44MJsGr%2Fh99BFHIAFlsftKWYVfv6sb%2FRzamHG05e91YYcXqq8bbu4i9O2E0oQLZ87Irr2S
f1n7XaQyAVEAr7PuOL1%2FKEBku4LL%2Fbad10HlSNpvDaaIDp5SIp%2Bd4oI7lABfk1zCd6qTDBc1jmu2I9K
n4uxelNKsmwvSjOcV0UBVlK8P2Zcyf%2FLA%3D%3D

In this state, merely inspecting the traffic at a protocol level is clearly not useful for anyone trying to understand the application, but the application continues to work just fine for end users.

Throughout this blog post, the example application code and HTTP traffic shown are from my Custom Crypto Example Webapp published on the MWR CyberSec Github. ​

If we poke through the application’s client-side source code, we can see that the app uses AES, RSA and… rot13?

const rawAesKey = window.crypto.getRandomValues(new Uint8Array(16));
let mac = rot13(window.btoa(String.fromCharCode(...rawAesKey)))
const aesKey = await getSecretKey(rawAesKey)
const rsaKey = await getPrivateKey()
let rawdata = "username=" + formDataObj["username"] + "&password=" + formDataObj["password"]
let data = window.btoa(String.fromCharCode(...new Uint8Array(await encryptMessage(aesKey, enc.encode(rawdata).buffer))))
let sign = window.btoa(String.fromCharCode(...new Uint8Array(await signMessage(rsaKey, enc.encode(rawdata).buffer))))

Well, since we have access to the client-side source code, we can see exactly what the app is doing, and replicate this ourselves. Ideally, we would want to do this in a way that would allow us to see and interact with the application’s HTTP traffic and one of the better ways to accomplish this is by extending Burp Suite.

What are Burp extensions?

​The Burp Extender API allows you to write code to interact with many Burp Suite tools. For example, we can change how Intruder processes payloads, or add insertion points to the Scanner, or interact with Collaborator, or modify the GUI, amongst other things.

Burp has recently moved from their old Wiener API (see The fame of Peter Wiener for a bit of the history behind the name) to the new Montoya API, which has simplified extension development. Where Montoya class names are mentioned, the similar old Weiner API classes are included in square brackets.

Existing work

The Burp BApp Store has existing extensions such as AES Killer, AES Payloads and Decompressor, which specifically handle AES and compression in requests. For more advanced or unique implementations of custom cryptography or compression or encoding, such as my Custom Crypto Example Webapp, it is desirable to have an extensible set of template code that can be used to write your own code to convert requests and responses into something usable. Custom problems (and applications) require custom solutions, after all.

The approach

​One common method for writing extensions required you to write a new class for every Burp feature you wanted to add. For example, if you wanted to use Repeater and Proxy, you’d use an HttpRequestEditor/HttpResponseEditor [IMessageEditorTab] to have a decrypted message tab (this is generally the feature you’d want to use the most). If you instead wanted to use Intruder, you’d use PayloadProcessor [IIntruderPayloadProcesser]. If you wanted to use Scanner, you’d use ScanCheck [IScannerListener], etc… With this approach, enabling custom treatment for session handlers, Sequencer, etc. would likely take even more time.

My extension uses ProxyRequestHandler, ProxyResponseHandler [IProxyListener] and HttpHandler [IHttpListener] to transparently decrypt requests and encrypt responses so that none of Burp’s tools (except Proxy) ever see an encrypted request. This makes it faster to write a usable extension, and has the added benefit of making testing significantly easier from a usability perspective. Instead of seeing HTTP payloads like:

mac=iF9z1rkwF%2FZm1ks%2BKxI7ut%3D%3D&data=9IM4B3nHzL%2B7UUMt6eKDCvRmND6fuYxA%2FJhqmKv
Mhy8%3D&sign=W0cgfjlcEaT5yIEeeOAQaSIT6zIKIwpTmjnGmHFp4QPwtOogx9rYMLbw2YUtIvno%2FUdZvl
gCHTgGk2rUR2D385T%2BwxudllIMW1zJPRbNlG4l8eoewQCa%2B1iG4v334ZVEMCe8za4tnuQltyKDp9E%2Bm
vJch3MMyCKg44MJsGr%2Fh99BFHIAFlsftKWYVfv6sb%2FRzamHG05e91YYcXqq8bbu4i9O2E0oQLZ87Irr2S
f1n7XaQyAVEAr7PuOL1%2FKEBku4LL%2Fbad10HlSNpvDaaIDp5SIp%2Bd4oI7lABfk1zCd6qTDBc1jmu2I9K
n4uxelNKsmwvSjOcV0UBVlK8P2Zcyf%2FLA%3D%3D

in all your history, you’ll see the equivalent plaintext in all the tools.

To understand what this extension is doing, refer to the drawing below:

Setting up the extension

First, you’ll want to download the extension source from Burp Custom Crypto Extension.

From there, you can modify the extension as needed for the application you’re testing. Of course, if you’re just using this for the example webapp, you can skip the modification.

​In particular, you’ll most likely want to modify the following methods in CustomCrypto.java:

handleRequestReceived()
handleHttpRequestToBeSent()
handleHttpResponseReceived()
handleResponseToBeSent()

In addition, we need to be able to configure the relevant keys for whatever crypto implementation the target application uses. In the case of the  Custom Crypto Example Webapp, this is an RSA private key retrieved from the JS application file performing the cryptography. This is set in the class’ initialize method:

public void initialize(MontoyaApi api) {
        api.extension().setName("MWR CyberSec Custom Crypto Template");
​
        ...
        storage = api.persistence().extensionData();
        ...
        
        //storage.setByteArray("rsaPublicKey", base64.decode("MIIB..."));
        storage.setByteArray("rsaPrivateKey", base64.decode("""
                MII...\
                muEM0Z"""));
        //storage.setByteArray("aesSecretkey", base64.decode("..."));
    }

At this point, any additional Burp API functionality needed for your use case can be implemented.

When you are ready to test or use your extension in Burp, you can run mvn package to build the extension. This will create a .jar file in target/, which you can then import from Burp’s extension tab.

Using the extension

Once the extension has been loaded into Burp, add your targeted requests to the Target Scope, to make sure we don’t try to tamper with any requests outside of the scope. In this case, that will be only the /login endpoint.

​Proxy the application, and BOOM, we have clear, usable requests and responses:

POST /login HTTP/1.1
Host: 127.0.0.1:5000
...
username=a&password=a

HTTP/1.1 403 FORBIDDEN
...
Username is not `MWR`
Debugging

​Unfortunately, I haven’t yet identified a reliable way to debug extensions from Burp, apart from just logging to the console, so I recommend putting in as many logging statements as you need.

Conclusion

I hope that this extension may help you in your own custom cryptography testing, however esoteric the scheme may be. Good luck!

Acknowledgements

This extension based on a prior MWR Burp extension written by Darryl Meyer, and ported to the new Burp Montoya API.

Download Links

Burp Extension Template Code – Burp Custom Crypto Extension

Test Application Implementing Custom Cryptography – Custom Crypto Example Webapp