前言


本文由 本人 首发于 先知安全技术社区: https://xz.aliyun.com/u/5274

最近在分析 dlink 的一个固件时遇到了用 goahead 开发的 web 服务。本文以一个 github 上的 开源项目为例简单介绍下对基于 goahead 的程序的分析。

https://github.com/Grant999/goahead-1

这里用的 goahead 程序的版本为 2.5

正文

编译运行

把源码下载下来,然后使用 make 编译即可。

$ make
................................................
................................................
................................................
gcc -m32 -g -O0 -Wall -DWITH_NONAMESPACES -o webs -Os \
-DWEBS -DOS="LINUX" -DLINUX -DUSER_MANAGEMENT_SUPPORT -DDIGEST_ACCESS_SUPPORT -I. -g -O0 -Wall \
main.o libwebs.a
tempnam' is dangerous, better use `mkstemp'

编译完成后当前目录下会生成一个 webs 的文件, 这个就是 goahead 编译完成生成的二进制文件。

然后运行它,就会在 80 端口起一个 http 服务(监听 80 端口需要权限, 所以用 root 运行程序)。

$ sudo ./webs
webdir: ./www

然后用 浏览器去访问

基于goahead 的固件程序分析-LMLPHP

分析

要测试一个东西,首先需要尽可能的去了解它(信息搜集)。

goahead 开发 api

我们首先了解一下 goahead 的工作机制。

GoAhead 自身实现了一个 web 服务器所需提供的基本功能,此外它提供了多种方法供用户扩展服务器的功能, 其中包括 asp过程、GoForms 过程 , embedded JavaScript 以及外部 cgi 程序等, 用户可以根据这些接口开发出各种各样的功能。

对于 goahead 本身, 这个项目时间也非常就久了,安全性也得到了检验,所以我们分析的重点不是goahead 本身的代码,而应该是用户自定义的那些代码。

相关的 api 如下

websUrlHandlerDefine

websUrlHandlerDefine(T("/goform"), NULL, 0, websFormHandler, 0);

表示 对 /goform 的请求都交给 websFormHandler 函数处理。函数的参数列表如下

int websFormHandler(webs_t wp, char_t *urlPrefix, char_t *webDir, int arg,
char_t *url, char_t *path, char_t *query)

其中 wp 这个参数里面包含了用户 请求的相关信息,比如请求头, 请求数据等。开发者通过 wp 这个参数就能获取到 用户请求的信息了。

websAspDefine

websAspDefine(T("aspTest"), aspTest);

当在 asp 文件中调用 aspTest, 实际调用的是这里 aspTest 这个 c 函数

基于goahead 的固件程序分析-LMLPHP

ps:

调用的 asp 函数的语句需要用 <% %> 包围

websFormDefine

websFormDefine(T("privacy"), FormPrivacy);

websUrlHandlerDefine 差不多, 表示往 /goform/privacy 的请求由 FormPrivacy 这个函数进行处理。

漏洞分析

根据上面提到的 api 在源代码里面搜索引用,可以很快的找的注册用户自定义回调函数的位置。

位于 initWebs 函数

基于goahead 的固件程序分析-LMLPHP

向上面4个 websUrlHandlerDefinegoahead 自带的,这里不管它。

通过对下面几个注册的函数的简单浏览,在 FormPrivacy 函数内部存在一个栈溢出漏洞。

下面对这个函数做一个简单的分析

基于goahead 的固件程序分析-LMLPHP

首先用

websGetVar(wp, T("Operate"), T(""))

获取 Operate 参数的值, 然后根据值的不同,进行不同的操作。

问题出在了 set 这操作的处理逻辑

基于goahead 的固件程序分析-LMLPHP

首先取出几个参数, 然后使用 sprintf 把参数填到 szParam 这个缓冲区 (缓冲区大小为 20 * 20), 这里 sprintf 使用的是 %s 不会校验字符串的长度,所以当我们传一个很长的字符串作为 Height 的参数值,就会触发栈溢出。

触发+简单调试

通过搜索关键字,定位到往这里 发请求的应该是 privacy.asp

基于goahead 的固件程序分析-LMLPHP

然后访问他

基于goahead 的固件程序分析-LMLPHP

填些参数然后抓包, 修改 Height 的值为一个很长的字符串

基于goahead 的固件程序分析-LMLPHP

同时在 FormPrivacy 设置一个断点, 发送请求过去,程序会断下来, 我们可以看看参数信息。

基于goahead 的固件程序分析-LMLPHP

可以看到 wp 里面保存了此次请求的相关信息, 继续运行可以触发栈溢出

基于goahead 的固件程序分析-LMLPHP

总结

分析 goahead 等可供开发者扩展的程序,分析的重点应该在那些自定义的代码上。

04-16 02:26