Remove attackers cron and visualization

This commit is contained in:
Brandon Myers 2020-02-18 13:23:08 -06:00
Родитель b203c087f1
Коммит 8e78be60b2
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 8AA79AD83045BBC7
26 изменённых файлов: 0 добавлений и 2065 удалений

Просмотреть файл

@ -241,9 +241,6 @@ Resources:
cookiename=sesmeteor
# Increase the AWS ES total fields limit from 1000 to 4000
OPTIONS_MAPPING_TOTAL_FIELDS_LIMIT=4000
# Set thresholds for attack dataviz lower means more ogres
OPTIONS_IPV4ATTACKERHITCOUNT=5
OPTIONS_IPV4ATTACKERPREFIXLENGTH=24
OPTIONS_ALERTSQSQUEUEURL=${AlertQueueUrl}
OPTIONS_MQPROTOCOL=sqs
DEFAULT_AWS_REGION=${AWS::Region}

Просмотреть файл

@ -1,9 +0,0 @@
[options]
esservers=http://localhost:9200
mongoport=3002
autocategorize = True
categorymapping = [{"bruteforce":"bruteforcer"},{"nothing":"nothing"}]
broadcastattackers = True
mqserver=localhost
mquser=guest
mqpassword=guest

Просмотреть файл

@ -1,473 +0,0 @@
#!/usr/bin/env python
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Copyright (c) 2014 Mozilla Corporation
import collections
import json
import random
import netaddr
import sys
from bson.son import SON
from datetime import datetime
from configlib import getConfig, OptionParser
from pymongo import MongoClient
from collections import Counter
from kombu import Connection, Exchange
from mozdef_util.utilities.logger import logger
from mozdef_util.utilities.toUTC import toUTC
from mozdef_util.elasticsearch_client import ElasticsearchClient
from mozdef_util.query_models import SearchQuery, PhraseMatch
def isIPv4(ip):
try:
# netaddr on it's own considers 1 and 0 to be valid_ipv4
# so a little sanity check prior to netaddr.
# Use IPNetwork instead of valid_ipv4 to allow CIDR
if '.' in ip and len(ip.split('.'))==4:
# some ips are quoted
netaddr.IPNetwork(ip.strip("'").strip('"'))
return True
else:
return False
except:
return False
def genMeteorID():
return('%024x' % random.randrange(16**24))
def keypaths(nested):
''' return a list of nested dict key paths
like: [u'_source', u'details', u'hostname']
'''
for key, value in nested.items():
if isinstance(value, collections.Mapping):
for subkey, subvalue in keypaths(value):
yield [key] + subkey, subvalue
else:
yield [key], value
def dictpath(path):
''' split a string representing a
nested dictionary path key.subkey.subkey
'''
for i in path.split('.'):
yield '{0}'.format(i)
def mostCommon(listofdicts,dictkeypath):
"""
Given a list containing dictionaries,
return the most common entries
along a key path separated by .
i.e. dictkey.subkey.subkey
returned as a list of tuples
[(value,count),(value,count)]
"""
inspectlist=list()
path=list(dictpath(dictkeypath))
for i in listofdicts:
for k in list(keypaths(i)):
if not (set(k[0]).symmetric_difference(path)):
inspectlist.append(k[1])
return Counter(inspectlist).most_common()
def searchESForBROAttackers(es, threshold):
search_query = SearchQuery(hours=2)
search_query.add_must([
PhraseMatch('category', 'bro'),
PhraseMatch('details.note', 'MozillaHTTPErrors::Excessive_HTTP_Errors_Attacker')
])
full_results = search_query.execute(es)
results = full_results['hits']
# Hit count is buried in the 'sub' field
# as: 'sub': u'6 in 1.0 hr, eps: 0'
# cull the records for hitcounts over the threshold before returning
attackers = list()
for r in results:
hitcount = int(r['_source']['details']['sub'].split()[0])
if hitcount > threshold:
attackers.append(r)
return attackers
def searchMongoAlerts(mozdefdb):
attackers = mozdefdb['attackers']
alerts = mozdefdb['alerts']
# search the last X alerts for IP addresses
# aggregated by CIDR mask/24
# aggregate IPv4 addresses in the most recent alerts
# to find common attackers.
ipv4TopHits = alerts.aggregate([
# reverse sort the current alerts
{"$sort": {"utcepoch": -1}},
# most recent 100
{"$limit": 100},
# must have an ip address
{"$match": {"events.documentsource.details.sourceipaddress": {"$exists": True}}},
# must not be already related to an attacker
{"$match": {"attackerid": {"$exists": False}}},
# make each event into it's own doc
{"$unwind": "$events"},
{"$project": {
"_id": 0,
# emit the source ip only
"sourceip": "$events.documentsource.details.sourceipaddress"
}},
# count by ip
{"$group": {"_id": "$sourceip", "hitcount": {"$sum": 1}}},
# limit to those with X observances
{"$match": {"hitcount": {"$gt": options.ipv4attackerhitcount}}},
# sort
{"$sort": SON([("hitcount", -1), ("_id", -1)])},
# top 10
{"$limit": 10}
])
for ip in ipv4TopHits:
# sanity check ip['_id'] which should be the ipv4 address
if isIPv4(ip['_id']) and ip['_id'] not in netaddr.IPSet(['0.0.0.0']):
ipcidr = netaddr.IPNetwork(ip['_id'])
# set CIDR
# todo: lookup ipwhois for asn_cidr value
# potentially with a max mask value (i.e. asn is /8, limit attackers to /24)
ipcidr.prefixlen = options.ipv4attackerprefixlength
# append to or create attacker.
# does this match an existing attacker's indicators
if not ipcidr.ip.is_loopback() and not ipcidr.ip.is_private() and not ipcidr.ip.is_reserved():
logger.debug('Searching for existing attacker with ip ' + str(ipcidr))
attacker = attackers.find_one({'indicators.ipv4address': str(ipcidr)})
if attacker is None:
logger.debug('Attacker not found, creating new one')
# new attacker
# generate a meteor-compatible ID
# save the ES document type, index, id
newAttacker = genNewAttacker()
# str to get the ip/cidr rather than netblock cidr.
# i.e. '1.2.3.4/24' not '1.2.3.0/24'
newAttacker['indicators'].append(dict(ipv4address=str(ipcidr)))
matchingalerts = alerts.find(
{"events.documentsource.details.sourceipaddress":
str(ipcidr.ip),
})
total_events = 0
if matchingalerts is not None:
# update list of alerts this attacker matched.
for alert in matchingalerts:
newAttacker['alerts'].append(
dict(alertid=alert['_id'])
)
# update alert with attackerID
alert['attackerid'] = newAttacker['_id']
alerts.save(alert)
total_events += len(alert['events'])
if len(alert['events']) > 0:
newAttacker['lastseentimestamp'] = toUTC(alert['events'][-1]['documentsource']['utctimestamp'])
newAttacker['alertscount'] = len(newAttacker['alerts'])
newAttacker['eventscount'] = total_events
attackers.insert(newAttacker)
# update geoIP info
latestGeoIP = [a['events'] for a in alerts.find(
{"events.documentsource.details.sourceipaddress":
str(ipcidr.ip),
})][-1][0]['documentsource']
updateAttackerGeoIP(mozdefdb, newAttacker['_id'], latestGeoIP)
if options.broadcastattackers:
broadcastAttacker(newAttacker)
else:
logger.debug('Found existing attacker')
# if alert not present in this attackers list
# append this to the list
# todo: trim the list at X (i.e. last 100)
# search alerts without attackerid
matchingalerts = alerts.find(
{"events.documentsource.details.sourceipaddress":
str(ipcidr.ip),
"attackerid":{"$exists": False}
})
if matchingalerts is not None:
logger.debug('Matched alert with attacker')
# update list of alerts this attacker matched.
for alert in matchingalerts:
attacker['alerts'].append(
dict(alertid=alert['_id'])
)
# update alert with attackerID
alert['attackerid'] = attacker['_id']
alerts.save(alert)
attacker['eventscount'] += len(alert['events'])
attacker['lastseentimestamp'] = toUTC(alert['events'][-1]['documentsource']['utctimestamp'])
# geo ip could have changed, update it to the latest
updateAttackerGeoIP(mozdefdb, attacker['_id'], alert['events'][-1]['documentsource'])
# update counts
attacker['alertscount'] = len(attacker['alerts'])
attackers.save(attacker)
# should we autocategorize the attacker
# based on their alerts?
if attacker['category'] == 'unknown' and options.autocategorize:
# take a look at recent alerts for this attacker
# and if they are all the same category
# auto-categorize the attacker
matchingalerts = alerts.find(
{"attackerid": attacker['_id']}
).sort('utcepoch', -1).limit(50)
# summarize the alert categories
# returns list of tuples: [(u'bruteforce', 8)]
categoryCounts= mostCommon(matchingalerts,'category')
# are the alerts all the same category?
if len(categoryCounts) == 1:
# is the alert category mapped to an attacker category?
for category in options.categorymapping:
if list(category.keys())[0] == categoryCounts[0][0]:
attacker['category'] = category[list(category.keys())[0]]
attackers.save(attacker)
def broadcastAttacker(attacker):
'''
send this attacker info to our message queue
'''
try:
connString = 'amqp://{0}:{1}@{2}:{3}/{4}'.format(options.mquser,
options.mqpassword,
options.mqserver,
options.mqport,
options.mqvhost)
if options.mqprotocol == 'amqps':
mqSSL = True
else:
mqSSL = False
mqConn = Connection(connString, ssl=mqSSL)
alertExchange = Exchange(
name=options.alertexchange,
type='topic',
durable=True)
alertExchange(mqConn).declare()
mqproducer = mqConn.Producer(serializer='json')
logger.debug('Kombu configured')
except Exception as e:
logger.error('Exception while configuring kombu for alerts: {0}'.format(e))
try:
# generate an 'alert' structure for this attacker:
mqAlert = dict(severity='NOTICE', category='attacker')
if 'datecreated' in attacker:
mqAlert['utctimestamp'] = attacker['datecreated'].isoformat()
mqAlert['summary'] = 'New Attacker: {0} events: {1}, alerts: {2}'.format(attacker['indicators'], attacker['eventscount'], attacker['alertscount'])
logger.debug(mqAlert)
ensurePublish = mqConn.ensure(
mqproducer,
mqproducer.publish,
max_retries=10)
ensurePublish(
mqAlert,
exchange=alertExchange,
routing_key=options.routingkey
)
except Exception as e:
logger.error('Exception while publishing attacker: {0}'.format(e))
def genNewAttacker():
newAttacker = dict()
newAttacker['_id'] = genMeteorID()
newAttacker['lastseentimestamp'] = toUTC(datetime.now())
newAttacker['firstseentimestamp'] = toUTC(datetime.now())
newAttacker['eventscount'] = 0
newAttacker['alerts'] = list()
newAttacker['alertscount'] = 0
newAttacker['category'] = 'unknown'
newAttacker['score'] = 0
newAttacker['geocoordinates'] = dict(countrycode='', longitude=0, latitude=0)
newAttacker['tags'] = list()
newAttacker['notes'] = list()
newAttacker['indicators'] = list()
newAttacker['attackphase'] = 'unknown'
newAttacker['datecreated'] = toUTC(datetime.now())
newAttacker['creator'] = sys.argv[0]
return newAttacker
def updateAttackerGeoIP(mozdefdb, attackerID, eventDictionary):
'''given an attacker ID and a dictionary of an elastic search event
look for a valid geoIP in the dict and update the attacker's geo coordinates
'''
# geo ip should be in eventDictionary['details']['sourceipgeolocation']
# "sourceipgeolocation": {
# "city": "Polska",
# "region_code": "73",
# "area_code": 0,
# "time_zone": "Europe/Warsaw",
# "dma_code": 0,
# "metro_code": null,
# "country_code3": "POL",
# "latitude": 52.59309999999999,
# "postal_code": null,
# "longitude": 19.089400000000012,
# "country_code": "PL",
# "country_name": "Poland",
# "continent": "EU"
# }
# logger.debug(eventDictionary)
if 'details' in eventDictionary:
if 'sourceipgeolocation' in eventDictionary['details']:
attackers=mozdefdb['attackers']
attacker = attackers.find_one({'_id': attackerID})
if attacker is not None:
attacker['geocoordinates'] = dict(countrycode='',
longitude=0,
latitude=0)
if 'country_code' in eventDictionary['details']['sourceipgeolocation']:
attacker['geocoordinates']['countrycode'] = eventDictionary['details']['sourceipgeolocation']['country_code']
if 'longitude' in eventDictionary['details']['sourceipgeolocation']:
attacker['geocoordinates']['longitude'] = eventDictionary['details']['sourceipgeolocation']['longitude']
if 'latitude' in eventDictionary['details']['sourceipgeolocation']:
attacker['geocoordinates']['latitude'] = eventDictionary['details']['sourceipgeolocation']['latitude']
attackers.save(attacker)
else:
logger.debug('no details in the dictionary')
logger.debug(eventDictionary)
def updateMongoWithESEvents(mozdefdb, results):
logger.debug('Looping through events identified as malicious from bro')
attackers = mozdefdb['attackers']
for r in results:
if 'sourceipaddress' in r['_source']['details']:
if netaddr.valid_ipv4(r['_source']['details']['sourceipaddress']):
sourceIP = netaddr.IPNetwork(r['_source']['details']['sourceipaddress'])
# expand it to a /24 CIDR
# todo: lookup ipwhois for asn_cidr value
# potentially with a max mask value (i.e. asn is /8, limit attackers to /24)
sourceIP.prefixlen = 24
if not sourceIP.ip.is_loopback() and not sourceIP.ip.is_private() and not sourceIP.ip.is_reserved():
esrecord = dict(
documentid=r['_id'],
documentindex=r['_index'],
documentsource=r['_source']
)
logger.debug('Trying to find existing attacker at ' + str(sourceIP))
attacker = attackers.find_one({'indicators.ipv4address': str(sourceIP)})
if attacker is None:
# new attacker
# generate a meteor-compatible ID
# save the ES document type, index, id
# and add a sub list for future events
logger.debug('Creating new attacker from ' + str(sourceIP))
newAttacker = genNewAttacker()
# expand the source ip to a /24 for the indicator match.
sourceIP.prefixlen = 24
# str sourceIP to get the ip/cidr rather than netblock cidr.
newAttacker['indicators'].append(dict(ipv4address=str(sourceIP)))
newAttacker['eventscount'] = 1
newAttacker['lastseentimestamp'] = esrecord['documentsource']['utctimestamp']
attackers.insert(newAttacker)
updateAttackerGeoIP(mozdefdb, newAttacker['_id'], esrecord['documentsource'])
else:
logger.debug('Attacker found, increasing eventscount and modding geoip')
attacker['eventscount'] += 1
attacker['lastseentimestamp'] = esrecord['documentsource']['utctimestamp']
attackers.save(attacker)
# geo ip could have changed, update it
updateAttackerGeoIP(mozdefdb, attacker['_id'], esrecord['documentsource'])
def main():
logger.debug('starting')
logger.debug(options)
try:
es = ElasticsearchClient((list('{0}'.format(s) for s in options.esservers)))
client = MongoClient(options.mongohost, options.mongoport)
# use meteor db
mozdefdb = client.meteor
esResults = searchESForBROAttackers(es, 100)
updateMongoWithESEvents(mozdefdb, esResults)
searchMongoAlerts(mozdefdb)
except ValueError as e:
logger.error("Exception %r collecting attackers to mongo" % e)
def initConfig():
# output our log to stdout or syslog
options.output = getConfig('output', 'stdout', options.configfile)
# syslog hostname
options.sysloghostname = getConfig('sysloghostname',
'localhost',
options.configfile)
# syslog port
options.syslogport = getConfig('syslogport', 514, options.configfile)
# elastic search server settings
options.esservers = list(getConfig('esservers',
'http://localhost:9200',
options.configfile).split(','))
options.mongohost = getConfig('mongohost', 'localhost', options.configfile)
options.mongoport = getConfig('mongoport', 3001, options.configfile)
# should we automatically categorize
# new attackers based on their alerts?
options.autocategorize = getConfig('autocategorize', False, options.configfile)
# get the mapping of alert category to attacker category
# supply as a list of dicts:
# [{"bruteforce":"bruteforcer"},{"alertcategory":"attackercategory"}]
options.categorymapping = json.loads(getConfig('categorymapping', "[]", options.configfile))
# should we broadcast new attackers
# to a message queue?
options.broadcastattackers = getConfig('broadcastattackers', False, options.configfile)
# message queue options
options.mqserver = getConfig('mqserver', 'localhost', options.configfile)
options.alertexchange = getConfig('alertexchange', 'alerts', options.configfile)
options.routingkey = getConfig('routingkey', 'mozdef.alert', options.configfile)
options.mquser = getConfig('mquser', 'guest', options.configfile)
options.mqpassword = getConfig('mqpassword', 'guest', options.configfile)
options.mqport = getConfig('mqport', 5672, options.configfile)
options.mqvhost = getConfig('mqvhost', '/', options.configfile)
# set to either amqp or amqps for ssl
options.mqprotocol = getConfig('mqprotocol', 'amqp', options.configfile)
# Set these settings to change the correlation for attackers
options.ipv4attackerprefixlength = getConfig('ipv4attackerprefixlength', 32, options.configfile)
options.ipv4attackerhitcount = getConfig('ipv4ipv4attackerhitcount', 5, options.configfile)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option(
"-c",
dest='configfile',
default=sys.argv[0].replace('.py', '.conf'),
help="configuration file to use")
(options, args) = parser.parse_args()
initConfig()
main()

