DEV Community

Cover image for Linux Enumeration and Access Control: What Happens in the First Sixty Seconds on a Target
AnonCoder | assert true
AnonCoder | assert true

Posted on Originally published at Medium

Linux Enumeration and Access Control: What Happens in the First Sixty Seconds on a Target

The first sixty seconds on an unknown target decide whether the engagement is methodical or random.

[LAB ENVIRONMENT — commands executed in a local throwaway sandbox]

# Throwaway reproduction sandbox (runs locally as unprivileged user; display_user="dev")
mkdir -p ~/lab/{reports,scripts,.config}
cd ~/lab
echo "README content" > README.txt
echo "status ok" > reports/q3.txt
echo "API_TOKEN=example-not-a-real-token" > deploy.env
chmod 640 deploy.env
echo "rotate the deploy token before friday" > .reminder
chmod 600 .reminder
printf "todo: archive old reports\r\ntodo: rotate keys\r\n" > notes.txt
printf "\x00\x01\x02\xfe\xff\x00\x00\x00CONNECT db.internal:5432\x00\xde\xad\xbe\xef\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00user=deploy\x00" > data.bin
chmod 755 scripts
Enter fullscreen mode Exit fullscreen mode

What this level is

You land on a shell on a machine you have never seen. There is no map, no architecture diagram, and no administrator telling you what matters. What you do in the next sixty seconds determines whether the rest of the session is disciplined, repeatable, and effective or chaotic and noisy. Professional operators on both offensive engagements and incident response investigations begin with the same three fundamental questions: who am I, where am I, and what is here?

In this guide, we answer those questions against BreachLab's Ghost track, Level 0, titled "First Contact". The level page lists three foundational commands: ls, cd, and cat.

Behind those three simple commands lie decades of computer science history and operating system architecture. In this guide, we examine:

  1. Why identity in Unix is governed by kernel-level numeric IDs rather than environment variables.
  2. How the filesystem hierarchy and hidden dot-files originated from a historical shortcut.
  3. How the access matrix compresses into nine permission bits, and how discretionary access control creates predictable security vulnerabilities.
  • Platform: BreachLab, a free, legal hands-on platform where every level is an isolated, real Linux environment.
  • Track & Level: Ghost I · Level 0 — First Contact (100 points).
  • Target Connection: ssh ghost0@204.168.229.209 -p 2222
  • Commands Covered: whoami, pwd, ls, cd, cat, file, head, tail, strings, xxd, stat, type.
  • Level Objective: Locate the credentials for the next account (ghost1).

Watch the full long-form video walkthrough: https://youtu.be/CJ459itJPeU

Follow along with the complete series playlist: https://www.youtube.com/playlist?list=PLUep6spDxjvo

Compliance Note: In strict adherence to BreachLab creator rules, this article teaches the underlying method, mechanics, and security theory. No passwords, flags, or copy-paste solutions are published.

Today's Topics

  • The Orientation Loop: Executing the initial sixty-second triage using whoami, pwd, and ls -la.
  • SSH Protocol Mechanics: Understanding TCP handshakes, Diffie-Hellman key agreement, and host verification.
  • Identity and Complete Mediation: Why the kernel evaluates effective UIDs rather than shell variables.
  • Filesystem Enumeration: Walking directory tables, understanding inodes, and unmasking dot-files.
  • Permission Bit Triads: Decoding octal modes, directory traversal mechanics, and access matrix theory.
  • Path Traversal with Shell Builtins: Why cd must execute inside the parent shell process.
  • Defensive Content Inspection: Safely examining unknown streams using file, cat -A, and strings.
  • Unsecured Credentials in Files (T1552.001): Real-world impact, kill chain positioning, and honeytoken detection.

Orienting on an Unknown Target: whoami and pwd

When I first connect to a remote target, before typing any complex commands or running automated scripts, I establish orientation. I need to know the security context of the process running my shell and my exact position in the directory hierarchy.

Figure 1: The opening moments on an unknown shell determine the course of the investigation.

I begin by asking the kernel for my active identity. I run whoami:

$ whoami
dev
Enter fullscreen mode Exit fullscreen mode

The command returns dev (or ghost0 when logged into the live target). Behind this single word, the whoami utility executed the geteuid() system call to fetch the numeric effective user ID from the operating system kernel, then performed a lookup against /etc/passwd.

To illustrate why this matters, consider what happens if I rely on the common $USER environment variable instead:

$ echo $USER
dev
$ USER=root
$ echo $USER
root
$ whoami
dev
Enter fullscreen mode Exit fullscreen mode

The environment variable $USER is completely under user-space control. An adversary or a misconfigured script can alter it at will. The kernel's reference monitor completely ignores $USER when enforcing access permissions; it consults only the numeric UID bound to the process structure in memory.

Next, I check my location in the filesystem with pwd:

$ pwd
/home/dev/lab
Enter fullscreen mode Exit fullscreen mode

The pwd (print working directory) command prints the absolute path of the current directory. This path serves as the anchor point for every relative path resolution performed by the kernel during system calls like open() and execve().

Takeaway: Always query the kernel directly for process identity rather than trusting environment variables that user space can manipulate.

Figure 2: BreachLab provides authentic Linux environments over SSH.


Anatomy of an SSH Connection

To reach Level 0, we initiate an SSH connection to port 2222:

