抱歉,你查看的文章已删除

GoAHEAD嵌入式WEB SERVER漏洞概览

GOAHEAD由于开源、简单、轻巧、功能强大、多平台等特点,主要运用于嵌入式设备上。考虑到如路由器等等的使用场景等加上出现的漏洞情况等等,使得其漏洞利用难度也会被大大降低,故最终漏洞造成的危害不容忽视。

本文以Linux debian 4.9.0-4-686-pae #1 SMP Debian 4.9.65-3+deb9u1 (2017-12-23) i686 GNU/Linux为实验环境尝试分析其存在过的目录遍历漏洞,堆溢出漏洞,以及最近的远程代码执行漏洞。

3.0.0 - 3.4.1 (3.x.x series before 3.4.2)目录遍历

首先,根据官方对该漏洞的简要描述得到一些信息。

故这里先对3.4.1和3.4.2做差异对比。

这里进行了websValidateUriPath对websNormalizeUriPath外层包装,并通过 segments[j] = segments[i];完成output与input之间的拷贝,不单单是自增保证堆不会溢出。

根据http://seclists.org/fulldisclosure/2015/Mar/157的描述可知是websNormalizeUriPath未能处理好以.字符开头的segment。

websNormalizeUriPath通过分割正斜杠到array中,并相应计算对应segments的长度,开始循环处理array的in-place normalization。根据3种情况处理。

(1)对应最后一部分里的处理,直接将segment原样拷贝。

(2)如果是仅仅为.则根据是否nseg个选择是忽略还是加上结束标志"",类似的对于..则相应向前合并到2个位置前并做有效性的检查集头尾的相应处理。

(3)以.开始但非.,..二者将会被直接跳过。

最终,将会pathArg的去除正向斜杠后长度和nseg也就是最后实际去除多余/及.或者..后的实际segment数量,补上\0的1字节。

对于如上分析,假设请求的uri是/../../../.x/.x/.x/.x/etc/password。

在第一次经过/处理的分割出segments如下为(1)null (2).. (3).. (4).. (5).x (6).x (7).x (8).x (9).x (10)etc (11)password。

在经过.及..的处理后变成(1)null (2).. (3).. (4).. (5)etc (6) password.

也就是最后在segment同/拼接后会形成/../../../etc/password。具体到细节的话,可以再次观察如下片段。

可以发现在..的处理中对于i == 1 && *segments[0] == '\0'时在迭代前会j=0,之后会因为 j = max(j - 2, -1);变成-1,进入到第一个.x开始变成0,故构造uri以这样格式需要多出一个.x。

实验中,实际路径如/home/oreo/文档/BinVuln/goahead_cve20149707/goahead-3.4.1/goahead-3.4.1/test/web。

故构造为如下脚本就可以完成目录遍历。

3.0.0 - 3.4.1 (3.x.x series before 3.4.2)堆溢出

依照如上分析,这里以/./AAAAAAAA/.x为例分析其漏洞形成的步骤。

第一步在经过/的处理的初步segment划分后,首先形成如下的segment:(1)null (2) . (3)AAAAAAA (4) .x 。此时len后变成1+8+2=11 bytes。

在经过.及..处理后形成的segement如下:(1)null (2)AAAAAAAA (3)AAAAAAAA。此时neg=j=3。

故最后的path输出的空间大小经过if ((path = walloc(len + nseg + 1)) != 0) 可知为11+3+1=15bytes。而实际可知实际最后形成的path为/AAAAAAAA/AAAAAAAA为8+8+2+1=19Byte>15bytes,发生了堆溢出。

目前glibc主要做如下检查。

(1)合并chunk的prev_inuse是否进行设置,如果未设置则抛出异常。

(2)BK->fd != P FD->bk != P,其中BK是P->bk,FD是P->fd。

(3)nextchunk->size = av->system_mem检查next chunk的size必须在16-arena最大小范围内。

具体对应到glibc的malloc.c的unlink宏定义如下。

除了BK->fd != P FD->bk != P双向链表的检查外还包括了对于large bin(第64个bin,512bytes以上范围内的bin)会进行P->fd_nextsize->bk_nextsize != P P->bk_nextsize->fd_nextsize != P的次要循环链表的检查。

