def submit(): nmap = NmapParser() data = request.get_json() newhost = {} newhost = json.loads(data) if not nmap.has_scan_report(newhost['nmap_data']): return "[!] No scan report found! Make sure your scan includes \"%s\"" % nmap.REPORT try: newhost['ip'] = nmap.get_ip(newhost['nmap_data']) if not isAcceptableTarget(newhost['ip']): return "[!] This address isn't in our authorized scope!" newhost['hostname'] = nmap.get_hostname(newhost['nmap_data']) newhost['ports'] = str(nmap.get_ports(newhost['nmap_data'])) newhost['ctime'] = datetime.now() except Exception as e: return "[!] Couldn't find necessary nmap_data\n" + str(e) if len(newhost['ports']) == 0: return "[!] No open ports found!" if len(newhost['ports']) > 500: return "[!] More than 500 ports found. This is probably an IDS/IPS. We're going to throw the data out." current_app.elastic.newhost(newhost) return "[+] nmap successful and submitted for ip: " + newhost['ip']
def rescan_host(ip): rescanForm = RescanForm() if rescanForm.validate_on_submit(): if not isAcceptableTarget(ip): # Someone is requesting we scan an ip that isn't allowed flash("We're not allowed to scan %s" % ip, "danger") return redirect(request.referrer) incompleteScans = current_app.ScopeManager.getIncompleteScans() for scan in incompleteScans: if ip == scan.target: if scan.dispatched == True: status = "dispatched" if (datetime.utcnow() - scan.date_dispatched).seconds > 1200: # 20 minutes have past since dispatch, something probably wen't seriously wrong # move it back to not dispatched and update the cached rescan data scan.dispatched = False db.session.add(scan) db.session.commit() current_app.ScopeManager.updatePendingRescans() current_app.ScopeManager.updateDispatchedRescans() flash("Refreshed existing rescan request for %s" % ip, "success") return redirect(request.referrer) else: status = "pending" flash( "There's already a %s rescan request for %s" % (status, ip), "warning") return redirect(request.referrer) rescan = RescanTask(user_id=current_user.id, target=ip) db.session.add(rescan) db.session.commit() flash("Requested rescan of %s" % ip, "success") current_app.ScopeManager.updatePendingRescans() current_app.ScopeManager.updateDispatchedRescans() return redirect(request.referrer)
def submit(): data = request.get_json() newhost = {} newhost = json.loads(data) if newhost['scan_reason'] != 'auto': dispatched = current_app.ScopeManager.getDispatchedRescans() for scan in dispatched: if scan.target == newhost['ip']: scan.completeTask(newhost['scan_id']) db.session.add(scan) db.session.commit() current_app.ScopeManager.updateDispatchedRescans() break if newhost['scan_start'] and newhost['scan_stop']: elapsed = dateutil.parser.parse( newhost['scan_stop']) - dateutil.parser.parse( newhost['scan_start']) newhost['elapsed'] = elapsed.seconds # If the agent data has an is_up and it's false, store that in the database if not newhost["is_up"] or (newhost["is_up"] and newhost["port_count"] == 0): newhost["ctime"] = dt.now(tz.utc) current_app.elastic.newhost(newhost) return json.dumps({ "status": 200, "message": "Received: " + newhost['ip'] }), 200, { 'content-type': 'application/json' } nmap = NmapParser.parse(newhost['xml_data']) # Some quick checks to ensure there are hosts in the scan data if nmap.hosts_total != 1: return json.dumps({ "status": 400, "message": "XML had too many hosts in it", 'retry': False }), 400, { 'content-type': 'application/json' } newhost['ip'] = nmap.hosts[0].address if not isAcceptableTarget(newhost['ip']): return json.dumps({ "status": 400, "message": "Out of scope: " + newhost['ip'], 'retry': False }), 400, { 'content-type': 'application/json' } if len(nmap.hosts[0].hostnames) > 0: newhost['hostname'] = nmap.hosts[0].hostnames[0] newhost['ctime'] = dt.now(tz.utc) newhost['is_up'] = nmap.hosts[0].is_up() if not newhost['is_up']: current_app.elastic.newhost(newhost) return json.dumps({ "status": 200, "message": "Thanks for telling us " + newhost['ip'] + " is down" }), 200, { 'content-type': 'application/json' } tmpports = [] newhost['ports'] = [] for port in nmap.hosts[0].get_ports(): tmpports.append(str(port[0])) srv = nmap.hosts[0].get_service(port[0]) portinfo = srv.get_dict() portinfo['service'] = srv.service_dict portinfo['scripts'] = [] for script in srv.scripts_results: scriptsave = {"id": script['id'], "output": script["output"]} portinfo['scripts'].append(scriptsave) newhost['ports'].append(portinfo) newhost['port_str'] = ', '.join(tmpports) if len(newhost['ports']) == 0: return json.dumps({ "status": 200, "message": "Expected open ports but didn't find any for %s" % newhost['ip'] }), 200, { "content-type": "application/json" } if len(newhost['ports']) > 500: return json.dumps({ "status": 200, "message": "More than 500 ports found, throwing data out" }), 200, { "content-type": "application/json" } current_app.elastic.newhost(newhost) return json.dumps({ "status": 200, "message": "Received %s ports for %s" % (len(newhost['ports']), newhost['ip']) }), 200, { "content-type": "application/json" }
def submit(): data = request.get_json() newhost = {} newhost = json.loads(data) if newhost['scan_reason'] != 'auto': dispatched = current_app.ScopeManager.getDispatchedRescans() for scan in dispatched: if scan.target == newhost['ip']: scan.completeTask(newhost['scan_id']) db.session.add(scan) db.session.commit() current_app.ScopeManager.updateDispatchedRescans() break if newhost['scan_start'] and newhost['scan_stop']: elapsed = dateutil.parser.parse(newhost['scan_stop']) - dateutil.parser.parse(newhost['scan_start']) newhost['elapsed'] = elapsed.seconds # If the agent data has an is_up and it's false, store that in the database if not newhost["is_up"] or (newhost["is_up"] and newhost["port_count"] == 0): newhost["ctime"] = dt.now(tz.utc) current_app.elastic.newhost(newhost) return json.dumps({"status":200, "message": "Received: " + newhost['ip']}), 200, {'content-type':'application/json'} nmap = NmapParser.parse(newhost['xml_data']) # Some quick checks to ensure there are hosts in the scan data if nmap.hosts_total != 1: return json.dumps({"status":400, "message":"XML had too many hosts in it", 'retry':False}), 400, {'content-type':'application/json'} newhost['ip'] = nmap.hosts[0].address if not isAcceptableTarget(newhost['ip']): return json.dumps({"status":400, "message":"Out of scope: " + newhost['ip'], 'retry':False}), 400, {'content-type':'application/json'} if len(nmap.hosts[0].hostnames) > 0: newhost['hostname'] = nmap.hosts[0].hostnames[0] newhost['ctime'] = dt.now(tz.utc) newhost['is_up'] = nmap.hosts[0].is_up() if not newhost['is_up']: current_app.elastic.newhost(newhost) return json.dumps({"status":200, "message":"Thanks for telling us " + newhost['ip'] +" is down"}), 200, {'content-type':'application/json'} tmpports = [] newhost['ports'] = [] for port in nmap.hosts[0].get_ports(): tmpports.append(str(port[0])) srv = nmap.hosts[0].get_service(port[0]) portinfo = srv.get_dict() portinfo['service'] = srv.service_dict portinfo['scripts'] = [] for script in srv.scripts_results: scriptsave = {"id": script['id'], "output": script["output"]} portinfo['scripts'].append(scriptsave) newhost['ports'].append(portinfo) newhost['port_str'] = ', '.join(tmpports) if newhost['screenshots']: datepath = newhost['ctime'].strftime("%Y/%m/%d/%H") dirpath = os.path.join(current_app.config["MEDIA_DIRECTORY"], datepath) thumbpath = os.path.join(dirpath, "t") # makedirs attempts to make every directory necessary to get to the "thumbs" folder: YYYY/MM/DD/HH/thumbs os.makedirs(thumbpath, exist_ok=True) # Handle screenshots thumb_size = (255, 160) num_screenshots = 0 for item in newhost['screenshots']: if item['service'] == 'VNC': file_ext = '.jpg' else: # Handles http, https files from aquatone/chromium-headless file_ext = '.png' image = base64.b64decode(item['data']) image_hash = hashlib.sha256(image).hexdigest() fname = os.path.join(dirpath, image_hash + file_ext) with open(fname, 'wb') as f: f.write(image) # use datepath instead of dirpath so that we don't include the base media directory in elasticsearch data item['path'] = os.path.join(datepath, image_hash + file_ext) del item['data'] thumb = Image.open(fname) thumb.thumbnail(thumb_size) thumb_hash = hashlib.sha256(thumb.tobytes()).hexdigest() fname = os.path.join(dirpath, "t", thumb_hash + file_ext) thumb.save(fname) thumb.close() item['thumb'] = os.path.join(datepath, "t", thumb_hash + file_ext) num_screenshots +=1 newhost['num_screenshots'] = num_screenshots if len(newhost['ports']) == 0: return json.dumps({"status":200, "message":"Expected open ports but didn't find any for %s" % newhost['ip']}), 200, {"content-type":"application/json"} if len(newhost['ports']) > 500: return json.dumps({"status":200, "message":"More than 500 ports found, throwing data out"}), 200, {"content-type":"application/json"} current_app.elastic.newhost(newhost) return json.dumps({"status":200, "message":"Received %s ports for %s" % (len(newhost['ports']), newhost['ip'])}), 200, {"content-type":"application/json"}
def getwork(): manual = request.args.get('target', '') if "natlas-agent" in request.headers["user-agent"]: verstr = request.headers["user-agent"].split('/')[1] if verstr != current_app.config["NATLAS_VERSION"]: errmsg = "The server detected you were running version {} but the server is running {}".format( verstr, current_app.config["NATLAS_VERSION"]) return json.dumps({ 'status': 400, 'message': errmsg, 'retry': False }), 400, { 'content-type': 'application/json' } work = {} if manual: canTarget = isAcceptableTarget(manual) if canTarget: work['scan_reason'] = 'manual' work['target'] = manual work = prepare_work(work) return json.dumps(work), 200, {'content-type': 'application/json'} else: errmsg = "{} is not a valid target for this server.".format(manual) return json.dumps({ 'status': 400, 'message': errmsg, 'retry': False }), 400, { 'content-type': 'application/json' } rescans = current_app.ScopeManager.getPendingRescans() if len( rescans ) == 0: # If there aren't any rescans, update the Rescan Queue and get it again, because of lazy loading current_app.ScopeManager.updatePendingRescans() rescans = current_app.ScopeManager.getPendingRescans() if len(rescans) == 0: # if we don't have rescans, use the ScanManager scanmanager = current_app.ScopeManager.getScanManager() if not scanmanager: current_app.ScopeManager.update() scanmanager = current_app.ScopeManager.getScanManager() if not scanmanager: return json.dumps({ 'status': 404, 'message': 'No scope is currently configured.', "retry": True }), 404, { 'content-type': 'application/json' } work['target'] = str(scanmanager.getNextIP()) work['scan_reason'] = 'auto' else: # Get the ip from the rescan queue, mark the job as dispatched, update the PendingRescans for other requests work['target'] = rescans[0].target work['scan_reason'] = 'requested' rescans[0].dispatchTask() db.session.add(rescans[0]) db.session.commit() current_app.ScopeManager.updatePendingRescans() current_app.ScopeManager.updateDispatchedRescans() work = prepare_work(work) return json.dumps(work), 200, {'content-type': 'application/json'}