Merge pull request #125 from netantho/averez-banhammer

BanHammer integration
This commit is contained in:
jeffbryner 2014-06-27 10:56:25 -07:00
Родитель 6ca4a9644b 9e2c8c95e2
Коммит 8a0e6f09db
8 изменённых файлов: 217 добавлений и 6 удалений

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

@ -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()