$ ssh ghost0@204.168.229.209 -p 2222
Enter fullscreen mode Exit fullscreen mode

Figure 3: Breakdown of an SSH connection string: binary, target account, host address, and non-standard port.

This command initiates a multi-stage protocol exchange:

  1. Transport Layer Handshake: The client opens a TCP connection to port 2222. Port 2222 is chosen by convention for secondary or containerised SSH daemons, avoiding privileged port binding (ports below 1024 require root privileges).
  2. Version Exchange: Both client and server exchange identification strings (e.g., SSH-2.0-OpenSSH_8.9p1).
  3. Key Exchange (KEX): Both sides agree on cryptographic algorithms and execute a Diffie-Hellman or elliptic curve exchange to establish a shared session key without transmitting it over the wire.
  4. Server Authentication: The server signs the exchange with its private host key. The client verifies this signature against its local ~/.ssh/known_hosts file.
  5. User Authentication: Once encryption is established, the client sends user authentication credentials (in Level 0, password authentication; in hardened environments, Ed25519 public keys or certificates).

Takeaway: SSH ensures confidentiality, integrity, and server authentication before a single credential character is sent across the network.


Enumerating the Filesystem: ls and What Else You Could Use

With identity and working directory confirmed, the next priority is inventorying what is present.

Figure 4: The orientation triage answering who am I, where am I, and what is here.

I start with a plain ls:

$ ls
README.txt
data.bin
deploy.env
notes.txt
reports
scripts
Enter fullscreen mode Exit fullscreen mode

A standard ls reads the directory data structure and outputs filenames alphabetically. However, a plain listing hides crucial information. In Unix, files whose names begin with a period (.) are excluded from default directory listings.

To see all entries, I supply the -a flag:

$ ls -a
.
..
.config
.reminder
README.txt
data.bin
deploy.env
notes.txt
reports
scripts
Enter fullscreen mode Exit fullscreen mode

Notice what appeared: . (the current directory), .. (the parent directory), .config (a configuration directory), and .reminder (a hidden text file).

In security assessments, dot-files are prime locations for misconfigured credentials, shell histories (.bash_history), cloud tokens (.aws/), and private keys (.ssh/id_rsa).

To inspect file metadata, I combine flags into the standard enumeration command ls -la:

$ ls -la
total 40
drwxrwxr-x 5 dev dev 4096 Oct  7 07:02 .
drwxrwxr-x 3 dev dev 4096 Oct  7 07:02 ..
drwxr-xr-x 2 dev dev 4096 Oct  7 07:02 .config
-rw------- 1 dev dev   38 Oct  4 07:02 .reminder
-rw-r--r-- 1 dev dev   80 Oct  7 07:02 README.txt
-rw-r--r-- 1 dev dev   61 Sep  7 07:02 data.bin
-rw-r----- 1 dev dev   67 Oct  2 07:02 deploy.env
-rw-r--r-- 1 dev dev   46 Sep 28 07:02 notes.txt
drwxr-xr-x 2 dev dev 4096 Oct  7 07:02 reports
drwxr-xr-x 2 dev dev 4096 Oct  7 07:02 scripts
Enter fullscreen mode Exit fullscreen mode

Figure 5: Examining file metadata, hidden dot-entries, and permission triads with ls -la.

What if ls is not available?

In minimal Docker containers or restricted shells, the ls binary may be absent or restricted. Because filename expansion (globbing) is handled directly by the shell before command execution, we can enumerate files using built-in shell features:

$ echo *
README.txt data.bin deploy.env notes.txt reports scripts
Enter fullscreen mode Exit fullscreen mode

When recursive enumeration is needed, find and tree provide structured visibility:

$ tree -a -L 2
.
├── .config
│   └── app.conf
├── .reminder
├── README.txt
├── data.bin
├── deploy.env
├── notes.txt
├── reports
│   ├── q3.txt
│   └── q4.txt
└── scripts
    └── backup.sh

4 directories, 9 files
Enter fullscreen mode Exit fullscreen mode

Takeaway: Plain ls conceals administrative configuration; standard enumeration requires ls -la or native shell globbing.


Decoding Access Rights: Reading a Permission String

The output of ls -la presents a 10-character string at the beginning of each line. Understanding this string is essential for recognizing privilege boundaries.

Figure 6: Anatomy of a Unix permission string and octal conversion.

Consider the line for deploy.env:
-rw-r----- 1 dev dev 67 Oct 2 07:02 deploy.env

We dissect the string from left to right:

  • Character 1 (File Type): - denotes a regular file. A d indicates a directory, while l denotes a symbolic link.
  • Characters 2–4 (Owner Permissions): rw- indicates the owner (dev) has read (r=4) and write (w=2) permissions, but no execute (x=1). Total = 6.
  • Characters 5–7 (Group Permissions): r-- indicates members of the owning group (dev) have read permission only. Total = 4.
  • Characters 8–10 (Others Permissions): --- indicates any user who is neither the owner nor a member of the group has zero permissions. Total = 0.

The combined octal mode is 640.

We can verify this numeric representation directly using stat:

$ stat -c '%A  %a  %U:%G  %s bytes  %n' README.txt .reminder scripts/backup.sh deploy.env
-rw-r--r--  644  dev:dev  80 bytes  README.txt
-rw-------  600  dev:dev  38 bytes  .reminder
-rwxr-xr-x  755  dev:dev  40 bytes  scripts/backup.sh
-rw-r-----  640  dev:dev  67 bytes  deploy.env
Enter fullscreen mode Exit fullscreen mode

