/Plainmaker

Plainmaker is a fully-implementable and programmable AESKiller-like Interface class for Burp extension.

Primary LanguagePythonGNU General Public License v3.0GPL-3.0

Plainmaker: Burpsuite Plugin

A Programmable and Implementable AESKiller-like Burpsuite Extension

Background

After some hours working to reverse engineer the encryption/decryption process of a mobile application, Jojo successfully comes up with a crypt.py script that allows him to generate a customized and encrypted HTTP requests and responses.

However, since it is a script, then Jojo must copy the values outputted by the script, paste it into Burpsuite, then send it away; like this:

Jojo's Illustration

Using AESKiller is also not an option because, for example:

  • The mobile application uses a unique AES encryption method that involves different keys and initialization vectors for encrypting HTTP request and HTTP response.
  • Certain calculations (such as XOR) must be performed on the key or initialization vector before it can be used in the encryption/decryption process.
  • The key or initialization vector is generated dynamically or must be obtained from somewhere within the HTTP request or response.
  • The mobile application may not be using AES encryption/decryption at all.

So, if sometimes in the future you find yourself suffering like Jojo, this repository might be for you.

Features

  • Fully-customizable and implementable Interface class for creating your own Burpsuite Extension.
  • Implement your custom encryption/decryption code and integrate them directly into Burpsuite requests and responses.
  • Total control over the encryption/decryption flow and choice of algorithms (e.g. AES, RSA, DES, etc.).
  • Written in Python/Jython 2.7.3.

What It Does

In hindsight, this is similar to what AESKiller is doing:

  • The IProxyListener decrypt requests and encrypt responses, and an IHttpListener than encrypt requests and decrypt responses.
  • Burp sees the decrypted traffic, including Repeater, Intruder and Scanner, but the client/mobile app and server see the encrypted version.

However, there will be no static input boxes to insert an AES key and IV; you have the freedom to implement the flow of the encryption/decryption by yourself.

Huh? Then?