Просмотреть файл

@ -1,9 +0,0 @@
#!/usr/bin/env bash
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
# Copyright (c) 2014 Mozilla Corporation
source /opt/mozdef/envs/python/bin/activate
/opt/mozdef/envs/mozdef/cron/collectAttackers.py -c /opt/mozdef/envs/mozdef/cron/collectAttackers.conf

Просмотреть файл

@ -13,7 +13,6 @@ COPY docker/compose/mozdef_cron/files/cron_entries.txt /cron_entries.txt
# Copy config files for crons
COPY --chown=mozdef:mozdef docker/compose/mozdef_cron/files/backup.conf /opt/mozdef/envs/mozdef/cron/backup.conf
COPY --chown=mozdef:mozdef docker/compose/mozdef_cron/files/collectAttackers.conf /opt/mozdef/envs/mozdef/cron/collectAttackers.conf
COPY --chown=mozdef:mozdef docker/compose/mozdef_cron/files/eventStats.conf /opt/mozdef/envs/mozdef/cron/eventStats.conf
COPY --chown=mozdef:mozdef docker/compose/mozdef_cron/files/healthAndStatus.conf /opt/mozdef/envs/mozdef/cron/healthAndStatus.conf
COPY --chown=mozdef:mozdef docker/compose/mozdef_cron/files/healthToMongo.conf /opt/mozdef/envs/mozdef/cron/healthToMongo.conf