The Crucial Difference for Directories

For files, r allows reading content, w allows modifying bytes, and x allows running the file as an executable program.

For directories, the bits have distinct meanings:

  • r (Read): Grants the ability to list the names of files inside the directory (e.g., with ls).
  • w (Write): Grants the ability to create, delete, or rename files within the directory (contingent on execute permissions).
  • x (Execute/Search): Grants the ability to enter the directory (cd) and access the inodes of files inside it.

Takeaway: Without directory execute permissions, read permissions allow listing names but prevent accessing file contents or metadata.


Navigating the Hierarchy: Moving Around with cd

Navigating the directory tree is accomplished using cd (change directory).

Figure 7: Inspecting command implementations with type: builtins versus disk executables.

When we check the binary location of cd, we encounter a fundamental architectural distinction:

$ type cd ls cat pwd
cd is a shell builtin
ls is /usr/bin/ls
cat is /usr/bin/cat
pwd is a shell builtin
Enter fullscreen mode Exit fullscreen mode

ls and cat are independent executable binaries located in /usr/bin/. When invoked, the shell calls fork() to create a child process, followed by execve() to load the binary into memory.

cd, however, is a shell builtin. In Unix process architecture, a child process inherits a copy of its parent's working directory, but any modifications made by the child to its own working directory do not propagate back to the parent. If cd were an external executable binary, running /usr/bin/cd reports would change the directory of the child process, which would then immediately exit, leaving the user's interactive shell exactly where it started.

Common Navigation Patterns

We test navigation shortcuts across our lab hierarchy:

$ cd reports && pwd && cd .. && pwd && cd ~ && pwd && cd - && pwd
/home/dev/lab/reports
/home/dev/lab
/home/dev
/home/dev/lab
/home/dev/lab
Enter fullscreen mode Exit fullscreen mode

Key shortcuts:

  • ..: References the parent directory entry.
  • ~: Expands to the current user's home directory ($HOME).
  • -: Returns to the previous working directory ($OLDPWD).

Takeaway: cd must be implemented inside the shell process because child processes cannot alter parent process state.


Inspecting Files Safely: cat and the Tools Around It

Once a target file is discovered, we must inspect its contents. The standard utility is cat (short for concatenate).

Figure 8: Examining files safely: content inspection, line terminators, and binary strings.

cat reads file streams sequentially and writes them to standard output. While effective for short text files, dumping arbitrary files directly with cat introduces risks:

  1. Long files scroll off the screen, obscuring terminal history.
  2. Binary files send control characters that can corrupt terminal settings or reprogram keyboard mappings.

To avoid this, we follow a two-step rule: identify first, read second.

We inspect file types using file:

$ file *
README.txt: ASCII text
data.bin:   data
deploy.env: ASCII text
notes.txt:  ASCII text, with CRLF line terminators
reports:    directory
scripts:    directory
Enter fullscreen mode Exit fullscreen mode

Notice notes.txt: it is flagged as containing CRLF line terminators (Windows-style \r\n).

If we view notes.txt with plain cat, the carriage return is invisible. But when we pass -A (show all invisible characters), the hidden control character becomes evident:

$ cat -A notes.txt
todo: archive old reports^M$
todo: rotate keys^M$
Enter fullscreen mode Exit fullscreen mode

The ^M represents carriage return (\r, ASCII 0x0D), while $ marks the newline (\n, ASCII 0x0A). If an automated script parses this file to extract a password or hostname, the carriage return remains attached to the string, causing subsequent authentication requests to fail silently.

Specialized Inspection Tools

When dealing with structured, binary, or large datasets, we use tailored utilities:

1. Inspecting Binaries with strings
Instead of dumping raw bytes from data.bin, strings extracts contiguous printable ASCII sequences (minimum length 4 by default):

$ strings data.bin
CONNECT db.internal:5432
user=deploy
Enter fullscreen mode Exit fullscreen mode

2. Exact Byte Inspection with xxd
To view hexadecimal representations and offsets:

$ xxd data.bin
00000000: 0001 02fe ff00 0000 434f 4e4e 4543 5420  ........CONNECT 
00000010: 6462 2e69 6e74 6572 6e61 6c3a 3534 3332  db.internal:5432
00000020: 00de adbe ef00 0000 0000 0000 0000 0000  ................
00000030: 0075 7365 723d 6465 706c 6f79 00         .user=deploy.
Enter fullscreen mode Exit fullscreen mode

3. Bounded Inspection with head and tail
To read headers or trailing log entries without flooding standard output:

$ head -n 3 reports/q3.txt
line 001: status ok
line 002: status ok
line 003: status ok
Enter fullscreen mode Exit fullscreen mode

4. Recursive Content Searching with grep
When searching across an entire hierarchy for credentials:

$ grep -rn -i 'token' . 2>/dev/null
./.reminder:1:rotate the deploy token before friday
./deploy.env:2:API_TOKEN=example-not-a-real-token
Enter fullscreen mode Exit fullscreen mode

Takeaway: Always classify unknown files with file before reading, and use cat -A to catch invisible carriage returns that break scripts.


Solving Level 0 on the Target Machine

Now we apply our orientation methodology to the live BreachLab Ghost 0 target.

