So far we've exploited the application (04-02) and the network (04-03). In this lesson we drop down to the host level: how a flaw in the operating system or in a local service turns into code execution on the machine, up to obtaining an initial shell, a foothold with limited privileges. At TechNova this applies to the internal Linux server, to dev, and to the workstations on the 10.10.10.0/24 network, where Module 3 found outdated software and end-of-life services.

The framing holds firm and, with systems, has an important technical nuance: system exploits are the most prone to crashing the service (an overflow with a miscalculated offset restarts the process or the host). That's why everything happens in TechNova's authorized lab, with a prior check when one exists, high-reliability exploits, the lowest-impact payload, and damage control (no unagreed denial of service). And the module's limit, again: here we reach the foothold. What's done from that foothold, escalating to root/administrator, persisting, pivoting, is Module 5. We teach the mechanism of each class and its counterpart (patching, hardening); not a turnkey operational 0-day exploit.

Contents

  1. From the network service to host execution
  2. RCE via a vulnerable service
  3. Buffer overflow: the concept
  4. Memory protections: ASLR, DEP, canaries
  5. Misconfigured local services and settings
  6. Obtaining the initial shell (foothold)
  7. Counterpart: patching and hardening
  8. Common mistakes and tips
  9. Exercises
  10. Conclusion

  1. From the network service to host execution

An RCE (Remote Code Execution) is the holy grail of system exploitation: getting the target machine to run our code. The most common paths:

  • Service with an execution vulnerability: a flaw in the service's code allows running commands (like the Werkzeug console from 04-03).
  • Memory corruption: a buffer overflow or another memory flaw that lets you divert the execution flow.
  • Abusable local configuration: binaries, permissions, or services that are misconfigured and grant execution.
flowchart LR
    A[Vulnerable<br/>service/OS] --> B[Code execution<br/>- RCE]
    B --> C[Initial shell<br/>foothold]
    C -. Module 5 .-> D[Privilege<br/>escalation]

The goal of this lesson is to reach C: the initial shell. The dotted arrow to D is Module 5.

  1. RCE via a vulnerable service

The cleanest path is a service with a known RCE and a reliable module. The pattern (already seen in 04-03) is always the same: verify, check, minimal payload, evidence.

# Conceptual example in the lab: vulnerable service on an internal host
msf6 > use exploit/linux/http/<service_module>
msf6 > set RHOSTS 10.10.10.60
msf6 > check                       # confirm the vulnerability WITHOUT exploiting
[+] The target appears to be vulnerable.
msf6 > set PAYLOAD cmd/unix/generic
msf6 > set CMD "id; hostname"      # minimal test that proves execution
msf6 > run
uid=33(www-data) gid=33(www-data)
srv-web-interno

The output uid=33(www-data) proves command execution as an unprivileged user: we already have a foothold. We don't open a persistent shell or touch data: id; hostname is enough proof for the report.

Counterpart: patch the service, retire it if it's end-of-life, run it with least privilege (the fact that www-data can't do much is precisely what limits the impact), and isolate it by network.

  1. Buffer overflow: the concept

The buffer overflow is the most classic class of memory corruption. We explain it at a conceptual/educational level: what it is and why it happens. We're not going to write an operational exploit.

Mechanism. A program reserves a fixed space (a buffer) for some data. If it copies more data than fits into it without checking the size, the excess bytes overwrite adjacent memory, including, on the stack, the function's return address. By controlling that address, an attacker can divert execution toward their own code.

// VULNERABLE: copies without checking the destination size
void greet(char *input) {
    char name[64];        // 64-byte buffer on the stack
    strcpy(name, input);  // if 'input' > 64 bytes -> overflow
    printf("Hello %s\n", name);
}

If input is 100 bytes, strcpy writes past name[64] and clobbers whatever is behind it on the stack. Stack diagram:

flowchart TB
    subgraph Stack["Stack (before / after the overflow)"]
        A["name buffer 64B"]
        B["other variables"]
        C["return address"]
    end
    A -->|the excess overflows downward| B
    B --> C