再次观察wmalloc填充完/和多个segment的拼接后存在如下代码。

那么最终思路就是覆盖完dupPath后,通过wfree完成后续空闲堆的unlink,如果能通过覆写free@GOT为shellcode的地址,那么wfree(segments)就会在调用时转为调用shellcode达到远程代码执行。然后构造/不包含\x00的shellcode/.a。假设不包含\x00的shellcode的长度为x,neg=j=3,wmalloc的长度为x+2+3+1=x+6,而实际的长度为x\*2+2+1=2\*x+3。

before 3.6.5 LD_PRELOAD远程代码执行

对于GoAhead web server < 3.6.5,使用http request参数初始化forked CGI 脚本环境变量,如果能够控制LD_PRELOAD那么便能远程代码执行。、

实验运行方式如下:

首先分析比较goahead 3.6.4版本及goahead 3.6.5发生差异的部分。

这里首先可以了解其修补漏洞的方式,其引入了ME_GOAHEAD_CGI_VAR_PREFIX同提交的内容通过sfmt进行字符串格式化以保证LD_PRELOAD这样的重要的环境变量不会被劫持。

根据分析,CgiHandler会使用launchCgi进行cgi脚本环境的初始化。该函数包括多个平台的实现版本,这里关注能够触发漏洞linux版本。vfork函数(vfork共享堆栈段,数据段)使得父进程直到子进程到execve前的挂起。重要的是这里会将传递过来的envp作为execve程序的环境变量。

继续关注cgiHandler将什么传递给了lanuchCgi。envp处理相关部分均在这里。

可以分析出envp环境变量由64bytes根据情况不断扩容,推测其根据http request将非REMOTE_HOST及HTTP_AUTHORIZATION的内容以key=value的形式放入。所以http://127.0.0.1/cgi-bin/cgitest?key=value中的key=value就会被作为环境变量带入。那么http://127.0.0.1/cgi-bin/cgitest?LD_PRELOAD=value就可以控制execve的LD_PRELOAD。

分析文章给出了大段的解释为何LD_PRELOAD会加载一个用户指定的so共享库。这里简而言之。

通过LD_TRACE_LOADED_OBJECTS=1 ./goahead展示了程序与程序依赖库的运行顺序,/lib/i386-linux-gnu/libc.so.6即为第一个加载的lib。根据源码可知,内核加载可执行文件后,首先交给\_\_start调用elf/rtld.c的\_\_dl\_main完成ld.so的自举完成自身的重定位。后转入entry point默认为是/libc/sysdeps/i386/elf/Start.S中的\_start调用__lib_start_main完成main的初始化工作再调用main函数。

其中重要的是dl_main会通过_dl_next_ld_env_entry (&runp))获取所有LD开头的环境变量并处理PRELOAD。

如果存入的preloadlist不为空则调用handle_ld_preload函数依次完成so文件的加载。

所以这说明了如果控制LD_PRELOAD的环境变量,就可以完成任意代码执行。同时为了加载ld_preload的so文件时代码就能执行,需要将函数放入.init section,这样就会在初始化时依次调用.init section的所有函数。

可以看到cgi处理机制同其他web server一致均使用(fdin = open(stdIn, O_RDWR O_CREAT O_BINARY, 0666)) < 0及dup2(fdin, 0)来完成post内容重定向到标准输入,所以该进程的标准输入与控制台解绑,转而指向socket通信的内容,故通过request body写入so文件,便可以通过linux的符号链接/proc/self/fd/0来访问该输入流。

参考内容

https://github.com/embedthis/goahead.git

https://www.elttam.com.au/blog/goahead/

http://blog.51cto.com/laokaddk/981868

http://blog.chinaunix.net/uid-2282111-id-2113348.html

https://sploitfun.wordpress.com/2015/02/10/understanding-glibc-malloc/comment-page-1/?blogsub=confirming#subscribe-blog%E3%80%82

http://blog.csdn.net/initphp/article/details/50833036

https://www.cnblogs.com/alisecurity/p/5520847.html

本文来自企鹅号 - 漏洞盒子VulBox媒体

编辑于

区块链

0 篇文章0 人订阅

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励