Figure 9: Step-by-step navigation through the target directory structure to locate the level credential.

We log in over SSH as ghost0. The session opens in /home/ghost0. We execute our triage loop:

$ whoami
ghost0
$ pwd
/home/ghost0
$ ls
workspace
Enter fullscreen mode Exit fullscreen mode

The directory contains an entry named workspace. We move into it:

$ cd workspace
$ ls
archive
Enter fullscreen mode Exit fullscreen mode

Inside workspace is a directory named archive. In enterprise systems, archive directories are frequently overlooked during credential rotation sweeps. We descend into archive:

$ cd archive
$ ls
credentials
Enter fullscreen mode Exit fullscreen mode

We find a file named credentials. Before reading it, we verify its format:

$ file credentials
credentials: ASCII text
Enter fullscreen mode Exit fullscreen mode

Finally, we display the credential:

$ cat credentials
Enter fullscreen mode Exit fullscreen mode

(The password output is intentionally redacted in accordance with BreachLab platform rules).

The password string displayed in this file represents the flag for Level 0 and serves as the SSH authentication password for ghost1. We immediately log this credential in an external secure password manager before proceeding to Level 1.

Takeaway: Level 0 requires zero exploit payloads; disciplined filesystem traversal and directory enumeration locate the credential directly.


Figure 10: Complete mediation ensures that every system call requesting file access is validated against kernel process credentials.


Running It

Here is the complete orientation session as executed in our sandbox environment, demonstrating the unbroken workflow from initial connection to secret identification:

$ whoami
dev
$ pwd
/home/dev/lab
$ ls -la
total 40
drwxrwxr-x 5 dev dev 4096 Oct  7 07:02 .
drwxrwxr-x 3 dev dev 4096 Oct  7 07:02 ..
drwxr-xr-x 2 dev dev 4096 Oct  7 07:02 .config
-rw------- 1 dev dev   38 Oct  4 07:02 .reminder
-rw-r--r-- 1 dev dev   80 Oct  7 07:02 README.txt
-rw-r--r-- 1 dev dev   61 Sep  7 07:02 data.bin
-rw-r----- 1 dev dev   67 Oct  2 07:02 deploy.env
-rw-r--r-- 1 dev dev   46 Sep 28 07:02 notes.txt
drwxr-xr-x 2 dev dev 4096 Oct  7 07:02 reports
drwxr-xr-x 2 dev dev 4096 Oct  7 07:02 scripts
$ stat -c '%A  %a  %U:%G  %s bytes  %n' deploy.env .reminder
-rw-r-----  640  dev:dev  67 bytes  deploy.env
-rw-------  600  dev:dev  38 bytes  .reminder
$ file *
README.txt: ASCII text
data.bin:   data
deploy.env: ASCII text
notes.txt:  ASCII text, with CRLF line terminators
reports:    directory
scripts:    directory
$ cat -A notes.txt
todo: archive old reports^M$
todo: rotate keys^M$
$ grep -rn -i 'token' . 2>/dev/null
./.reminder:1:rotate the deploy token before friday
./deploy.env:2:API_TOKEN=example-not-a-real-token
Enter fullscreen mode Exit fullscreen mode

Reading it in groups:

  • Identity & Context: whoami and pwd verify unprivileged user execution inside the lab root.
  • Surface Discovery: ls -la unmasks hidden entries (.config, .reminder) that default listings omit.
  • Permission Assessment: stat reveals that .reminder is restricted to mode 600 (owner read/write only), while deploy.env is mode 640.
  • Stream Verification: file alerts us to Windows-style CRLF terminators in notes.txt, confirmed via cat -A.
  • Targeted Extraction: grep recursively isolates credential assignments without manual file crawling.

Theory: Why Unix Looks the Way It Does

Fifty years of hierarchical abstraction and the accident of dot-files.

Sources

  • Ritchie & Thompson, The UNIX Time-Sharing System (Communications of the ACM, 1974)
  • Unix Programmer's Manual, 1st Edition (Bell Laboratories, 1971)
  • Filesystem Hierarchy Standard (FHS 3.0, Linux Foundation, 2015)

In 1969 at Bell Laboratories, Ken Thompson and Dennis Ritchie began designing a streamlined operating system on a discarded Digital Equipment Corporation PDP-7. The design principles they established remain the structural foundation of modern Linux systems.

Figure 11: The evolution of the Unix directory tree from the 1971 Programmer's Manual to modern FHS.

Ritchie and Thompson formulated four enduring architectural tenets:

  1. Hierarchical Namespace: A single rooted tree where directories contain file descriptors and pointers to subordinate directories.
  2. Unstructured Byte Streams: A file is simply an arbitrary sequence of bytes. The operating system imposes no record delimiters or indexed access methods; interpretation is delegated entirely to user space.
  3. Pervasive File Abstraction: Peripheral devices, storage disks, terminals (/dev/tty), and inter-process communication channels are presented as file descriptors within the namespace.
  4. Tool Composition: Modular utilities that perform a single task well, linked via unidirectional pipes (introduced by Douglas McIlroy in 1973).

In November 1971, the Unix Programmer's Manual (First Edition) formally documented ls, cat, and chdir (the predecessor to cd). In the 1974 CACM paper, directories were defined as simple lookup tables mapping character string names to numeric internal indices called i-numbers (inodes).

The Accident of Dot-Files