By overwriting the return address, when the function ends, instead of returning where it should, it jumps wherever the attacker wants. That's the heart of the exploit. The pentester's discipline here: recognize the class, understand why the code is vulnerable, and, crucially, know that testing this can crash the process, so it's done only in the lab and with agreement.

Secure code (mitigation in the code itself):

// SECURE: limit the copy to the destination size
void greet(char *input) {
    char name[64];
    strncpy(name, input, sizeof(name) - 1);  // never more than 63 bytes
    name[sizeof(name) - 1] = '\0';           // null-terminate the string
    printf("Hello %s\n", name);
}

Using functions that respect the size (strncpy, snprintf) instead of the unsafe ones (strcpy, gets, sprintf) eliminates the class at the root. In memory-managed languages (Python, Java, Rust) this family of flaws practically disappears.

  1. Memory protections: ASLR, DEP, canaries

Modern operating systems add defense in depth that makes an overflow far harder to exploit (which is why a "lab" exploit often doesn't work against an up-to-date system):

Protection What it does Effect on the attacker
Stack canary Places a sentinel value before the return address; if it changes, it aborts Detects the overflow before the jump
DEP / NX Marks the stack as non-executable Code injected onto the stack won't run
ASLR Randomizes memory addresses on each run The attacker doesn't know where to jump
PIE Also randomizes the executable's own base Reinforces ASLR

These protections don't remove the flaw, but they raise the cost of exploiting it enormously. For the report, this matters: an overflow in a binary without these protections is far more serious than the same flaw in one that has them all. They're checked with tools like checksec.

  1. Misconfigured local services and settings

Not all RCE comes from memory corruption; often the path is a local misconfiguration of the system itself:

Insecure configuration Risk Counterpart
End-of-life service (PHP 7.2, MySQL 5.5 from the inventory) Known unpatched CVEs Update / retire EOL
Default credentials on a service Direct access Change credentials (see 04-05)
Excessive file permissions, misset SUID Path to more access Review permissions, least privilege
Unnecessary exposed services More attack surface Disable what isn't used

At TechNova, the PHP 7.2.24 out of support and the MySQL 5.5.62 from the inventory are clear examples: unmaintained software with accumulated CVEs. The most reliable entry path is usually this, configuration and obsolescence, rather than a custom overflow.

  1. Obtaining the initial shell (foothold)

The result of this lesson is the initial shell: a console on the host with the privileges of the exploited service (usually limited: www-data, devapp, a service account). Recapping the controlled flow:

flowchart LR
    A[Vulnerable<br/>service/OS] --> B[check / verify]
    B --> C[minimal payload<br/>id, hostname]
    C --> D[initial shell<br/>limited privileges]
    D --> E[capture evidence<br/>and STOP here]

Once you have the shell, you stabilize it just enough to work and you capture the evidence (user, host, proof of execution). And here we stop: what to do with that foothold, enumerating the system from the inside, escalating privileges, maintaining access, pivoting, is all Module 5. Jumping ahead would break the control and the course's thread.

  1. Counterpart: patching and hardening

Against system exploitation, the defense rests on:

  • Patch management: 90% of this lesson evaporates with up-to-date systems and no EOL software. It's the number-one countermeasure.
  • OS hardening: keep ASLR, DEP, PIE, and canaries active; disable unnecessary services; review permissions and SUID; apply CIS Benchmarks.
  • Least privilege: having services run with the lowest possible privilege limits the value of a foothold.
  • Detection: EDR/antivirus, process and log monitoring, alerts on unexpected shells or anomalous binaries. An unusual outbound reverse shell is a clear signal for the defender.

  1. Common Mistakes and Tips

  • Launching memory exploits without check or high reliability. They're the ones that most often crash the service; a crash in production is an unagreed denial of service. Verify and prioritize a high Rank.
  • Trying to write your own buffer overflow against the client. It's not the objective (or the scope) of a standard pentest; recognize the class, report it, and validate with a safe PoC or with check.
  • Ignoring memory protections in the report. A flaw in a binary without ASLR/DEP/canary is far more serious; document the real state with checksec.
  • Pressing on after the shell. The foothold is the end of Module 4. Enumerating and escalating from the inside is Module 5; doing it here breaks the control.
  • Focusing only on flashy CVEs and forgetting configuration. EOL software, default credentials, and excessive permissions are usually the real, most reliable path.
  • Not stabilizing or documenting the shell. A shell lost for not stabilizing it, or without captured evidence, is wasted work.
  • Tip: before a risky memory exploit, look for the boring, reliable path (EOL service, default credential, misconfiguration). It usually exists and is far lower impact.

  1. Exercises

Exercise 1. Explain in your own words, at a conceptual level, why the greet function with strcpy is vulnerable to buffer overflow, what gets overwritten, and why that can grant control of execution. Write the secure version and state which OS protections would hamper the attack even if the code remained vulnerable.

Exercise 2. You're going to validate an RCE on an internal TechNova service (10.10.10.60) with a Metasploit module. Describe the low-impact sequence you would follow to prove execution without crashing the service or going out of scope, and what evidence you would capture. State where this lesson ends and what would already be Module 5.

Exercise 3. The Module 3 inventory lists PHP 7.2.24 and MySQL 5.5.62 (both EOL) at TechNova. Argue why this "boring path" of obsolete software may be preferable, for the pentester, to attempting a custom buffer overflow, and give the remediation counterpart.

Solutions

Solution 1. strcpy(name, input) copies input into name[64] without checking the size; if input exceeds 64 bytes, the excess bytes write past the buffer and overwrite the adjacent memory on the stack, including the function's return address. When greet ends, the CPU jumps to that address: if the attacker has controlled it, they divert execution toward their code. Secure version: use strncpy(name, input, sizeof(name)-1) and null-terminate with '\0', so that nothing is ever written outside the buffer. OS protections that would hamper the attack even if the code were vulnerable: stack canary (detects the overwrite before the jump), DEP/NX (the stack isn't executable, injected shellcode doesn't run), and ASLR/PIE (they randomize addresses, the attacker doesn't know where to jump).

