Ejemplo n.º 1
0
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']
Ejemplo n.º 2
0
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)
Ejemplo n.º 3
0
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"
    }
Ejemplo n.º 4
0
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"}
Ejemplo n.º 5
0
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'}