The convention of "hidden" files originated as a programming shortcut rather than a deliberate security mechanism. According to a widely cited historical account by Rob Pike, when Thompson and Ritchie added directory navigation, every directory received two structural entries: . (pointing to the directory itself) and .. (pointing to its parent). To prevent these two entries from cluttering directory listings, a check was added to ls: if the first character of a filename was ., the entry was skipped.

This simple prefix check inadvertently caused any file beginning with a period to be hidden from the default listing. Developers quickly adopted this behavior to stash user configuration files (.profile, .bashrc) out of everyday view. In modern security testing, this design artifact makes dot-files the primary repository for unmonitored credentials.

Under the Hood: Directory Inodes

In modern Linux filesystems (ext4, XFS), a directory is an inode containing data blocks filled with directory entries (struct linux_dirent64):

$ ls -i
5771093 README.txt
5771103 data.bin
5771104 deploy.env
5771095 notes.txt
5771100 reports
5771098 scripts
Enter fullscreen mode Exit fullscreen mode

The filename is merely a human-readable link pointing to an inode number. The permissions, file size, timestamps, and data block pointers reside entirely inside the inode table, not within the directory entry itself.


Theory: Why SSH Exists (History, Diffie-Hellman, and MITM)

From plaintext cleartext telnet to cryptographically authenticated sessions.

Sources

  • Ylönen, SSH — Secure Shell Remote Login (1995)
  • RFC 4251: The Secure Shell (SSH) Protocol Architecture (IETF, 2006)
  • Diffie & Hellman, New Directions in Cryptography (IEEE Transactions on Information Theory, 1976)

Before SSH, remote administration relied on Telnet (RFC 854) and the Berkeley r-commands (rlogin, rsh). These protocols transmitted every packet across local networks and the ARPANET in plaintext. Anyone with network access could capture passwords and keystrokes using packet sniffers.

Figure 12: Diffie-Hellman key exchange mechanics preventing eavesdropping over untrusted networks.

In 1995, following a major password sniffing incident at the Helsinki University of Technology, Tatu Ylönen designed SSH-1 as a secure replacement. In 1999, the OpenBSD project developed OpenSSH, which became the global standard implementation, formalized as SSH-2 in RFCs 4251–4254 in 2006.

Cryptographic Foundation: The Diffie-Hellman Key Agreement

The central challenge of remote login across untrusted networks is key distribution: how can two machines agree on a shared secret without an eavesdropper deducing it?

Whitfield Diffie and Martin Hellman solved this in 1976 using modular arithmetic over a cyclic group. Here is a worked example using deliberately small numbers:

  1. Client and server publicly agree on a generator base $g = 5$ and a prime modulus $p = 23$.
  2. The client picks a private secret $a = 6$ and computes the public value $A = g^a \pmod p = 5^6 \pmod{23} = 15625 \pmod{23} = 8$. The client transmits $A = 8$.
  3. The server picks a private secret $b = 15$ and computes the public value $B = g^b \pmod p = 5^{15} \pmod{23} = 19$. The server transmits $B = 19$.
  4. The client computes the shared secret: $K = B^a \pmod p = 19^6 \pmod{23} = 47045881 \pmod{23} = 2$.
  5. The server computes the shared secret: $K = A^b \pmod p = 8^{15} \pmod{23} = 35184372088832 \pmod{23} = 2$.

Both sides obtain the shared secret $K = 2$. An adversary observing the network sees $g=5$, $p=23$, $A=8$, and $B=19$. Computing $a$ or $b$ requires solving the discrete logarithm problem ($g^x \equiv A \pmod p$), which is computationally infeasible when $p$ is a 2048-bit prime or an elliptic curve (Curve25519).

The Man-in-the-Middle (MITM) Threat

Diffie-Hellman establishes encryption against passive wiretapping, but it is vulnerable to an active attacker who intercepts communications and negotiates independent keys with each side.

To prevent this, the SSH server signs the key exchange using its asymmetric host key (RSA, ECDSA, or Ed25519). The client verifies this signature against its local known_hosts file. On the very first connection, the client must rely on Trust On First Use (TOFU), displaying the key fingerprint for manual user confirmation.


Theory: Identity and the Reference Monitor

Complete mediation, separation of identity, and the kernel boundary.

Sources

  • Anderson, Computer Security Technology Planning Study (US Air Force, ESD-TR-73-51, 1972)
  • Saltzer & Schroeder, The Protection of Information in Computer Systems (Proceedings of the IEEE, 1975)

In 1972, James P. Anderson introduced the foundational concept of the Reference Monitor: an abstract machine that mediates all access attempts by active subjects to passive objects.

Anderson defined three mandatory properties for any reference monitor:

  1. Complete Mediation: The monitor must be invoked on every single access attempt without exception.
  2. Tamper Resistance: The monitor mechanism itself must be protected from unauthorized modification.
  3. Verifiability: The monitor must be small and simple enough to be formally analyzed and proven correct.

In the Linux kernel, the Virtual Filesystem (VFS) and the Linux Security Module (LSM) hooks act as the reference monitor. When a process issues an open() or unlink() system call, the kernel intercepts execution, evaluates the credentials stored in the calling process's struct cred, and compares them with the target inode's mode and ownership fields.

The AAA Framework

