권한상승 분석: 실행 주체와 쓰기 권한이 만나는 지점
로컬 권한상승 전체가 아니라 강의에서 다룬 구성·권한 경계 패턴을 파일 권한, sudo·cron, 파일 ACL·서비스 DACL, Unquoted Service Path로 나눠 정리한다.
목차 5
2026-08-09 업데이트 — 로컬 권한상승 전체를 파일 쓰기 문제로 일반화한 설명을 바로잡고, 이 글의 범위를 구성·권한 기반 패턴으로 한정했다. Windows 파일 ACL과 서비스 객체 DACL, Unquoted Service Path가 실제로 실행되는 조건도 구분했다.
권한상승은 무엇을 찾는 일인가
로컬 권한상승(Local Privilege Escalation, LPE)은 시스템 안의 낮은 권한 주체가 더 높은 권한을 얻는 흐름이다. MITRE ATT&CK의 Privilege Escalation 전술은 구성 오류뿐 아니라 소프트웨어·서비스·커널 취약점 악용과 계정·토큰 조작까지 여러 경로를 포함한다. 따라서 높은 권한 파일에 대한 쓰기 권한은 LPE 전체의 필요조건이 아니다.
공통 질문은 낮은 권한 사용자의 입력이 의도한 경계를 넘어 높은 권한의 실행 문맥에 영향을 줄 수 있는가다. 영향 경로에는 파일·디렉터리 쓰기뿐 아니라 허용된 명령의 인자, PATH와 환경변수, 액세스 토큰, 프로그램과 커널의 취약점이 들어간다. Access Token Manipulation과 Exploitation for Privilege Escalation은 뒤의 두 경로를 보여 주는 별도 기법이다.
이 글은 그중 강의에서 다룬 구성·권한 경계만 좁혀 본다. 이 범위에서는 실행 주체와 낮은 권한 사용자가 통제할 수 있는 파일·경로·인자가 만나는 곳을 찾는다. 예를 들어 서비스가 SYSTEM으로 돌아도 일반 사용자가 실행 파일이나 검색 경로에 쓸 수 없고 실행 정의에도 영향을 줄 수 없다면, 적어도 이 파일·경로 하이재킹 조건만으로 곧바로 권한상승이 되지는 않는다.
리눅스 파일 권한 읽는 법
리눅스에서는 이 ’쓸 수 있는가’가 파일 권한으로 드러난다. 권한은 읽기, 쓰기, 실행을 소유자·그룹·기타 사용자 순으로 표시한다.
-rwxr-xr--위는 소유자가 읽기·쓰기·실행, 그룹이 읽기·실행, 기타 사용자가 읽기만 가능한 상태다. 프롬프트의 $는 보통 일반 사용자, #는 root 권한을 뜻한다.
chmod로 권한을 바꾸고 chown으로 소유자를 바꾼다.
chmod 700 script.sh
chmod +x script.sh
chown root:root script.shroot가 실행하는 스크립트는 root 소유로 두고 일반 사용자가 수정하지 못하게 해야 한다. 반대로 다른 사용자가 수정 가능한 실행 파일이나 스크립트는 그 자체로 권한상승 단서가 된다.
리눅스에서 권한이 오르는 지점
이 글이 다루는 리눅스 구성·권한 점검은 다음 순서로 좁혀 본다.
- 현재 사용자와 그룹을 확인한다.
- sudo 권한과
NOPASSWD설정을 확인한다. - cron, systemd timer 같은 자동 실행 작업을 확인한다.
- writable 파일과 디렉터리를 확인한다.
- SUID 파일과 권한 오설정을 확인한다.
- 환경변수, PATH, 실행 스크립트의 상대경로 사용 여부를 확인한다.
sudo -l로 현재 사용자가 root로 돌릴 수 있는 명령을 본다. NOPASSWD로 특정 명령을 root 권한 실행할 수 있으면 점검 대상이다.
sudo -l
id
env
find / -writable -type f 2>/dev/null두 종류의 오설정이 자주 나온다. 하나는 root cron이 일반 사용자가 수정 가능한 스크립트를 실행하는 경우다.
root의 cron이 /tmp/backup.sh 실행
/tmp/backup.sh를 일반 사용자가 수정 가능스크립트 내용을 바꿔 두면 다음 실행 때 root 권한으로 그 내용이 돈다. 다른 하나는 sudo로 허용한 명령의 인자를 제한하지 않은 경우다. rsync를 제한 없이 허용하면 경로와 인자를 조작해 의도보다 넓은 파일에 접근하거나 덮어쓸 수 있다.
# 위험
user ALL=(root) NOPASSWD: /usr/bin/rsync
# 더 안전
user ALL=(root) NOPASSWD: /usr/bin/rsync -av /safe/source/ /safe/dest/이 단서들을 찾는 find, grep 같은 기본 명령은 다른 글에 정리해 두었다(셸에서 반복하는 침투테스트 기본 명령어).
Windows에서는 파일 ACL과 서비스 DACL을 나눠 본다
Windows에서는 ’누가 무엇을 할 수 있는가’가 보안 설명자의 ACL(Access Control List)로 정의된다. 다만 권한 이름과 의미는 객체마다 다르다. 파일·디렉터리에서는 Read, Write, Modify, Execute 같은 파일 권한을 보고, 서비스 객체에서는 SERVICE_QUERY_CONFIG, SERVICE_CHANGE_CONFIG, SERVICE_START, SERVICE_STOP, WRITE_DAC 같은 서비스 전용·표준 권한을 본다.
구성형 권한상승 경로도 둘로 나뉜다. 첫째, SYSTEM 서비스의 실행 파일이나 검색 후보가 놓일 중간 디렉터리에 일반 사용자 쓰기 권한이 있으면 파일 교체나 경로 하이재킹 가능성을 확인한다. 둘째, 서비스 객체 DACL이 일반 사용자에게 SERVICE_CHANGE_CONFIG를 허용하면 현재 실행 파일을 수정하지 않아도 서비스의 실행 경로(ImagePath)를 사용자가 통제하는 프로그램으로 바꿀 수 있다. Microsoft의 Service Security and Access Rights는 이 권한이 서비스가 실행할 파일을 바꿀 수 있으므로 관리자에게만 부여해야 한다고 설명한다. WRITE_DAC처럼 서비스 DACL 자체를 바꿀 수 있는 권한도 함께 확인한다.
Windows LPE에서 점검하는 항목은 다음과 같다.
- 현재 사용자와 그룹 권한
- 서비스 객체 DACL의
SERVICE_CHANGE_CONFIG·WRITE_DAC·시작/중지 권한 - 서비스 실행 계정과 실행 경로
- 서비스 바이너리·디렉터리의 쓰기 권한
- ACL 오설정
- Unquoted Service Path
- 관리자 권한으로 실행되는 스케줄 작업
- 저장된 자격 증명
여기서도 높은 권한의 실행 문맥과 낮은 권한 사용자가 통제할 수 있는 입력이 함께 있어야 한다. 서비스가 SYSTEM으로 실행되더라도 일반 사용자가 실행 파일·검색 경로·서비스 실행 정의 중 어느 것도 바꿀 수 없다면, 적어도 이 구성·권한 패턴만으로 곧바로 상승으로 이어지지 않는다.
Unquoted Service Path
ACL 오설정이 구체적인 패턴으로 나타나는 예가 Unquoted Service Path다. Windows 서비스 실행 경로에 공백이 있는데 따옴표로 감싸지 않으면 발생한다.
C:\Program Files\Some App\service.exe따옴표가 없으면 Windows가 경로를 공백 단위로 끊어 앞에서부터 해석을 시도한다. Microsoft의 CreateProcessW 문서도 실행 파일 이름이 모호해질 수 있는 경로와 보안 위험을 설명한다.
C:\Program.exe
C:\Program Files\Some.exe
C:\Program Files\Some App\service.exe공격자가 C:\Program.exe처럼 중간에 걸리는 위치에 실행 파일을 만들 수 있고, 그 서비스가 높은 권한으로 다음에 시작될 때 의도한 실행 파일보다 먼저 선택되면 권한상승으로 이어질 수 있다. 성립하려면 다음 조건이 맞아야 한다.
- 서비스 실행 경로에 공백이 있다.
- 실행 경로가 따옴표로 감싸져 있지 않다.
- 중간 경로 중 하나에 일반 사용자가 쓰기 권한을 가진다.
- 서비스가 관리자나 SYSTEM 같은 높은 권한으로 실행된다.
- 파일을 심은 뒤 부팅, 운영자의 재시작, 트리거 시작 등 서비스가 다시 시작되는 계기가 있다.
마지막 계기가 반드시 공격자의 서비스 제어 권한일 필요는 없다. 자동 시작 서비스가 다음 부팅에 실행될 수도 있다. 다만 공격자가 직접 시작·중지하려면 서비스 DACL의 SERVICE_START·SERVICE_STOP 같은 권한이 별도로 필요하다. Microsoft의 StartService 문서도 서비스 시작에 SERVICE_START 권한이 필요하다고 명시한다.
이 글에서 다룬 구성·권한 패턴의 방어는 한 방향으로 모인다. 높은 권한으로 실행되는 대상의 실행 파일과 상위 디렉터리에서 일반 사용자 쓰기 권한을 없애고, sudo·서비스 경로 같은 실행 정의를 최소 권한으로 제한하며, 서비스 객체 DACL에서 구성 변경과 제어 권한을 관리자에게만 둔다. Windows 서비스 경로는 항상 따옴표로 감싼다. 소프트웨어·커널 취약점에는 패치와 완화책이, 토큰·자격 증명 경로에는 별도의 자격 증명 보호와 권한 관리가 필요하다.
여기까지는 강의로 정리한 구성·권한 패턴과 성립 조건이고, 직접 취약한 서비스를 만들어 실행 파일을 심고 SYSTEM 셸을 얻는 것까지 돌려 본 것은 Unquoted Service Path 한 종류뿐이다. cron·sudo·SUID 계열의 리눅스 권한상승은 아직 실습 환경에서 재현해 보지 않았다. 토큰 조작과 소프트웨어·커널 취약점 악용은 개념의 경계를 확인하는 데만 참고했고 이 글에서 실습하거나 분석하지 않았다.
Unquoted Service Path 결과는 당시 일회성 로컬 실습에 대한 기록이다. 현재 블로그 저장소와 도달 가능한 Git 이력에는 취약 서비스 설정, 실행 파일, 명령 출력이나 하네스가 남아 있지 않아 독립적으로 재현하거나 결과를 다시 검토할 수 없다. Windows 버전과 정확한 ImagePath·ACL·서비스 시작 조건도 보존되지 않았고, 2026-08-09 정정 때 다시 실행하지 않았다. 따라서 SYSTEM 셸을 얻었다는 문장은 현재 재현 가능한 성과가 아니라 당시 관찰 범위로만 읽는다.