Просмотреть файл

@ -1,10 +0,0 @@
[options]
esservers=http://elasticsearch:9200
mongohost=mongodb
mongoport=3002
autocategorize = True
categorymapping = [{"bruteforce":"bruteforcer"},{"nothing":"nothing"}]
broadcastattackers = True
mqserver=rabbitmq
mquser=guest
mqpassword=guest

Просмотреть файл

@ -1,7 +1,6 @@
BASH_ENV=/env
* * * * * /opt/mozdef/envs/mozdef/cron/healthAndStatus.sh
* * * * * /opt/mozdef/envs/mozdef/cron/healthToMongo.sh
* * * * * /opt/mozdef/envs/mozdef/cron/collectAttackers.sh
* * * * * /opt/mozdef/envs/mozdef/cron/syncAlertsToMongo.sh
* * * * * /opt/mozdef/envs/mozdef/cron/eventStats.sh
0 0 * * * /opt/mozdef/envs/mozdef/cron/esMaint.sh

Просмотреть файл

@ -1,74 +0,0 @@
<!--
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
Copyright (c) 2014 Mozilla Corporation
-->
<template name="attackerdetails">
<div class="container">
<div class="row center">
<div id="attacker" >
<table class="table table-reactive table-hover table-condensed" id="alert-table">
<thead>
<tr>
<td class="upperwhite">Last Seen</td>
<td class="upperwhite">Created</td>
<td class="upperwhite">Events</td>
<td class="upperwhite">Alerts</td>
<td class="upperwhite">Category</td>
<td class="upperwhite">Summary</td>
</tr>
</thead>
<tbody>
<tr>
<td>{{lastseentimestamp}}</td>
<td>{{dateCreated}}</td>
<td>{{eventscount}}</td>
<td>{{alertscount}}</td>
<td>
<select id="attackerCategory" name="category" class="form-control" title="category of this attacker">
<option {{ isselected 'unknown' category }} value='unknown'>Unknown</option>
<option {{ isselected 'skiddie' category }} value='skiddie'>Script Kiddie</option>
<option {{ isselected 'bruteforcer' category }} value='bruteforcer'>Brute Forcer</option>
<option {{ isselected 'bountyhunter' category }} value='bountyhunter'>Bounty Hunter</option>
<option {{ isselected 'apt' category }} value='apt'>APT</option>
<option {{ isselected 'falsepositive' category }} value='falsepositive'>False Positive</option>
</select>
</td>
<td>{{{ipDecorate summary}}}</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row center">
<caption><h5>Alerts</h5></caption>
<table class="table table-reactive table-hover table-condensed " id="attacker-alerts-table">
<tbody class="table-striped">
{{#each this.alerts}}
{{#with thisalert this.alertid}}
{{>attacker_alert}}
{{/with}}
{{/each}}
</tbody>
</table>
</div>
</div>
</template>
<!--each individual alert -->
<template name="attacker_alert">
<tr>
<td><a href="{{getAlertURL _id}}" target="_blank">MozDef</a></td>
<td>{{utctimestamp}}</td>
<td>{{severity}}</td>
<td>{{category}}</td>
<td>{{{ ipDecorate summary}}}</td>
</tr>
</template>

Просмотреть файл

@ -1,47 +0,0 @@
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
Copyright (c) 2014 Mozilla Corporation
*/
import { Meteor } from 'meteor/meteor'
import { Template } from 'meteor/templating';
import { Session } from 'meteor/session';
import { Tracker } from 'meteor/tracker';
import { tooltip } from 'meteor/twbs:bootstrap';
if (Meteor.isClient) {
Template.attackerdetails.events({
"change #attackerCategory": function(e,t){
attackers.update(Session.get('attackerID'), {$set: {'category':$('#attackerCategory').val()}});
}
});
//details helpers
Template.attackerdetails.thisalert = function (mongoalertid) {
//attackers store a ref mongo id to alerts attacker.alerts.alertid
//return an alert given it's mongo id
return alerts.findOne({'_id': mongoalertid},
{fields:{
events:0}
});
};
Template.attackerdetails.rendered = function() {
Deps.autorun(function(comp) {
//subscribe to the alerts data we need
Meteor.subscribe('attacker-details', Session.get('attackerID'),onReady=function(){
attackerAlerts=attackers.findOne({"_id":Session.get('attackerID')}).alerts;
//subscribe to each alert minus the event details since
//we already have sample events in the attacker data structure.
attackerAlerts.forEach(function(a){
Meteor.subscribe('alerts-details',a.alertid,false);
});
});
}); //end deps.autorun
};
};

Просмотреть файл

@ -1,81 +0,0 @@
<!--
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
Copyright (c) 2014 Mozilla Corporation
-->
<template name="attackers">
<!-- menu -->
<sidenav>
<form class="form-horizontal">
<div class="form-group">
<label class="control-label col-md-2" for="attackerLimit">Limit </label>
<div class="col-md-6">
<select name="attackerLimit" id="attackerLimit" class="form-control input-small"
title="limit how many attackers are retrieved">
<option value='5'>5</option>
<option value='10'>10</option>
<option value='15'>15</option>
<option value='20'>20</option>
<option value='25'>25</option>
<option value='30'>30</option>
<option value='35'>35</option>
<option value='40'>40</option>
</select>
</div>
</div>
<div class="form-group">
<label class="control-label col-md-2" for="attackersearchIP">IP</label>
<div class="col-md-8">
<input type="search" name="attackersearchIP" class="form-control" id="attackersearchIP"
placeholder="ip address regex search">
</div>
</div>
<div class="form-group">
<div class="col-xs-8 col-xs-offset-2">
<button class="btn btn-xs attackerssearch">search</button>
</div>
</div>
</form>
<div class="row reset-filter">
<button id="btnResetFilter" class="btn">Reset Filters</button>
</div>
<div class="col-md-6 filters-col">
<div class="row">
<div id="ringChart-category" class="text-center">
<h5 class="upperwhite" id="Categories">Categories:</h5>
</div>
</div>
<div class="row">
<div id="ringChart-lastseen" class="text-center">
<h5 class="upperwhite" id="LastSeen">Last Seen:</h5>
</div>
</div>
</div>
<div class="col-md-6 filters-col">
<div class="row">
<div id="ringChart-country" class="text-center">
<h5 class="upperwhite" id="Countries">Country:</h5>
</div>
</div>
<div class="row">
<div id="ringChart-ip" class="text-center">
<h5 class="upperwhite" id="IPs">IP Address:</h5>
</div>
</div>
</div>
</sidenav>
<div class="attackers-wrapper" id="attackers-wrapper">
<div id="bottom-toolbar">
<center>
<ul class="list-inline">
<li><button id="btnReset" class="btn btn-primary">Reset Layout</button></li>
<li><button id="btnWireFrame" class="btn btn-primary">WireFrame</button></li>
</ul>
</center>
</div>
{{>blockIPModal}}
</div>
</template>

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -23,10 +23,6 @@ import '/client/alertdetails.js';
import '/client/alertssummary.html';
import '/client/alertsummary.js';
import '/client/alertTableItem.js'
import '/client/attackerdetails.html';
import '/client/attackerdetails.js';
import '/client/attackers.html';
import '/client/attackers.js';
import '/client/blockFQDN.html';
import '/client/blockFQDN.js';
import '/client/blockIP.html';
@ -60,8 +56,6 @@ import '/client/manageAlertsTable.html';
import '/client/manageAlertsTable.js';
import '/client/mozdefhealth.html';
import '/client/mozdefhealth.js';
import '/client/nameplate.html';
import '/client/nameplate.js';
import '/client/verisTags.html';
import '/client/preferences.html';
import '/client/preferences.js'

Просмотреть файл

@ -62,9 +62,6 @@ Copyright (c) 2014 Mozilla Corporation
{{#if isFeature "logincounts"}}
<li><a href="/logincounts/">logincounts</a></li>
{{/if}}
{{#if isFeature "attackers"}}
<li><a href="/attackers">attackers</a></li>
{{/if}}
{{#if isFeature "globe"}}
<li><a href="/globe">globe</a></li>
{{/if}}

Просмотреть файл

@ -18,8 +18,6 @@ if ( Meteor.isClient ) {
Session.set( 'alertssearchtext', '' );
Session.set( 'alertssearchtime', '1 days' );
Session.set( 'alertsfiltertext', '' );
Session.set( 'attackerlimit', '10' );
Session.set( 'attackersearchIP', '' );
Session.set( 'blockIPipaddress', '' );
Session.set( 'blockFQDN', '' );
Session.set( 'watchItemwatchcontent', '' );
@ -191,16 +189,6 @@ if ( Meteor.isClient ) {
}
} );
UI.registerHelper( 'getAttackerURL', function( attackerid ) {
//return the router URL for a specific attacker
return ( getSetting( 'rootURL' ) + '/attacker/' + attackerid );
} );
UI.registerHelper( 'getAttackerIndicator', function( attackerid ) {
//return the first indicator from a specific attacker
return ( attackers.findOne( { '_id': attackerid } ).indicators[0].ipv4address );
} );
UI.registerHelper( 'isselected', function( optionvalue, datavalue ) {
if ( optionvalue == datavalue ) {
return 'selected'

Просмотреть файл

@ -1,13 +0,0 @@
<template name="nameplate">
<div class="row-fluid">
<span class="id">{{category}}</span>
</div>
<div class="row-fluid">
<ul class="details">
<li class="indicator">{{getAttackerIndicator _id}}</li>
<li>Last Seen: {{lastseentimestamp}}</li>
<li><a href="{{getAttackerURL _id}}" target="_blank">alerts: {{alertscount}}</a></li>
<li><a href="{{getAttackerURL _id}}" target="_blank">events: {{eventscount}}</a></li>
</ul>
</div>
</template>

Просмотреть файл

@ -1,17 +0,0 @@
/*
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at https://mozilla.org/MPL/2.0/.
Copyright (c) 2014 Mozilla Corporation
*/
if (Meteor.isClient) {
Template.nameplate.rendered = function() {
Deps.autorun(function(comp) {
//subscribe to the data we need
Meteor.subscribe('attackers-summary');
}); //end deps.autorun
};
};

Просмотреть файл

@ -142,26 +142,6 @@ Router.map(function() {
layoutTemplate: 'layout'
});
this.route('attackers', {
path: '/attackers',
template: 'attackers',
layoutTemplate: 'layout'
});
this.route('attackerdetails', {
path: '/attacker/:attackerid',
template: 'attackerdetails',
waitOn: function() {
Session.set('attackerID', this.params.attackerid);
return Meteor.subscribe('attacker-details', Session.get('attackerID'))
},
data: function() {
return attackers.findOne({ '_id': Session.get('attackerID') });
},
layoutTemplate: 'layout'
});
this.route('globe', {
path: '/globe',
template: 'globe',

Просмотреть файл

@ -62,9 +62,6 @@ Copyright (c) 2014 Mozilla Corporation
{{#if isFeature "logincounts"}}
<li><a href="/logincounts/">logincounts</a></li>
{{/if}}
{{#if isFeature "attackers"}}
<li><a href="/attackers">attackers</a></li>
{{/if}}
{{#if isFeature "globe"}}
<li><a href="/globe">globe</a></li>
{{/if}}

Просмотреть файл

@ -132,11 +132,6 @@ Copyright (c) 2014 Mozilla Corporation
<a href="/logincounts/">logincounts</a>
</li>
{{/if}}
{{#if isFeature "attackers"}}
<li>
<a href="/attackers">attackers</a>
</li>
{{/if}}
{{#if isFeature "globe"}}
<li>
<a href="/globe">globe</a>

Просмотреть файл

@ -25,7 +25,6 @@ Meteor.startup( () => {
healthescluster = new Mongo.Collection( "healthescluster" );
healthesnodes = new Mongo.Collection( "healthesnodes" );
healtheshotthreads = new Mongo.Collection( "healtheshotthreads" );
attackers = new Mongo.Collection( "attackers" );
actions = new Mongo.Collection( "actions" );
userActivity = new Mongo.Collection( "userActivity" );
ipblocklist = new Mongo.Collection( "ipblocklist" );
@ -219,33 +218,6 @@ Meteor.startup( () => {
} );
} );
Meteor.publish( "attacker-details", function( attackerid ) {
return attackers.find( { '_id': attackerid },
{
fields: {
events: { $slice: -20 },
alerts: { $slice: -10 }
},
sort: { 'events.documentsource.utctimestamp': -1 },
reactive: false
}
);
} );
Meteor.publish( "attackers-summary", function() {
//limit to the last 100 records by default
//to ease the sync transfer to dc.js/crossfilter
return attackers.find( {},
{
fields: {
events: 0,
alerts: 0,
},
sort: { lastseentimestamp: -1 },
limit: 100
} );
} );
Meteor.publish( "investigation-details", function( investigationid ) {
return investigations.find( { '_id': investigationid } );
} );
@ -321,13 +293,6 @@ Meteor.startup( () => {
fetch: ['creator']
} );
attackers.allow( {
update: function( userId, doc, fields, modifier ) {
// the user must be logged in
return ( userId );
}
} );
alerts.allow( {
update: function( userId, doc, fields, modifier ) {
// the user must be logged in

Просмотреть файл

@ -138,27 +138,6 @@ models = {
'lastModifier': ''
};
},
attacker: function() {
return {
'_id': uuid(),
'lastseentimestamp': today,
'firstseentimestamp': '',
'events': [],
'eventscount': 0,
'alerts': [],
'alertscount': 0,
'category': 'unknown',
'score': 0,
'geocoordinates': { 'countrycode': '', 'longitude': 0, 'lattitude': 0 },
'tags': [],
'notes': [],
'indicators': [],
'attackphase': 'unknown',
'datecreated': today,
'creator': '',
'lastModifier': ''
};
},
credential: function() {
return {

Просмотреть файл

@ -265,50 +265,6 @@ caption, legend {
border-radius: 6px 0 6px 6px;
}
.attackercallout {
width: 120px;
height: 160px;
box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
z-index: 99;
}
.attackercallout .id {
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .details {
text-align: left;
left: 2px;
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .blockip {
color: var(--txt-primary-color);
text-transform: uppercase;
margin-top: 20px;
}
.attackercallout ul {
list-style: none;
float: left;
left: auto;
margin: 0px;
padding: 0px;
}
.attackercallout .indicator {
color: yellow;
}
.attackercallout a {
color: yellow;
}
.veris-wrapper td {
color: black
}
@ -540,8 +496,6 @@ circle:hover {
margin: .5em;
}
/* attacker side nav pull out styling */
/* http://www.sitepoint.com/css3-sliding-menu/ */
sidenav {

Просмотреть файл

@ -258,50 +258,6 @@ legend {
display: none;
}
.attackercallout {
width: 120px;
height: 160px;
box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
z-index: 99;
}
.attackercallout .id {
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .details {
text-align: left;
left: 2px;
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .blockip {
color: #FFF;
text-transform: uppercase;
margin-top: 20px;
}
.attackercallout ul {
list-style: none;
float: left;
left: auto;
margin: 0px;
padding: 0px;
}
.attackercallout .indicator {
color: yellow;
}
.attackercallout a {
color: yellow;
}
.veris-wrapper td {
color: black
}

Просмотреть файл

@ -260,51 +260,6 @@ div.dc-chart {
border-radius: 6px 0 6px 6px;
}
.attackercallout {
width: 120px;
height: 160px;
box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
z-index: 99;
}
.attackercallout .id {
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .details {
text-align: left;
left: 2px;
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .blockip {
color: var(--txt-primary-color);
;
text-transform: uppercase;
margin-top: 20px;
}
.attackercallout ul {
list-style: none;
float: left;
left: auto;
margin: 0px;
padding: 0px;
}
.attackercallout .indicator {
color: yellow;
}
.attackercallout a {
color: yellow;
}
.veris-wrapper td {
color: black
}
@ -557,10 +512,6 @@ circle:hover {
margin: .5em;
}
/* attacker side nav pull out styling */
/* http://www.sitepoint.com/css3-sliding-menu/ */
sidenav {

Просмотреть файл

@ -263,52 +263,6 @@ footer .footer__link:hover svg {
display: none;
}
.attackercallout {
width: 120px;
height: 160px;
box-shadow: 0px 0px 12px rgba(0, 255, 255, 0.5);
opacity: .5;
background: black;
border: 1px solid rgba(127, 255, 255, 0.25);
text-align: center;
cursor: default;
z-index: 99;
}
.attackercallout .id {
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .details {
text-align: left;
left: 2px;
font-size: 12px;
color: rgba(127, 255, 255, 0.75);
}
.attackercallout .blockip {
color: #FFF;
text-transform: uppercase;
margin-top: 20px;
}
.attackercallout ul {
list-style: none;
float: left;
left: auto;
margin: 0px;
padding: 0px;
}
.attackercallout .indicator {
color: yellow;
}
.attackercallout a {
color: yellow;
}
.veris-wrapper td {
color: black
}

Просмотреть файл

@ -7,7 +7,6 @@ investigations /investigations
incidents /incidents
visualizations /visualizations
logincounts /logincounts
attackers /attackers
globe /globe
about /about
blockip /blockip