Solution 2. Low-impact sequence: (1) confirm that 10.10.10.60 is in scope and within the window; (2) use the module and read what it does; (3) check to confirm the vulnerability without exploiting; (4) choose the minimal payload (cmd/unix/generic) with set CMD "id; hostname" instead of a persistent shell; (5) run and capture the output (uid=..., hostname) as evidence of execution. This lesson ends at the initial shell/execution (the foothold with limited privileges). Enumerating the system from the inside, escalating to root, maintaining access, or pivoting to other subnets is Module 5.

Solution 3. EOL software is preferable because it's a reliable, low-impact path: it has known CVEs with proven exploits and modules with check, it doesn't depend on calculating offsets or bypassing ASLR/DEP, and therefore it's far less prone to crashing the service than a custom overflow (which can restart the process if something doesn't fit). In pentesting you prefer the safe, demonstrable entry over the risky one. Remediation counterpart: update to supported versions of PHP and MySQL (or migrate), retire all end-of-life software, and in the meantime isolate and monitor those services. Patch management is the main countermeasure.

Conclusion

We close the technical block of exploitation by layers: application (04-02), network (04-03), and now system (04-04). We've seen how code execution on a host is reached, via a service with RCE, via memory corruption (with the buffer overflow explained at a conceptual level and its ASLR/DEP/canary protections), or via insecure local configuration, up to obtaining the initial shell: a foothold with limited privileges, validated with an id, documented, and going no further. The counterpart has been constant: patch, harden, and apply least privilege.

We're left with one cross-cutting access path that runs through the web, the network, and the systems: credentials. Many of the most reliable footholds don't come from an exploit but from a weak, default, or reused password. The module's final lesson, 04-05 Password and Authentication Attacks, tackles how authentication, hashing, offline/online attacks, and session and MFA mechanisms are evaluated, always with their defensive counterpart. And with it we'll close Module 4 to make way for post-exploitation.

© Copyright 2026. All rights reserved