зеркало из https://github.com/mozilla/MozDef.git
Merge pull request #125 from netantho/averez-banhammer
BanHammer integration
This commit is contained in:
Коммит
8a0e6f09db
|
@ -20,9 +20,9 @@ Anthony Verez averez@mozilla.com
|
|||
<ul class="inline">
|
||||
<li><button id="btnReset" class="btn btn-primary">Reset Layout</button></li>
|
||||
<li><button id="btnWireFrame" class="btn btn-primary">WireFrame</button></li>
|
||||
<li><a id="btnBanhammer" class="btn btn-danger" href="">Banhammer <span id="banhammerIP"></span>!</a></li>
|
||||
</ul>
|
||||
</center>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
<!--
|
||||
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 http://mozilla.org/MPL/2.0/.
|
||||
Copyright (c) 2014 Mozilla Corporation
|
||||
|
||||
Contributors:
|
||||
Anthony Verez averez@mozilla.com
|
||||
-->
|
||||
|
||||
<!--new incident form -->
|
||||
<template name="banhammerform">
|
||||
<form id="banhammerform" class="form-horizontal" style="margin: 0px 30% 20px;">
|
||||
<legend>Banhammer</legend>
|
||||
<fieldset>
|
||||
<!-- IP addr -->
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="ipaddr">IP address or subnet (IPv6 supported, use addr/X for subnets)</label>
|
||||
<div class="controls">
|
||||
<input id="ipaddr" name="ipaddr" class="form-control" type="text" required>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Duration -->
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="duration">Duration</label>
|
||||
<div class="controls">
|
||||
<select id="duration" name="duration" class="form-control">
|
||||
<option value='1hr' selected>1 hour</option>
|
||||
<option value='12hr'>12 hours</option>
|
||||
<option value='1d'>1 day</option>
|
||||
<option value='1w'>1 week</option>
|
||||
<option value='30d'>30 days</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Comment -->
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="comment">Comment</label>
|
||||
<div class="controls">
|
||||
<input id="comment" name="comment" class="input-xlarge" type="text" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="bugid">Bug ID</label>
|
||||
<div class="controls">
|
||||
<input id="bugid" name="bugid" class="form-control" type="number" placeholder="optional" maxlength="7">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Button -->
|
||||
<div class="control-group">
|
||||
<label class="control-label" for="submit"></label>
|
||||
<div class="controls">
|
||||
<button id="submit" type="submit" name="submit" class="btn btn-danger submit">Banhammer now!</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</template>
|
|
@ -411,7 +411,7 @@ if (Meteor.isClient) {
|
|||
format: 'MM/DD/YYYY hh:mm:ss A',
|
||||
startDate: moment()
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
//add incident events
|
||||
Template.addincidentform.events({
|
||||
|
@ -433,6 +433,39 @@ if (Meteor.isClient) {
|
|||
|
||||
});
|
||||
|
||||
Template.banhammerform.rendered = function() {
|
||||
$('#ipaddr')[0].value = Session.get('banhammeripaddr');
|
||||
};
|
||||
|
||||
Template.banhammerform.events({
|
||||
"submit form": function(event, template) {
|
||||
event.preventDefault();
|
||||
var reporter = '';
|
||||
try {
|
||||
reporter = Meteor.user().profile.email;
|
||||
}
|
||||
catch(err) {
|
||||
reporter = 'test';
|
||||
}
|
||||
var ipaddr = $('#ipaddr')[0].value.split('/');
|
||||
var address = ipaddr[0];
|
||||
var cidr = 32;
|
||||
if (ipaddr.length == 2) {
|
||||
parseInt(ipaddr[1]);
|
||||
}
|
||||
var actionobj = {
|
||||
address: address,
|
||||
cidr: cidr,
|
||||
duration: $('#duration')[0].value,
|
||||
comment: $('#comment')[0].value,
|
||||
reporter: reporter,
|
||||
bugid: parseInt($('#bugid')[0].value)
|
||||
};
|
||||
Meteor.call('banhammer', actionobj);
|
||||
Router.go('/incidents/attackers');
|
||||
}
|
||||
});
|
||||
|
||||
//auto run to handle session variable changes
|
||||
Deps.autorun(function() {
|
||||
var message = Session.get('displayMessage');
|
||||
|
@ -777,6 +810,11 @@ if (Meteor.isClient) {
|
|||
}
|
||||
|
||||
},
|
||||
"click #btnBanhammer": function(event, template) {
|
||||
// TODO: modal with ipaddr, duration (dropdown), comment (text 1024 chars), bug (text 7 chars, optional)
|
||||
console.log("Banhammer!");
|
||||
console.log(event);
|
||||
},
|
||||
"mousedown": function(event,template){
|
||||
//if mouse is over a character
|
||||
//set the selected object
|
||||
|
@ -793,6 +831,13 @@ if (Meteor.isClient) {
|
|||
var intersects = raycaster.intersectObject( plane );
|
||||
offset.copy( intersects[ 0 ].point ).sub( plane.position );
|
||||
container.style.cursor = 'move';
|
||||
//console.log(selectedObject);
|
||||
if (getSetting('enableBanhammer')) {
|
||||
var attacker = attackers.findOne({_id: selectedObject.dbid})
|
||||
$("#banhammerIP")[0].textContent = attacker.sourceipaddress;
|
||||
$('#btnBanhammer')[0].href = '/incidents/banhammer/'+attacker.sourceipaddress;
|
||||
$("#btnBanhammer").show();
|
||||
}
|
||||
}
|
||||
},
|
||||
"mousemove": function(event,template){
|
||||
|
@ -868,6 +913,7 @@ if (Meteor.isClient) {
|
|||
|
||||
Template.attackers.rendered = function () {
|
||||
//console.log('entering draw attackers');
|
||||
$("#btnBanhammer").hide();
|
||||
scene = new THREE.Scene();
|
||||
scene.name='attackerScene';
|
||||
var clock = new THREE.Clock();
|
||||
|
|
|
@ -22,4 +22,5 @@ healthescluster = new Meteor.Collection("healthescluster");
|
|||
healthesnodes = new Meteor.Collection("healthesnodes");
|
||||
healtheshotthreads = new Meteor.Collection("healtheshotthreads");
|
||||
attackers = new Meteor.Collection("attackers");
|
||||
actions = new Meteor.Collection("actions");
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ elasticsearch = {
|
|||
mozdef = {
|
||||
rootURL: "https://localhost",
|
||||
port: "443",
|
||||
rootAPI: "http://localhost:8081"
|
||||
rootAPI: "http://localhost:8081",
|
||||
enableBanhammer: false
|
||||
}
|
||||
|
||||
|
|
|
@ -81,7 +81,14 @@ Router.map(function () {
|
|||
layoutTemplate: 'layout'
|
||||
});
|
||||
|
||||
|
||||
this.route('banhammer', {
|
||||
path: '/incidents/banhammer/:_ipaddr',
|
||||
template: 'banhammerform',
|
||||
data: function() {
|
||||
Session.set('banhammeripaddr', this.params._ipaddr);
|
||||
},
|
||||
layoutTemplate: 'layout'
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -11,7 +11,8 @@ Jeff Bryner jbryner@mozilla.com
|
|||
//public functions
|
||||
Meteor.methods({
|
||||
'saySomething': saySomething,
|
||||
'loadKibanaDashboards': loadKibanaDashboards
|
||||
'loadKibanaDashboards': loadKibanaDashboards,
|
||||
'banhammer': banhammer
|
||||
});
|
||||
|
||||
function saySomething() {
|
||||
|
@ -37,3 +38,13 @@ function loadKibanaDashboards() {
|
|||
}
|
||||
}
|
||||
|
||||
function banhammer(actionobj) {
|
||||
var banhammerRequest = HTTP.post(mozdef.rootAPI + '/banhammer', {data: actionobj});
|
||||
if (banhammerRequest.statusCode==200) {
|
||||
console.log(actionobj.address+"/"+actionobj.cidr+" banhammered for "+actionobj.duration);
|
||||
}
|
||||
else {
|
||||
console.log("Could not banhammer "+actionobj.address+"/"+actionobj.cidr+" for "+actionobj.duration);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
|
||||
import sys
|
||||
import bottle
|
||||
from bottle import debug,route, run, response, request, default_app
|
||||
from bottle import debug,route, run, response, request, default_app, post
|
||||
import json
|
||||
from configlib import getConfig, OptionParser
|
||||
import pyes
|
||||
|
@ -18,8 +18,12 @@ from datetime import datetime
|
|||
from datetime import timedelta
|
||||
from dateutil.parser import parse
|
||||
import pytz
|
||||
import MySQLdb
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
options = None
|
||||
dbcursor = None
|
||||
mysqlconn = None
|
||||
# cors decorator for rest/ajax
|
||||
|
||||
|
||||
|
@ -89,6 +93,16 @@ def index():
|
|||
return(kibanaDashboards())
|
||||
|
||||
|
||||
@post('/banhammer', methods=['POST'])
|
||||
@post('/banhammer/', methods=['POST'])
|
||||
@enable_cors
|
||||
def index():
|
||||
# try:
|
||||
return(banhammer(request.json))
|
||||
# except Exception as e:
|
||||
# sys.stderr.write('Error parsing json sent to POST /banhammer\n')
|
||||
|
||||
|
||||
#debug(True)
|
||||
def toUTC(suspectedDate, localTimeZone="US/Pacific"):
|
||||
'''make a UTC date out of almost anything'''
|
||||
|
@ -221,6 +235,51 @@ def kibanaDashboards():
|
|||
sys.stderr.write('Elastic Search server could not be reached, check network connectivity\n')
|
||||
|
||||
|
||||
def banhammer(action):
|
||||
try:
|
||||
# Look if attacker already in the DB, if yes get id
|
||||
dbcursor.execute("""SELECT id FROM blacklist_offender
|
||||
WHERE address = "%s" AND cidr = %d""" % (action['address'], int(action['cidr'])))
|
||||
qresult = dbcursor.fetchone()
|
||||
if not qresult:
|
||||
# insert new attacker in banhammer DB
|
||||
created_date = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
||||
dbcursor.execute("""
|
||||
INSERT INTO blacklist_offender(address, cidr, created_date, updated_date)
|
||||
VALUES ("%s", %d, '%s', '%s')
|
||||
""" % (action['address'], action['cidr'], created_date, created_date))
|
||||
# get the ID of this query
|
||||
dbcursor.execute("""SELECT id FROM blacklist_offender
|
||||
WHERE address = "%s" AND cidr = %d""" % (action['address'], int(action['cidr'])))
|
||||
(attacker_id,) = qresult
|
||||
# Compute start and end dates
|
||||
start_date = datetime.utcnow().strftime("%Y-%m-%d %H:%M:%S")
|
||||
end_date = datetime.utcnow() + timedelta(hours=1)
|
||||
if action['duration'] == '12hr':
|
||||
end_date = datetime.utcnow() + timedelta(hours=12)
|
||||
elif action['duration'] == '1d':
|
||||
end_date = datetime.utcnow() + timedelta(days=1)
|
||||
elif action['duration'] == '1w':
|
||||
end_date = datetime.utcnow() + timedelta(days=7)
|
||||
elif action['duration'] == '30d':
|
||||
end_date = datetime.utcnow() + timedelta(days=30)
|
||||
|
||||
if action['bugid']:
|
||||
# Insert in DB
|
||||
dbcursor.execute("""
|
||||
INSERT INTO blacklist_blacklist(offender_id, start_date, end_date, comment, reporter, bug_number, removed)
|
||||
VALUES (%d, "%s", "%s", "%s", "%s", %d, 0)
|
||||
""" % (attacker_id, start_date, end_date, action['comment'], action['reporter'], int(action['bugid'])))
|
||||
else:
|
||||
dbcursor.execute("""
|
||||
INSERT INTO blacklist_blacklist(offender_id, start_date, end_date, comment, reporter, removed)
|
||||
VALUES (%d, "%s", "%s", "%s", "%s", 0)
|
||||
""" % (attacker_id, start_date, end_date, action['comment'], action['reporter']))
|
||||
mysqlconn.commit()
|
||||
except Exception as e:
|
||||
sys.stderr.write('Error while banhammering %s/%d: %s\n' % (action['address'], action['cidr'], e))
|
||||
|
||||
|
||||
def initConfig():
|
||||
#change this to your default zone for when it's not specified
|
||||
options.defaultTimeZone = getConfig('defaulttimezone', 'US/Pacific',
|
||||
|
@ -229,6 +288,14 @@ def initConfig():
|
|||
options.configfile).split(','))
|
||||
options.kibanaurl = getConfig('kibanaurl', 'http://localhost:9090',
|
||||
options.configfile)
|
||||
options.banhammerdbhost = getConfig('banhammerdbhost', 'localhost',
|
||||
options.configfile)
|
||||
options.banhammerdbuser = getConfig('banhammerdbuser', 'root',
|
||||
options.configfile)
|
||||
options.banhammerdbpasswd = getConfig('banhammerdbpasswd', '',
|
||||
options.configfile)
|
||||
options.banhammerdbdb = getConfig('banhammerdbdb', 'banhammer',
|
||||
options.configfile)
|
||||
print(options)
|
||||
|
||||
|
||||
|
@ -239,6 +306,15 @@ if __name__ == "__main__":
|
|||
help="configuration file to use")
|
||||
(options, args) = parser.parse_args()
|
||||
initConfig()
|
||||
try:
|
||||
mysqlconn = MySQLdb.connect(
|
||||
host=options.banhammerdbhost,
|
||||
user=options.banhammerdbuser,
|
||||
passwd=options.banhammerdbpasswd,
|
||||
db=options.banhammerdbdb)
|
||||
dbcursor = mysqlconn.cursor()
|
||||
except Exception as e:
|
||||
sys.stderr.write('Failed to connect to the Banhammer DB\n')
|
||||
run(host="localhost", port=8081)
|
||||
else:
|
||||
parser = OptionParser()
|
||||
|
@ -247,4 +323,13 @@ else:
|
|||
help="configuration file to use")
|
||||
(options, args) = parser.parse_args()
|
||||
initConfig()
|
||||
try:
|
||||
mysqlconn = MySQLdb.connect(
|
||||
host=options.banhammerdbhost,
|
||||
user=options.banhammerdbuser,
|
||||
passwd=options.banhammerdbpasswd,
|
||||
db=options.banhammerdbdb)
|
||||
dbcursor = mysqlconn.cursor()
|
||||
except Exception as e:
|
||||
sys.stderr.write('Failed to connect to the Banhammer DB\n')
|
||||
application = default_app()
|
||||
|
|
Загрузка…
Ссылка в новой задаче