보안정보
전문화된 보안 관련 자료, 보안 트렌드를 엿볼 수 있는
차세대 통합보안관리 기업 이글루코퍼레이션 보안정보입니다.
Sudo 취약점 분석 및 대응방안 part.2
2021.06.02
14,196
01. 개요
No |
CVE |
Description |
1 |
CVE-2015-5602 |
sudoeit에 입력하는 파일 경로에 와일드카드 문자(*)를 사용하여 상위 권한의 파일을 수정할 수 있는 취약점 |
2 |
CVE-2016-7076 |
wordexp 함수에 특정 인자를 사용하는 응용 프로그램을 실행하여 noexec 제한 옵션이 존재하는 sudo를 우회하여 상위 권한을 획득하는 취약점 |
3 |
CVE-2017-1000367 |
SELinux 모듈이 활성화된 시스템에서 유효성 검증 미흡으로 제한된 권한의 sudoer가 완전한 root 권한을 취득할 수 있는 취약점 |
4 |
CVE-2019-14287 |
-u 옵션의 입력값 검증이 미흡한 취약점을 이용하여 명령어를 실행해 상위 권한을 획득하는 취약점 |
5 |
CVE-2019-18634 |
pwfeedback 옵션이 활성화된 sudo 프로세스에서 비밀번호 입력값에 오버 플로우를 일으켜 상위 권한을 취득할 수 있는 취약점 |
6 |
CVE-2021-3156 |
sudo에 백슬래시 문자에 대한 버퍼 오버플로우가 존재하여 이를 이용해 root 권한을 획득할 수 있는 취약점 |
구분 |
취약한 버전 |
위험도 |
CVE-2021-3156 |
sudo 1.8.2 ~ 1.8.31p2 |
High |
sudo 1.9.0 ~ 1.9.5p1 |
플래그 |
MODE_SHELL |
MODE_RUN |
MODE_CHECK |
MODE_EDIT |
옵션 |
s |
- |
l |
e |
03. sudo 소스코드 분석
[그림 2]는 sudo 1.8.31 버전의 소스코드 sudoers.c 파일 내 힙 오버플로우 취약점이 존재하는 set_cmnd() 함수의 내용이다. CVE-2021-3156의 공격 흐름도인 [그림4-1]에서 Section3에 해당하는 루틴으로 힙 오버플로우가 발생되는 상세한 과정은 다음과 같다.
Step1 : line 866의 백슬래시() 이스케이프를 해제하는 로직에 접근하게 될 때 from 포인터 변수가 가르키는 백슬래시()문자열 뒤에는 NULL 문자열이 위치하게 된다.
Step2 : line 867에서 이스케이프를 진행하기 위해 from 변수를 증감하여 백슬래시() 문자열 뒤에 존재하는 NULL 문자열을 가르키게 되고 line 868에서 from 변수가 한번 더 증감되면서 NULL 문자열 뒤의 임의의 값을 읽게 된다.
Step3 : line 867과 line 868 로직에 의해 증감 연산을 총 두 번 진행하게 되어 NULL 문자열을 건너뛰게 됨으로써 라인 865의 while 문 조건식(from 변수가 NULL 값이 아닐 때까지 실행)을 무시하게 된다. 따라서 line 853에서 계산한 힙 메모리의 크기를 벗어나 임의의 값을 계속 입력할 수 있게 되어 힙 오버플로우 취약점이 발생하게 된다.
[그림 2] set_cmnd() 함수 내 힙 오버플로우 취약점이 존재하는 루틴
[그림 3]의 소스코드는 [그림 5-1]의 Section2에 해당 하는 루틴이며, 해당 루틴들은 sudoers.c 파일 내 set_cmnd() 함수에 존재한다. 취약한 코드에 진입하기 위해서는 2개의 조건식을 만족해야 하는데, MODE_RUN(기본 실행 플래그), MODE_EDIT(-e), MODE_CHECK(-l) 플래그 중 1개의 플래그가 설정되어야 하며, MODE_SHELL(-s), MODE_LOGIN_SHELL 플래그가 설정되어야 한다.
[그림 3] 취약점이 존재하는 루틴에 진입하기 위한 조건들
그러나 sudo 명령으로는 [그림 3] 에서 체크하는 플래그(옵션)들을 동시에 설정할 수 없도록 되어있기 때문에 일반적인 sudo 명령을 활용한 취약점 공격은 불가능하다.
[그림 4]는 parge_args.c 파일 내 parse_args() 함수의 일부 내용으로, sudo 명령 실행 시 적용한 옵션에 따라 플래그를 설정하는 루틴이다. 취약점이 존재하는 루틴에 진입하기 위해 MODE_EDIT(-e) 혹은 MODE_CHECK(-l) 플래그와 MODE_SHELL(-s) 플래그를 동시에 적용하여 실행할 경우 line 532의 조건식에 의해 에러메시지가 출력되며 프로그램이 종료되게 된다.
[그림 4] –e, -l 옵션과 –s 옵션의 동시 적용을 방지하는 루틴
MODE_RUN(기본 실행 플래그) 플래그와 MODE_SHELL(-s) 플래그가 동시에 설정되는 경우에도 parge_args.c 파일 내 parse_args() 함수의 line 571 조건식에 의해 line 588의 이스케이프 루틴에서 백슬래시() 문자열이 이스케이프 되면서, 취약점이 존재하는 백슬래시() 이스케이프 루틴으로의 진입이 불가능하다.
[그림 5] MODE_RUN 플래그와 MODE_SHELL 플래그 적용 시 백슬래시() 문자열을 이스케이프 하는 루틴
그러나 sudo의 심볼릭 링크 파일인 sudoedit 명령어로 sudo를 실행시킬 경우 기본으로 MODE_SHELL(-s) 플래그와 MODE_EDIT(-e) 플래그가 설정되므로, [그림 3] 의 조건을 만족하여 취약점이 존재하는 루틴으로 진입할 수 있다. 따라서 sudo 명령어 대신 sudoedit 명령어로 “sudoedit –s ‘’ '임의의 문자열’“ 과 같은 페이로드를 활용한 힙 오버플로우 취약점 공격이 가능하게 된다.
[그림 6] sudoedit 명령어로 sudo 실행 시 설정되는 플래그
04. PoC 분석 및 공격 시연
exploit 코드에서는 -source 옵션으로 대상 일반유저의 uid 와 gid의 값을 0 으로 수정한 passwd 파일을 파라미터로 전달받으며, 해당 passwd 파일의 내용을 / etc /passwd 파일에 덮어써서 최종적으로 root권한을 획득하게 된다.
[그림 7] 조작된 passwd 파일이 공격에 활용되는 과정
exploit 코드 내에서 공격을 위한 절차는 아래와 같이 진행된다.
Step1 : –source 옵션으로 조작된 passwd 파일을 받은 후 해당 파일의 내용을 환경변수에 저장한다.
Step2 : 레이스 컨디션 공격에 활용될 디렉터리를 생성 후 해당 디렉터리의 심볼릭 링크를 생성한다.
Step3 : –A –s 옵션과 백슬래시() 문자열 뒤에 힙 메모리 인덱스를 맞추기 위한 문자열들을 파라미터로 설정 후 sudoedit을 실행한다. 이때 환경변수에 저장된 조작된 passwd 파일의 내용은 sudo의 스택 메모리에 들어가게 된다.
위와 같은 과정은 레이스 컨디션 공격에 성공할 때까지 최대 5000번 반복 실행되게 된다.
[그림 8] 조작된 exploit-db 에 공개된 CVE-2021-3156의 exploit 코드
exploit 코드 실행 시 실제로 sudoedit 에 전달되는 페이로드는 아래와 같다.
[그림 9] exploit 코드 실행 시 sudoedit 에 전달되는 페이로드
레이스 컨디션 공격 진행 시 아래와 같이 무작위로 작업 디렉터리가 생성된다.
[그림 10] exploit 코드 실행 시 무작위로 생성되는 디렉터리
레이스 컨디션 공격 성공 시 timestamp.c 파일 timestamp_lock() 함수 내 라인 657에 의해 –source 옵션으로 전달받아 스택에 저장되어있는 passwd 파일의 내용이 / etc /passwd 파일에 덮어 쓰여지게 되면서 공격에 성공하게 된다.
[그림 11] sudo의 스택 메모리 영역에 저장된 조작된 passwd 파일
[그림 12] 조작된 passwd 파일을 / etc /passwd 파일에 덮어쓰는 루틴
2) 공격 시연
공격 시연 환경은 exploit 코드 개발자가 테스트 한 OS 의 버전과 sudo 버전을 동일하게 구성하여 진행하였다.
구분 |
버전 |
sudo |
1.8.31 |
OS |
Ubuntu 20.04.1 |
root 권한을 획득할 대상 일반유저의 uid 값을 확인한다. 현재 1000으로 설정되어 있는 것이 확인된다.
[그림 13] 대상 일반유저의 uid 값
/ etc /passwd 파일을 fake_passwd 라는 이름으로 복사한 후, fake_passwd 파일 내에서 test 유저의 uid와 gid를 모두 0 으로 수정한다.
[그림 14] 파라미터로 전달할 조작된 passwd 파일
[그림 15] 대상 유저의 uid, gid 를 0 으로 조작한 passwd 파일의 내용
https://www.exploit-db.com/exploits/49521 에서 CVE-2021-3156 python exploit code를 다운로드 받은 후 [그림 15] 에서 수정한 fake_passwd 파일을 –source 옵션으로 전달하여 python 3.X 대 버전으로 실행시킨다.
“success at iteration …” 메시지 발생 후 기존 test 유저로 다시 로그인 한다. 유저이름과 uid 가 각각 root 와 0 으로 변경된 것이 확인된다.
[그림 17] exploit 성공 시 발생하는 메시지
[그림 18] exploit 성공 후 uid 가 0 으로 변경되면서 root 권한이 획득된 화면
/ etc /passwd 파일에서 test 유저의 uid가 0으로 변경된 것이 확인된다.
[그림 19] 조작된 passwd 파일의 내용으로 변경된 / etc /passwd 파일의 내용
05. 대응방안
1) systemtap 스크립트 활용
systemtap 스크립트를 활용하여 sudoedit 명령어의 실행을 차단할 수 있다. 해당 스크립트를 실행하면 sudoedit 명령은 사용 불가능하게 되고, 기존 sudoedit의 기능은 sudo –e 명령어로 대체가 가능하다. 단, 시스템 재부팅 시 스크립트를 다시 실행해야 하는 번거로움이 존재한다.
Step1 : 필요한 systemtap 패키지 및 종속성을 설치한다.
[그림 20] systemtap 패키지 및 종속성 설치
RedHat7 혹은 RetHat6,8 에서는 debuginfo 패키지를 추가로 설치해야 한다.
[그림 21] Redhat 7 계열에서의 debuginfo 패키지 설치
[그림 22] Redhat 6, 8 계열에서의 debuginfo 패키지 설치
Step2 : 파일명을 sudoedit-block.stap 로 지정하여 systemtap 스크립트를 제작한다.
[그림 23] sudoedit-block.stap 파일 내 systemtap 스크립트 내용
Step3 : 제작한 systemtap 스크립트 백그라운드로 실행시킨다.
[그림 24] sudoedit-block.stap 스크립트를 백그라운드로 실행
systemtap 스크립트가 백그라운드로 동작하는 동안 sudoedit 명령어가 작동하지 않는 것을 확인할 수 있다.
[그림 25] sudoedit 실행 시 차단되는 화면
2) 보안 업데이트
취약한 버전의 sudo 사용 시 취약점이 해결된 최신 버전으로의 업데이트가 필요하다.
No |
취약한 버전 |
보안 패치 버전 |
패치일자 |
1 |
1.8.2 ~1.8.31p2 |
1.8.32 |
2021-02-09 |
2 |
1.9.0 ~ 1.9.5p1 |
1.9.5p2 |
2021-01-26 |
현재 sudo의 버전은 “sudo –V” 명령어로 확인이 가능하다.
[그림 26] sudo 버전 확인
“sudoedit –s '' `perl –e 'print "A" x 65536'`” 페이로드로 현재 사용중인 sudo의 취약점 존재 여부 확인이 가능하다. 취약점이 존재하는 sudo 일 경우 해당 명령 실행 시 에러가 발생한다.
[그림 27] 사용중인 sudo에 취약점 존재 시 발생하는 메시지
취약점이 패치 된 sudo 일 경우 “usage:” 로 시작하는 메시지가 발생한다.
[그림 28] 사용중인 sudo에 취약점 존재하지 않을 시 발생하는 메시지
[그림 29]는 취약점이 패치 된 sudo 1.8.32 의 소스코드 sudoers.c 파일 내 set_cmnd() 함수의 내용이다. 기존 취약점이 존재하는 루틴에 힙 메모리 할당 시 계산한 사이즈와 파라미터로 전달 된 문자열의 사이즈를 계산하여 힙 오버플로우 공격을 방지하는 로직이 추가되었다.
[그림 29] 힙 오버플로우 공격 방어를 위해 추가된 로직
06. 참고자료
[1] CVE-2021-3156: Heap-Based Buffer Overflow in Sudo (Baron Samedit)
https://blog.qualys.com/vulnerabilities-research/2021/01/26/cve-2021-3156-heap-based-buffer-overflow-in-sudo-baron-samedit
[2] Sudo 1.9.5p1 - 'Baron Samedit ' Heap-Based Buffer Overflow Privilege Escalation (1)
https://www.exploit-db.com/exploits/49521
[3] Privilege escalation via command line argument parsing - sudo - (CVE-2021-3156)
https://access.redhat.com/security/vulnerabilities/RHSB-2021-002
[4] Dashboard Toolbox - VMDR DASHBOARD: Baron Samedit | Heap-based buffer overflow Sudo
https://qualys-secure.force.com/customer/s/article/000006518