Identity is partitioned across three distinct security operations:

  • Authentication: Verifying who the entity is (e.g., SSH password verification).
  • Authorization: Determining what the authenticated entity is permitted to do (e.g., filesystem permission bit checks).
  • Accounting (Auditing): Recording what the entity actually did (e.g., Linux Audit logs via auditd).

Real vs. Effective UIDs

Every Linux process maintains multiple UID attributes:

  • Real UID (RUID): Identifies the actual user who spawned the process.
  • Effective UID (EUID): Evaluated by the kernel for filesystem and IPC permission checks.
  • Saved UID (SUID): Enables setuid binaries to drop and regain elevated privileges safely.

When an unprivileged user executes a command, RUID and EUID match. In subsequent Ghost levels, understanding the divergence between RUID and EUID becomes the cornerstone of privilege escalation analysis.


Theory: Enumeration as a Method (Kill Chain, ATT&CK, NIST)

Systematic discovery versus aimless exploration.

Sources

  • Hutchins, Cloppert & Amin, Intelligence-Driven Computer Network Defense Informed by Analysis of Adversary Campaigns and Intrusion Kill Chains (Lockheed Martin, 2011)
  • MITRE ATT&CK Framework: Discovery Tactic (TA0007) (2015–Present)
  • NIST Special Publication 800-115, Technical Guide to Information Security Testing and Assessment (2008)

Security assessments and forensic investigations do not proceed through random trial and error; they operate within structured threat models.

1. The Intrusion Kill Chain

Published in 2011 by Lockheed Martin researchers, the Cyber Kill Chain defines the linear phases of a cyberattack:
Reconnaissance → Weaponization → Delivery → Exploitation → Installation → Command & Control (C2) → Actions on Objectives.

When an attacker establishes an interactive shell on a target, the engagement has passed the Exploitation phase. The attacker enters the initial phase of Actions on Objectives, where local internal discovery is required to understand the operating environment.

2. MITRE ATT&CK Mapping

The MITRE ATT&CK matrix decomposes adversary behavior into specific tactics and techniques. The actions in Level 0 map directly to the Discovery (TA0007) tactic:

  • T1033 (System Owner/User Discovery): Running whoami or id to identify the active user context.
  • T1083 (File and Directory Discovery): Executing ls, find, or tree to map directory trees and locate sensitive files.
  • T1552.001 (Credentials in Files): Accessing unencrypted configuration files, archives, and flat files to harvest credentials.

3. NIST SP 800-115 Methodology

NIST outlines four phases of penetration testing: Planning, Discovery, Attack, and Reporting. Discovery is the engine that drives exploitation: each command run on a target trades operational risk (generating audit logs) for information gain.

Attacker vs. Defender Trade-offs: Quiet vs. Loud Enumeration

  • Quiet Enumeration: Running native shell builtins and a minimal set of standard utilities (whoami, pwd, ls -la). This generates minimal telemetry and blends into normal administrative traffic.
  • Loud Enumeration: Running automated post-exploitation scripts (such as LinPEAS or automated find loops) that touch thousands of files in seconds. This provides rapid discovery but triggers volume-based detection rules in modern Endpoint Detection and Response (EDR) sensors.

Theory: Access Control (The Matrix, DAC vs. MAC, and Design Principles)

Lampson's access matrix, the POSIX compression, and the Saltzer-Schroeder axioms.

Sources

  • Lampson, Protection (ACM Operating Systems Review, 1974 / 5th Princeton Conference, 1971)
  • Saltzer & Schroeder, The Protection of Information in Computer Systems (Proceedings of the IEEE, 1975)
  • Department of Defense Trusted Computer System Evaluation Criteria (TCSEC / "Orange Book", DoD 5200.28-STD, 1983)

In 1971, Butler Lampson formalized access control theory using the Access Matrix Model.

In Lampson's model:

  • The rows represent Subjects (active processes executing on behalf of users).
  • The columns represent Objects (passive entities: files, directories, sockets).
  • Each cell $M[S, O]$ defines the exact access rights held by subject $S$ over object $O$.

Real-world operating systems cannot store an uncompressed matrix with thousands of users and millions of files. Systems store the matrix in one of two ways:

  1. By Row (Capabilities): Each process holds a ticket or capability list granting specific operations.
  2. By Column (Access Control Lists - ACLs): Each object stores a list of authorized subjects and their permitted actions.

The Unix Compression

Unix implements a compressed column-based ACL. Instead of listing every user individually, each file inode stores exactly 9 permission bits, divided into three triads:

  • Owner (User): The identity owning the file.
  • Group: The primary group associated with the file.
  • Other: All other system users.

While computationally efficient and requiring only 12 bits of storage per inode (including setuid, setgid, and sticky bits), this compression creates a structural flaw: an owner cannot grant read access to Alice and write access to Bob without creating a dedicated group.

DAC vs. MAC

  • Discretionary Access Control (DAC): The resource owner determines access permissions. An unprivileged user can set mode 777 on their home directory or credentials file, exposing it to all users on the host.
  • Mandatory Access Control (MAC): Access decisions are governed by a central security policy enforced by the operating system kernel (e.g., SELinux, AppArmor), independent of user intent. Even if a file is mode 777, a MAC policy can block unauthorized process domains from reading it.

Saltzer & Schroeder's Design Principles (1975)