Simply take your encryption/decryption script (like Jojo's crypt.py), then rewrite it into a Python class that implements IEncryptDecrypt interface, and voila. The encrypted/decrypted values will be injected into Burpsuite's requests/responses automatically.

How It Works

Plainmaker Illustration

Plainmaker has 4-stage encryption/decryption interfaces that can be implemented and overridden in your own Python script.

Stage Interface Method When to Implement?
Request Decryption decrypt_http_request(original_request, iRequestInfo) When the HTTP request is encrypted and you want Burpsuite to display it in the decrypted format.
Request Re-encryption encrypt_http_request(original_request, iRequestInfo) When the decrypted HTTP request has been modified and you want to re-encrypt it so that it stays valid upon received by the server..
Response Decryption decrypt_http_response(original_response, iResponseInfo) When the HTTP response is encrypted and you want Burpsuite to display it in the decrypted format.
Response Re-encryption encrypt_http_response(original_response, iResponseInfo) When the decrypted HTTP response has been modified and you want to re-encrypt it so that it stays valid upon received by the application.

Every methods above receives two (2) parameters by design, original_request or original_response and iRequestInfo or iResponseInfo.

original_request: string

A parameter that contains the original HTTP request in Python string format.

original_response: string

A parameter that contains the original HTTP response in Python string format.

iRequestInfo: object

A parameter that contains Burp interface object used to retrieve key details about the HTTP requests. See iRequestInfo for more information.

iResponseInfo: object

A parameter that contains Burp interface object used to retrieve key details about the HTTP responses. See iResponseInfo for more information.

Quick Start (Example)

First, you have to create a Python class that implements IEncryptorDecryptor interface. Then, in most cases you will only need to override some of the 4 interface methods above according to your needs.

Here is an implementation example to decrypt every HTTP request using a static key (secure_r4ndom_key_1337) and IV (secure_r4ndom_IV_1338) and then calls a user-defined function named my_decryption_algorithm() to decrypt the content of the HTTP request body:

class MyCustomEncryptorDecryptor(IEncryptorDecryptor):
    
    # Overrides decrypt_http_request() from IEncryptorDecryptor interface
    def decrypt_http_request(self, original_request, iRequestInfo):
        
        # Get the original HTTP request body
        req_body = IEncryptorDecryptor.get_http_body(original_request, iRequestInfo)
        key = "secure_r4ndom_key_1337"
        IV = "secure_r4ndom_IV_1338"

        # Run your decryption algorithm workflow here
        # ...
        decrypted_body = my_decryption_algorithm(req_body, key, IV)

        # Should always return a dictionary containing 'headers' and 'body' attributes. 
        # The decrypted request body is returned here.
        return {
            "headers": {
                "X-API-Key": key,
                "X-Some-Extra-Header": "you_can_inject_new_header_here_as_well"
            },
            "params": {},
            "body": "request=%s" % decrypted_body
        }

In a nutshell, Plainmaker works by injecting your modified HTTP headers and HTTP body into Burpsuite. Henceforth, each of the interface methods you override should return a dictionary containing two attributes: headers and body. These attributes represent the HTTP headers and body that you want to add to the original request or response.

Thus, when Burpsuite intercepts an HTTP request or response, it will insert/update the headers and body from your dictionary into the original request or response.

Plainmaker Burp Preview 1

Installation

1. Building the Plainmaker Extension

In essence, there are two (2) "TODO:" marks that we have put into the plainmaker.py source code in this repository, indicating sections of code that you need to write/customize by yourself. Before installing the plugin into Burpsuite, you have to visit both sections and write your changes there.

A. Write and implement your own encryptor-decryptor class.

#####################################################################
# TODO: Write and implement your own encryptor-decryptor class here.
#####################################################################

class MyCustomEncryptorDecryptor(IEncryptorDecryptor):
    def __init__(self):
        super().__init__()

    def encrypt_http_request(self, original_request, iRequestInfo):
        return {
    
    # ...

In this TODO: section, you need to create a new Python class that implements IEncryptorDecryptor interface.

After that, according to your needs, you might want to override any of the following available methods according to your needs:

  • decrypt_http_request(original_request, iRequestInfo)
  • decrypt_http_response(original_response, iResponseInfo)
  • encrypt_http_request(original_request, iRequestInfo)
  • encrypt_http_response(original_response, iResponseInfo)

In each of those methods, implement the encryption/decryption code that fits the cryptographic operation of your application, then return a dictionary object containing two attributes: headers and body. The returned values will be injected into Burpsuite when it displays the intercepted HTTP requests or responses.

See samples directory for detailed examples.

B. Create a new instance of your encryptor-decryptor class.

class BurpExtender(IBurpExtender, IHttpListener, IProxyListener):
    HTTP_HANDLER = 0
    PROXY_HANDLER = 1

    def __init__(self):
        # TODO: Create a new instance of your encryptor-decryptor class here.
        encdec = MyCustomEncryptorDecryptor()

    # ...

Burpsuite's extension logics and workflow is placed in another class named BurpExtender. Hence, in this TODO: section, you have to create a new instance of your encryptor-decryptor class and store it into a variable named encdec inside the BurpExtender class.

Then, that's all. Every interface methods that you have overridden will be called automatically when Burpsuite receives HTTP requests and responses.

See samples directory for detailed examples.

2. Installing Plainmaker Extension to Burpsuite

Use the following tutorials to install Python-based extension (like Plainmaker) into Burpsuite.

  1. Install Jython: https://burpsuite.guide/runtimes/python/
  2. Install Python extension into Burpsuite: https://portswigger.net/burp/documentation/desktop/extensions/installing-extensions

Frequently Asked Questions (FAQ)

What if I don't want to modify Burpsuite's original HTTP headers/body on a certain encryption-decryption stages?

Suppose you don't want to modify both HTTP headers and body on the Request Re-encryption stage, then in the overridden encrypt_http_request() method you simply set the headers and body attribute into False.

Contributors

  • Chrisando 'siahaan' Ryan
  • Henky 'kazuya' Tornado