Four of Jerome Saltzer and Michael Schroeder's foundational security principles directly govern our analysis of Level 0:

  1. Least Privilege: Every program and user should operate using the bare minimum set of privileges necessary. A credentials file should never exceed mode 600.
  2. Fail-Safe Defaults: Access decisions must default to denial. Default umask configurations in standard Linux distributions (e.g., 022) create files that are world-readable (644) by default, violating this principle.
  3. Complete Mediation: Every access to every object must be checked on every access attempt, preventing cached permission bypasses.
  4. Psychological Acceptability: Security mechanisms must not impose excessive cognitive or operational friction. When secure secret management is difficult, administrators store plain passwords in local text files.

Theory: A History of Getting Secrets Wrong

From early plaintext shadow files to modern honeytokens and canary credentials.

Sources

  • Morris & Thompson, Password Security: A Case History (Communications of the ACM, 1979)
  • MITRE Common Weakness Enumeration: CWE-798: Use of Hard-coded Credentials & CWE-312: Cleartext Storage of Sensitive Information
  • Paes de Barros, The Honeytoken Approach (SecurityFocus, 2003)
  • CyberArk Threat Research, Unpacking the Uber Breach (2022)

The file credentials discovered in Level 0 represents a recurring design failure spanning five decades of computing.

In early Unix (First through Sixth Editions), /etc/passwd was world-readable (644) because programs like ls needed it to map numeric UIDs to username strings. The file contained the hashed password representations.

In 1979, Robert Morris and Ken Thompson published Password Security: A Case History. They demonstrated that an attacker using a PDP-11/70 could compute approximately 800 password hashes per second. Using a dictionary of 250,000 words, an entire system's password file could be cracked in five minutes.

Their initial defense was the introduction of a salt—a pseudo-random string appended to the password before hashing, preventing global rainbow table attacks. However, as computing hardware accelerated, leaving hashes accessible to unprivileged users became untenable. In 1988, the Morris Worm used automated dictionary attacks against /etc/passwd to propagate across the internet.

The structural remedy was the Shadow Suite: moving the password hashes out of /etc/passwd into /etc/shadow, a file restricted to mode 640 or 600 owned by root:

$ cat /etc/shadow
cat: /etc/shadow: Permission denied
Enter fullscreen mode Exit fullscreen mode

This permission denial is complete mediation working as intended.

The Modern Threat: CWE-798 and Hard-Coded Credentials

While system password hashes were moved to shadow files, application credentials frequently remain in flat files:

  • CWE-798: Use of Hard-coded Credentials.
  • CWE-312: Cleartext Storage of Sensitive Information.
  • CWE-256: Plaintext Storage of a Password.

In 2022, according to published threat research by CyberArk and public disclosures, an adversary compromised an internal network share at Uber. In a PowerShell script stored in a readable folder, the intruder located hard-coded credentials for an administrative service account. Those static credentials provided access to the enterprise's privileged access management vault. No vulnerability exploit was required; the adversary simply read a file that was exposed through lax discretionary access controls.

Turning the Tables: The Honeytoken Strategy

In 2003, Brazilian researcher Augusto Paes de Barros introduced the concept of the honeytoken: an attractive piece of data (a credential, API key, or database record) that has no legitimate operational purpose.

Defenders deploy canary credentials into filesystem paths where intruders typically hunt (~/.aws/credentials, archive/credentials, .env). When an adversary discovers and attempts to authenticate using the token, the central authentication system triggers an immediate, high-fidelity security alert. Through honeytokens, the attacker's enumeration loop is transformed into a detection tripwire.


Theory: The Theory Behind the Loop

Synthesizing the practical workflow with fundamental computer science principles.

Every command executed in the first sixty seconds of an engagement directly probes a core operating system structure:

  1. Who am I? (whoami) $\rightarrow$ Queries the process subject credentials evaluated by the reference monitor.
  2. Where am I? (pwd) $\rightarrow$ Establishes the current namespace node in the rooted directory hierarchy.
  3. What is here? (ls -la) $\rightarrow$ Probes the directory table and maps visible and hidden inode entries.
  4. What can I do? (stat) $\rightarrow$ Evaluates the compressed access matrix governing subject-object interactions.
  5. What is the content? (file / cat -A) $\rightarrow$ Treats files as raw byte streams while guarding against terminal control injection.

The Defensive Mirror

For every offensive discovery action, there is a corresponding defensive control:

  • Adversary queries process identity $\rightarrow$ Defender monitors suspicious account enumeration via auditd or EDR.
  • Adversary enumerates directory entries $\rightarrow$ Defender enforces strict DAC modes and restricts directory traverse bits.
  • Adversary hunts for credentials $\rightarrow$ Defender implements automated secrets management (HashiCorp Vault, AWS Secrets Manager) and deploys honeytoken tripwires.

The Quiet Trap

A quiet trap is an operational failure mode that executes without generating an error message, leading the analyst to incorrect conclusions.

$ cat notes.txt | grep 'rotate'
todo: rotate keys
Enter fullscreen mode Exit fullscreen mode

The command appears to succeed. However, because notes.txt originated from a Windows environment, it contains carriage returns (\r). If we extract the token into an environment variable:

$ TOKEN=$(cat notes.txt | head -n 1 | awk '{print $2}')
$ curl -H "Authorization: Bearer $TOKEN" https://api.internal/auth
Enter fullscreen mode Exit fullscreen mode

The HTTP request fails or corrupts the header because the carriage return is treated as a header termination delimiter.

The Rule of Thumb

Whenever inspecting text files on an unknown system, always verify line endings using file or cat -A. If CRLF terminators are detected, sanitize the file using dos2unix or tr -d '\r' before passing values to downstream tools.


Why These Concepts Matter

  • Rooted Simplicity: Understanding that directories are simple tables mapping names to inodes demystifies filesystem navigation.
  • Security Boundaries: Recognizing that the kernel respects numeric UIDs rather than shell variables prevents reliance on spoofable user-space data.
  • Discretionary Vulnerabilities: Discretionary access control places the burden of protection on individual users, making configuration drift and credential exposure inevitable in large environments.
  • Detection Engineering: Understanding that enumeration produces a distinct telemetry trail enables defenders to build high-fidelity behavioral detection rules.

Key Takeaways

  1. Orientation First: Never run automated scripts before manually confirming identity (whoami) and location (pwd).
  2. Always Use ls -la: Default directory listings conceal dot-files where sensitive configuration and credentials reside.
  3. Check Directory Execute Bits: Reading a directory requires r, but accessing files inside it requires x.
  4. Identify Before Reading: Use file and cat -A to avoid terminal corruption and detect hidden carriage return traps.
  5. Credentials in Files Are Real: MITRE ATT&CK technique T1552.001 remains a primary initial compromise vector in real-world breaches.

The BreachLab Journey Continues

Level 0 establishes the orientation baseline. In subsequent levels of the Ghost track, the challenges become progressively more constrained:

  • Level 1 introduces unusual filename syntax (spaces, special characters, leading hyphens) that breaks naive shell command lines.
  • Subsequent levels introduce restricted shells, custom binaries, network listener inspection, and cron automation.

The orientation loop mastered here—identifying identity, location, and readable surface—remains identical across every level of the wargame and every enterprise network engagement.


Follow along with the complete playlist

https://www.youtube.com/playlist?list=PLUep6spDxjvo

Platform

BreachLab is an independent platform dedicated to hands-on cybersecurity education. If content built on its tracks earns revenue, consider supporting the platform via Liberapay to keep it free and accessible for everyone.

GitHub Repository

Follow along with the source code and production pipeline tools in the official repository:
https://github.com/Someone-anon-coder

Follow the Complete Series

Access every written guide and theoretical deep dive in the official Medium publication series:
https://computer-info-1.medium.com/list/breachlab-ghost-i-24dad052016f

Explore My Other Learning Series

Sources

  1. Ritchie, D. M., & Thompson, K. (1974). The UNIX Time-Sharing System. Communications of the ACM, 17(7), 365–375. https://www.nokia.com/bell-labs/about/dennis-m-ritchie/manintro.html
  2. Filesystem Hierarchy Standard Group. (2015). Filesystem Hierarchy Standard (FHS 3.0). Linux Foundation. https://refspecs.linuxfoundation.org/fhs
  3. Ylönen, T., & Lonvick, C. (2006). The Secure Shell (SSH) Protocol Architecture (RFC 4251). Internet Engineering Task Force. https://www.rfc-editor.org/rfc/rfc4251
  4. Saltzer, J. H., & Schroeder, M. D. (1975). The Protection of Information in Computer Systems. Proceedings of the IEEE, 63(9), 1278–1308. https://www.cs.virginia.edu/~evans/cs551/saltzer/
  5. Lampson, B. W. (1974). Protection. ACM Operating Systems Review, 8(1), 18–24. https://bwlampson.site/08-Protection/WebPage.html
  6. Morris, R., & Thompson, K. (1979). Password Security: A Case History. Communications of the ACM, 22(11), 594–597. https://www.passwordresearch.com/papers/paper41.html
  7. Scarfone, K., Souppaya, M., Cody, A., & Orebaugh, A. (2008). Technical Guide to Information Security Testing and Assessment (NIST SP 800-115). National Institute of Standards and Technology. https://csrc.nist.gov/pubs/sp/800/115/final
  8. Hutchins, E. M., Cloppert, M. J., & Amin, R. M. (2011). Intelligence-Driven Computer Network Defense Informed by Analysis of Adversary Campaigns and Intrusion Kill Chains. Lockheed Martin Corporation. https://www.lockheedmartin.com/en-us/capabilities/cyber/cyber-kill-chain.html
  9. MITRE Corporation. (2015). Discovery (TA0007) — Enterprise Matrix. MITRE ATT&CK. https://attack.mitre.org/tactics/TA0007/
  10. MITRE Corporation. (2006). CWE-798: Use of Hard-coded Credentials. Common Weakness Enumeration. https://cwe.mitre.org/data/definitions/798.html
  11. CyberArk Labs. (2022). Unpacking the Uber Breach: Technical Threat Analysis. CyberArk Software. https://www.cyberark.com/resources/threat-research/unpacking-the-uber-breach

This article was prepared with AI assistance. The companion video's narration is synthesized speech and the presenter is an animated illustration, not a real person. This guide teaches methodology and intentionally does not reveal wargame solutions or passwords.

What's Next?

In the next installment, we tackle Level 1: Name Game. We confront filenames containing whitespace, special escape sequences, and leading dashes, exploring how the shell's argument parsing treats options and filenames, and how operators manipulate files that seem impossible to open.

Happy hacking!

Tags: Cybersecurity, Linux, Ethical Hacking, Beginners, Computer Science

Top comments (0)