Merge pull request #323 from yashmehrotra/master

[Mozilla Winter of Security] 3D interactive Attack visualization via Landmass
This commit is contained in:
Jeff Bryner 2016-01-24 11:51:49 -08:00
Родитель 3519a84873 ab2cf9b6d3
Коммит 48a650f379
20 изменённых файлов: 2540 добавлений и 13 удалений

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

@ -417,7 +417,8 @@ def updateMongoWithESEvents(mozdefdb, results):
esrecord = dict(documentid=r['_id'],
documenttype=r['_type'],
documentindex=r['_index'],
documentsource=r['_source'])
documentsource=r['_source'],
read=False)
logger.debug('searching for ' + str(sourceIP))
#attacker = attackers.find_one({'events.details.sourceipaddress': str(sourceIP.ip)})

Двоичные данные
docs/source/images/AttacksLandmass.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 426 KiB

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

@ -61,6 +61,14 @@ to quickly filter attackers by category or timeframe and get easy access to rece
.. image:: images/AttackerOgres.png
3D interactive Attack visualization via Landmass
-------------------------------------
MozDef has a service-oriented visualization where you will get see various animations on a landmass service wise.
There are also options for handling attacks, and a sidebar which gives you detailed info into the attacks
.. image:: images/AttacksLandmass.png
Demo Instance
=============

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

@ -0,0 +1,583 @@
/**
* @author qiao / https://github.com/qiao
* @author mrdoob / http://mrdoob.com
* @author alteredq / http://alteredqualia.com/
* @author WestLangley / http://github.com/WestLangley
* @author erich666 / http://erichaines.com
*/
/*global THREE, console */
// This set of controls performs orbiting, dollying (zooming), and panning. It maintains
// the "up" direction as +Y, unlike the TrackballControls. Touch on tablet and phones is
// supported.
//
// Orbit - left mouse / touch: one finger move
// Zoom - middle mouse, or mousewheel / touch: two finger spread or squish
// Pan - right mouse, or arrow keys / touch: three finter swipe
//
// This is a drop-in replacement for (most) TrackballControls used in examples.
// That is, include this js file and wherever you see:
// controls = new THREE.TrackballControls( camera );
// controls.target.z = 150;
// Simple substitute "OrbitControls" and the control should work as-is.
THREE.OrbitControls = function ( object, domElement ) {
this.object = object;
this.domElement = ( domElement !== undefined ) ? domElement : document;
// API
// Set to false to disable this control
this.enabled = true;
// "target" sets the location of focus, where the control orbits around
// and where it pans with respect to.
this.target = new THREE.Vector3();
// center is old, deprecated; use "target" instead
this.center = this.target;
// This option actually enables dollying in and out; left as "zoom" for
// backwards compatibility
this.noZoom = false;
this.zoomSpeed = 1.0;
// Limits to how far you can dolly in and out
this.minDistance = 0;
this.maxDistance = Infinity;
// Set to true to disable this control
this.noRotate = false;
this.rotateSpeed = 1.0;
// Set to true to disable this control
this.noPan = false;
this.keyPanSpeed = 7.0; // pixels moved per arrow key push
// Set to true to automatically rotate around the target
this.autoRotate = false;
this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
// How far you can orbit vertically, upper and lower limits.
// Range is 0 to Math.PI radians.
this.minPolarAngle = 0; // radians
this.maxPolarAngle = Math.PI; // radians
// Set to true to disable use of the keys
this.noKeys = false;
// The four arrow keys
this.keys = { LEFT: 37, UP: 38, RIGHT: 39, BOTTOM: 40 };
////////////
// internals
var scope = this;
var EPS = 0.000001;
var rotateStart = new THREE.Vector2();
var rotateEnd = new THREE.Vector2();
var rotateDelta = new THREE.Vector2();
var panStart = new THREE.Vector2();
var panEnd = new THREE.Vector2();
var panDelta = new THREE.Vector2();
var dollyStart = new THREE.Vector2();
var dollyEnd = new THREE.Vector2();
var dollyDelta = new THREE.Vector2();
var phiDelta = 0;
var thetaDelta = 0;
var scale = 1;
var pan = new THREE.Vector3();
var lastPosition = new THREE.Vector3();
var STATE = { NONE : -1, ROTATE : 0, DOLLY : 1, PAN : 2, TOUCH_ROTATE : 3, TOUCH_DOLLY : 4, TOUCH_PAN : 5 };
var state = STATE.NONE;
// events
var changeEvent = { type: 'change' };
this.rotateLeft = function ( angle ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
}
thetaDelta -= angle;
};
this.rotateUp = function ( angle ) {
if ( angle === undefined ) {
angle = getAutoRotationAngle();
}
phiDelta -= angle;
};
// pass in distance in world space to move left
this.panLeft = function ( distance ) {
var panOffset = new THREE.Vector3();
var te = this.object.matrix.elements;
// get X column of matrix
panOffset.set( te[0], te[1], te[2] );
panOffset.multiplyScalar(-distance);
pan.add( panOffset );
};
// pass in distance in world space to move up
this.panUp = function ( distance ) {
var panOffset = new THREE.Vector3();
var te = this.object.matrix.elements;
// get Y column of matrix
panOffset.set( te[4], te[5], te[6] );
panOffset.multiplyScalar(distance);
pan.add( panOffset );
};
// main entry point; pass in Vector2 of change desired in pixel space,
// right and down are positive
this.pan = function ( delta ) {
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
if ( scope.object.fov !== undefined ) {
// perspective
var position = scope.object.position;
var offset = position.clone().sub( scope.target );
var targetDistance = offset.length();
// half of the fov is center to top of screen
targetDistance *= Math.tan( (scope.object.fov/2) * Math.PI / 180.0 );
// we actually don't use screenWidth, since perspective camera is fixed to screen height
scope.panLeft( 2 * delta.x * targetDistance / element.clientHeight );
scope.panUp( 2 * delta.y * targetDistance / element.clientHeight );
} else if ( scope.object.top !== undefined ) {
// orthographic
scope.panLeft( delta.x * (scope.object.right - scope.object.left) / element.clientWidth );
scope.panUp( delta.y * (scope.object.top - scope.object.bottom) / element.clientHeight );
} else {
// camera neither orthographic or perspective - warn user
console.warn( 'WARNING: OrbitControls.js encountered an unknown camera type - pan disabled.' );
}
};
this.dollyIn = function ( dollyScale ) {
if ( dollyScale === undefined ) {
dollyScale = getZoomScale();
}
scale /= dollyScale;
};
this.dollyOut = function ( dollyScale ) {
if ( dollyScale === undefined ) {
dollyScale = getZoomScale();
}
scale *= dollyScale;
};
this.update = function () {
var position = this.object.position;
var offset = position.clone().sub( this.target );
// angle from z-axis around y-axis
var theta = Math.atan2( offset.x, offset.z );
// angle from y-axis
var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
if ( this.autoRotate ) {
this.rotateLeft( getAutoRotationAngle() );
}
theta += thetaDelta;
phi += phiDelta;
// restrict phi to be between desired limits
phi = Math.max( this.minPolarAngle, Math.min( this.maxPolarAngle, phi ) );
// restrict phi to be betwee EPS and PI-EPS
phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
var radius = offset.length() * scale;
// restrict radius to be between desired limits
radius = Math.max( this.minDistance, Math.min( this.maxDistance, radius ) );
// move target to panned location
this.target.add( pan );
offset.x = radius * Math.sin( phi ) * Math.sin( theta );
offset.y = radius * Math.cos( phi );
offset.z = radius * Math.sin( phi ) * Math.cos( theta );
position.copy( this.target ).add( offset );
this.object.lookAt( this.target );
thetaDelta = 0;
phiDelta = 0;
scale = 1;
pan.set(0,0,0);
if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
this.dispatchEvent( changeEvent );
lastPosition.copy( this.object.position );
}
};
function getAutoRotationAngle() {
return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
}
function getZoomScale() {
return Math.pow( 0.95, scope.zoomSpeed );
}
function onMouseDown( event ) {
if ( scope.enabled === false ) { return; }
event.preventDefault();
if ( event.button === 0 ) {
if ( scope.noRotate === true ) { return; }
state = STATE.ROTATE;
rotateStart.set( event.clientX, event.clientY );
} else if ( event.button === 1 ) {
if ( scope.noZoom === true ) { return; }
state = STATE.DOLLY;
dollyStart.set( event.clientX, event.clientY );
} else if ( event.button === 2 ) {
if ( scope.noPan === true ) { return; }
state = STATE.PAN;
panStart.set( event.clientX, event.clientY );
}
// Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
scope.domElement.addEventListener( 'mousemove', onMouseMove, false );
scope.domElement.addEventListener( 'mouseup', onMouseUp, false );
}
function onMouseMove( event ) {
if ( scope.enabled === false ) return;
event.preventDefault();
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
if ( state === STATE.ROTATE ) {
if ( scope.noRotate === true ) return;
rotateEnd.set( event.clientX, event.clientY );
rotateDelta.subVectors( rotateEnd, rotateStart );
// rotating across whole screen goes 360 degrees around
scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
// rotating up and down along whole screen attempts to go 360, but limited to 180
scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
rotateStart.copy( rotateEnd );
} else if ( state === STATE.DOLLY ) {
if ( scope.noZoom === true ) return;
dollyEnd.set( event.clientX, event.clientY );
dollyDelta.subVectors( dollyEnd, dollyStart );
if ( dollyDelta.y > 0 ) {
scope.dollyIn();
} else {
scope.dollyOut();
}
dollyStart.copy( dollyEnd );
} else if ( state === STATE.PAN ) {
if ( scope.noPan === true ) return;
panEnd.set( event.clientX, event.clientY );
panDelta.subVectors( panEnd, panStart );
scope.pan( panDelta );
panStart.copy( panEnd );
}
// Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
scope.update();
}
function onMouseUp( /* event */ ) {
if ( scope.enabled === false ) return;
// Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
scope.domElement.removeEventListener( 'mousemove', onMouseMove, false );
scope.domElement.removeEventListener( 'mouseup', onMouseUp, false );
state = STATE.NONE;
}
function onMouseWheel( event ) {
if ( scope.enabled === false || scope.noZoom === true ) return;
var delta = 0;
if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
delta = event.wheelDelta;
} else if ( event.detail ) { // Firefox
delta = - event.detail;
}
if ( delta > 0 ) {
scope.dollyOut();
} else {
scope.dollyIn();
}
}
function onKeyDown( event ) {
if ( scope.enabled === false ) { return; }
if ( scope.noKeys === true ) { return; }
if ( scope.noPan === true ) { return; }
// pan a pixel - I guess for precise positioning?
// Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
var needUpdate = false;
switch ( event.keyCode ) {
case scope.keys.UP:
scope.pan( new THREE.Vector2( 0, scope.keyPanSpeed ) );
needUpdate = true;
break;
case scope.keys.BOTTOM:
scope.pan( new THREE.Vector2( 0, -scope.keyPanSpeed ) );
needUpdate = true;
break;
case scope.keys.LEFT:
scope.pan( new THREE.Vector2( scope.keyPanSpeed, 0 ) );
needUpdate = true;
break;
case scope.keys.RIGHT:
scope.pan( new THREE.Vector2( -scope.keyPanSpeed, 0 ) );
needUpdate = true;
break;
}
// Greggman fix: https://github.com/greggman/three.js/commit/fde9f9917d6d8381f06bf22cdff766029d1761be
if ( needUpdate ) {
scope.update();
}
}
function touchstart( event ) {
if ( scope.enabled === false ) { return; }
switch ( event.touches.length ) {
case 1: // one-fingered touch: rotate
if ( scope.noRotate === true ) { return; }
state = STATE.TOUCH_ROTATE;
rotateStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
break;
case 2: // two-fingered touch: dolly
if ( scope.noZoom === true ) { return; }
state = STATE.TOUCH_DOLLY;
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
var distance = Math.sqrt( dx * dx + dy * dy );
dollyStart.set( 0, distance );
break;
case 3: // three-fingered touch: pan
if ( scope.noPan === true ) { return; }
state = STATE.TOUCH_PAN;
panStart.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
break;
default:
state = STATE.NONE;
}
}
function touchmove( event ) {
if ( scope.enabled === false ) { return; }
event.preventDefault();
event.stopPropagation();
var element = scope.domElement === document ? scope.domElement.body : scope.domElement;
switch ( event.touches.length ) {
case 1: // one-fingered touch: rotate
if ( scope.noRotate === true ) { return; }
if ( state !== STATE.TOUCH_ROTATE ) { return; }
rotateEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
rotateDelta.subVectors( rotateEnd, rotateStart );
// rotating across whole screen goes 360 degrees around
scope.rotateLeft( 2 * Math.PI * rotateDelta.x / element.clientWidth * scope.rotateSpeed );
// rotating up and down along whole screen attempts to go 360, but limited to 180
scope.rotateUp( 2 * Math.PI * rotateDelta.y / element.clientHeight * scope.rotateSpeed );
rotateStart.copy( rotateEnd );
break;
case 2: // two-fingered touch: dolly
if ( scope.noZoom === true ) { return; }
if ( state !== STATE.TOUCH_DOLLY ) { return; }
var dx = event.touches[ 0 ].pageX - event.touches[ 1 ].pageX;
var dy = event.touches[ 0 ].pageY - event.touches[ 1 ].pageY;
var distance = Math.sqrt( dx * dx + dy * dy );
dollyEnd.set( 0, distance );
dollyDelta.subVectors( dollyEnd, dollyStart );
if ( dollyDelta.y > 0 ) {
scope.dollyOut();
} else {
scope.dollyIn();
}
dollyStart.copy( dollyEnd );
break;
case 3: // three-fingered touch: pan
if ( scope.noPan === true ) { return; }
if ( state !== STATE.TOUCH_PAN ) { return; }
panEnd.set( event.touches[ 0 ].pageX, event.touches[ 0 ].pageY );
panDelta.subVectors( panEnd, panStart );
scope.pan( panDelta );
panStart.copy( panEnd );
break;
default:
state = STATE.NONE;
}
}
function touchend( /* event */ ) {
if ( scope.enabled === false ) { return; }
state = STATE.NONE;
}
this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
this.domElement.addEventListener( 'mousedown', onMouseDown, false );
this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
this.domElement.addEventListener( 'DOMMouseScroll', onMouseWheel, false ); // firefox
this.domElement.addEventListener( 'keydown', onKeyDown, false );
this.domElement.addEventListener( 'touchstart', touchstart, false );
this.domElement.addEventListener( 'touchend', touchend, false );
this.domElement.addEventListener( 'touchmove', touchmove, false );
};
THREE.OrbitControls.prototype = Object.create( THREE.EventDispatcher.prototype );

944
meteor/app/client/js/zData.gui.min.js поставляемый Normal file

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -0,0 +1,166 @@
/* General styles for all menus */
.cbp-spmenu {
background: #47a3da;
position: fixed;
}
.cbp-spmenu h3 {
color: #afdefa;
font-size: 1.9em;
padding: 20px;
margin: 0;
font-weight: 300;
background: #0d77b6;
}
.cbp-spmenu a {
display: block;
color: #fff;
font-size: 1.1em;
font-weight: 300;
}
.cbp-spmenu a:hover {
background: #258ecd;
}
.cbp-spmenu a:active {
background: #afdefa;
color: #47a3da;
}
/* Orientation-dependent styles for the content of the menu */
.cbp-spmenu-vertical {
width: 240px;
height: 100%;
top: 0;
z-index: 1000;
}
.cbp-spmenu-vertical a {
border-bottom: 1px solid #258ecd;
padding: 1em;
}
.cbp-spmenu-horizontal {
width: 100%;
height: 150px;
left: 0;
z-index: 1000;
overflow: hidden;
}
.cbp-spmenu-horizontal h3 {
height: 100%;
width: 20%;
float: left;
}
.cbp-spmenu-horizontal a {
float: left;
width: 20%;
padding: 0.8em;
border-left: 1px solid #258ecd;
}
/* Vertical menu that slides from the left or right */
.cbp-spmenu-left {
left: -240px;
}
.cbp-spmenu-right {
right: -240px;
}
.cbp-spmenu-left.cbp-spmenu-open {
left: 0px;
}
.cbp-spmenu-right.cbp-spmenu-open {
right: 0px;
}
/* Horizontal menu that slides from the top or bottom */
.cbp-spmenu-top {
top: -150px;
}
.cbp-spmenu-bottom {
bottom: -150px;
}
.cbp-spmenu-top.cbp-spmenu-open {
top: 0px;
}
.cbp-spmenu-bottom.cbp-spmenu-open {
bottom: 0px;
}
/* Push classes applied to the body */
.cbp-spmenu-push {
overflow-x: hidden;
position: relative;
left: 0;
}
.cbp-spmenu-push-toright {
left: 240px;
}
.cbp-spmenu-push-toleft {
left: -240px;
}
/* Transitions */
.cbp-spmenu,
.cbp-spmenu-push {
-webkit-transition: all 0.3s ease;
-moz-transition: all 0.3s ease;
transition: all 0.3s ease;
}
/* Example media queries */
@media screen and (max-width: 55.1875em){
.cbp-spmenu-horizontal {
font-size: 75%;
height: 110px;
}
.cbp-spmenu-top {
top: -110px;
}
.cbp-spmenu-bottom {
bottom: -110px;
}
}
@media screen and (max-height: 26.375em){
.cbp-spmenu-vertical {
font-size: 90%;
width: 190px;
}
.cbp-spmenu-left,
.cbp-spmenu-push-toleft {
left: -190px;
}
.cbp-spmenu-right {
right: -190px;
}
.cbp-spmenu-push-toright {
left: 190px;
}
}

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

@ -0,0 +1,183 @@
/* General Demo Style */
@import url(http://fonts.googleapis.com/css?family=Lato:300,400,700);
@font-face {
font-family: 'fontawesome';
src:url('../fonts/fontawesome.eot');
src:url('../fonts/fontawesome.eot?#iefix') format('embedded-opentype'),
url('../fonts/fontawesome.svg#fontawesome') format('svg'),
url('../fonts/fontawesome.woff') format('woff'),
url('../fonts/fontawesome.ttf') format('truetype');
font-weight: normal;
font-style: normal;
}
body, html { font-size: 100%; padding: 0; margin: 0;}
/* Reset */
*,
*:after,
*:before {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
/* Clearfix hack by Nicolas Gallagher: http://nicolasgallagher.com/micro-clearfix-hack/ */
.clearfix:before,
.clearfix:after {
content: " ";
display: table;
}
.clearfix:after {
clear: both;
}
body {
font-family: 'Lato', Calibri, Arial, sans-serif;
color: #47a3da;
}
a {
color: #f0f0f0;
text-decoration: none;
}
a:hover {
color: #000;
}
.main,
.container > header {
width: 90%;
max-width: 69em;
margin: 0 auto;
padding: 0 1.875em 3.125em 1.875em;
}
.container > header {
padding: 2.875em 1.875em 1.875em;
}
.container > header h1 {
font-size: 2.125em;
line-height: 1.3;
margin: 0;
float: left;
font-weight: 400;
}
.container > header span {
display: block;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.5em;
padding: 0 0 0.6em 0.1em;
}
.container > header nav {
float: right;
}
.container > header nav a {
display: block;
float: left;
position: relative;
width: 2.5em;
height: 2.5em;
background: #fff;
border-radius: 50%;
color: transparent;
margin: 0 0.1em;
border: 4px solid #47a3da;
text-indent: -8000px;
}
.container > header nav a:after {
content: attr(data-info);
color: #47a3da;
position: absolute;
width: 600%;
top: 120%;
text-align: right;
right: 0;
opacity: 0;
pointer-events: none;
}
.container > header nav a:hover:after {
opacity: 1;
}
.container > header nav a:hover {
background: #47a3da;
}
.main > section {
max-width: 260px;
width: 90%;
margin: 0 auto;
}
.main > section h2 {
font-weight: 300;
color: #ccc;
}
.main > section button {
border: none;
background: #47a3da;
color: #fff;
padding: 1.5em;
display: block;
width: 100%;
cursor: pointer;
margin: 10px 0;
font-size: 0.8em;
}
.main > section button:hover {
background: #258ecd;
}
.main > section button.active {
background: #0d77b6;
}
.main > section button.disabled {
background: #aaa;
pointer-events: none;
}
.icon-drop:before,
.icon-arrow-left:before {
font-family: 'fontawesome';
position: absolute;
top: 0;
width: 100%;
height: 100%;
speak: none;
font-style: normal;
font-weight: normal;
line-height: 2;
text-align: center;
color: #47a3da;
-webkit-font-smoothing: antialiased;
text-indent: 8000px;
padding-left: 8px;
}
.container > header nav a:hover:before {
color: #fff;
}
.icon-drop:before {
content: "\e000";
}
.icon-arrow-left:before {
content: "\f060";
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -41,6 +41,7 @@ Anthony Verez averez@mozilla.com
<ul>
<li class="first"><a href="/logincounts/">logincounts</a></li>
<li><a href="/attackers">attackers</a></li>
<li><a href="/landmass">Landmass</a></li>
<li class="last"><a href="/globe">globe</a></li>
</ul>
</li>

73
meteor/app/client/vr.html Normal file
Просмотреть файл

@ -0,0 +1,73 @@
<!--
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
Jeff Bryner jeffbryner@gmail.com
Sanchit Kapoor sanchitlucknow@gmail.com
Avijit Gupta 526avijit@gmail.com
Yash Mehrotra yashmehrotra95@gmail.com
-->
<template name="vr">
<style>
body {
background: #6495ED;
overflow: hidden;
}
.blockip {
cursor: pointer;
margin-bottom: 16px;
}
#date {
font-size: 12px;
}
</style>
<div id="container"></div>
<nav class="vr-sidenav cbp-spmenu cbp-spmenu-vertical cbp-spmenu-right text-center" id="attack-sidenav">
<h3>Summary</h3>
<div id="filter-read-unread" class="filter-radios"> Filter Attacks:
<label>
<input type="radio" name="filter-type" class="filter-type" value="all" checked/>
All
</label>
<label>
<input type="radio" name="filter-type" class="filter-type" value="read"/>
Read
</label>
<label>
<input type="radio" name="filter-type" class="filter-type" value="unread"/>
Unread
</label>
</div>
<a id="attacks-host"><em>{{hostAttacks.host}}</em></a>
<a id="attacks-rank">Priority <em># {{displayIndex hostAttacks.rank}}</em></a>
<span id="specific-attack-details">
<i class="glyphicon glyphicon-chevron-left back-button"></i>
<h5>{{displayIndex index}}. {{attackDetails.category}}</h5>
<h5>Severity: {{attackDetails.severity}}</h5>
<h5>IP: {{attackDetails.details.sourceipv4address}}</h5>
<h5>Seen: <span id="date">{{displayDate attackDetails.timestamp}}</span></h5>
<h5 class="blockip btn" data-ipaddress={{attackDetails.details.sourceipv4address}}>BLOCK IP</h5><br/>
{{#if attackDetails.read}}
<input type="checkbox" class="cbox" name="attack-isread" checked/> Mark as Read
{{else}}
<input type="checkbox" class="cbox" name="attack-isread" /> Mark as Read
{{/if}}
</span>
<ul class="text-center" id="attacks-list">
{{#each hostAttacks.attacks}}
<li class="text-center attacks-list-item" data-index="{{index}}">{{displayIndex index}}. {{category}}</li>
{{/each}}
</ul>
</nav>
{{>blockIPModal}}
</template>

435
meteor/app/client/vr.js Normal file
Просмотреть файл

@ -0,0 +1,435 @@
/*
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:
Jeff Bryner jbryner@mozilla.com
Anthony Verez averez@mozilla.com
Sanchit Kapoor sanchitlucknow@gmail.com
Yash Mehrotra yashmehrotra95@gmail.com
Avijit Gupta 526avijit@gmail.com
*/
if (Meteor.isClient) {
var MESH_PROPERTIES = {
count: 4,
position: [
{x: 0, y: 0, z: 0},
{x: -800, y: -20, z: 0},
{x: -800, y: -20, z: -800},
{x: 0 , y: -20, z: -800}
],
rotationY: [
0,
0,
Math.PI/2,
Math.PI/2
]
};
var RANK_COORDINATES = [
{x: -286, z: -115},
{x: -15, z: 11},
{x: -234, z: 232},
{x: -69, z: -142},
{x: 124, z: 293},
{x: 153, z: -869},
{x: 124, z: -1122},
{x: -261, z: -1031},
{x: 87, z: -583},
{x: -288, z: -625},
{x: 265, z: -501},
{x: -850, z: -134},
{x: -1094, z: -74},
{x: -576, z: -190},
{x: -605, z: 98},
{x: -964, z: 293},
{x: -1084, z: -554},
{x: -899, z: -628},
{x: -589, z: -716},
{x: -992, z: -962},
{x: -754, z: -1087}
];
var ATTACK_ANIMATIONS = {
'broxss': Examples.smoke,
'brosqli': Examples.smoke,
'brotunnel': Examples.smoke,
};
var WIDTH = window.innerWidth;
var HEIGHT = window.innerHeight;
var SPEED = 0.01;
var OPENNAV = 'cbp-spmenu-open';
var geometry = null;
var scene = null;
var camera = null;
var renderer = null;
var material = null;
var json = null;
var controls = null;
var clock = null;
var mesh = null;
var spotlight = null;
var loader = null;
var projector = null;
var sceneObjects = [];
var attackedIds = 0;
var cssRenderer = null;
var intersectedObject = null;
var engine = null;
var enginesList = [];
var world = {};
var jsonData = {};
function init() {
Meteor.call('getVrJson', function(err, response) {
jsonData = JSON.parse(response);
initMeshes();
setCamera();
setLights();
setRenderers();
setStats();
document.getElementById("container").appendChild(renderer.domElement);
document.getElementById("container").appendChild(cssRenderer.domElement);
});
}
function initVariables() {
clock = new THREE.Clock();
scene = new THREE.Scene();
loader = new THREE.JSONLoader();
camera = new THREE.PerspectiveCamera(70, WIDTH / HEIGHT, 1, 10000);
sceneControls = new THREE.TrackballControls(camera);
spotLight = new THREE.SpotLight(0xffffff, 1);
renderer = new THREE.WebGLRenderer({ antialias: true });
projector = new THREE.Projector();
cssRenderer = new THREE.CSS3DRenderer();
controls = new THREE.OrbitControls(camera);
stats = new Stats();
Session.set('filterType', 'all');
}
function restartEngine(parameters, x, z) {
parameters.positionBase.x=x;
parameters.positionBase.z=z;
engine = new ParticleEngine();
engine.setValues(parameters);
engine.initialize(scene);
enginesList.push(engine);
}
function setStats() {
stats.domElement.style.position = 'absolute';
stats.domElement.style.bottom = '0px';
stats.domElement.style.zIndex = 100;
}
function setCamera() {
camera.position.set(-39.52908903855581, -4.352138336979161, 40.70626794923796);
var lookAt = { x: -30.52908903855581, y: -4.352138336979161, z: 37.70626794923796 };
camera.lookAt(lookAt);
}
function setRenderers() {
renderer.setSize(WIDTH, HEIGHT);
renderer.shadowMapEnabled = true; // enable shadows
cssRenderer.setSize(WIDTH, HEIGHT);
cssRenderer.domElement.style.position = 'absolute';
cssRenderer.domElement.style.top = 0;
}
function setLights() {
spotLight.position.set( 100, 10000, 100 );
scene.add(spotLight);
spotLight.castShadow = true;
}
function initMeshes() {
json = loader.parse(jsonData);
geometry = json.geometry;
material = new THREE.MeshPhongMaterial(json.materials);
for (var i = 0; i < MESH_PROPERTIES.count; i++) {
mesh = new THREE.Mesh(geometry, material);
mesh.scale.x = mesh.scale.y = mesh.scale.z = 50.75;
mesh.translation = THREE.GeometryUtils.center(geometry);
mesh.castShadow = true;
mesh.position.copy(MESH_PROPERTIES.position[i]);
mesh.rotation.y = MESH_PROPERTIES.rotationY[i];
scene.add(mesh);
}
}
function update() {
controls.update();
stats.update();
enginesList.forEach(function(engine) {
engine.update(0.01*0.5);
});
}
function render() {
requestAnimationFrame(render);
update();
renderer.render(scene, camera);
cssRenderer.render(scene, camera);
}
function getAttackers() {
Meteor.subscribe("attackers-summary-landmass", onReady = function() {
attackers.find().forEach(function(element) {
element.events.forEach(function(evt) {
var evtHost = evt.documentsource.details.host;
var doc = evt.documentsource;
doc.id = evt.documentid;
doc.read = evt.read || false;
if (evtHost == undefined) {
return;
}
if (Object.keys(world).length >=26) {
return;
}
if (world[evtHost]) {
world[evtHost].push(doc);
} else {
world[evtHost] = [doc];
world[evtHost].rank = attackedIds++;
}
});
});
var attacks = Object.keys(world).sort(function(prev, current) {
return world[current].length - world[prev].length;
});
attacks.forEach(function(host, index) {
var attackRank = world[host].rank;
// Create enclosing transparent sphere
var sphereGeometry = new THREE.SphereGeometry(70);
var sphereMaterial = new THREE.MeshBasicMaterial({ transparent: true, opacity: 0 });
var sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.x = RANK_COORDINATES[attackRank].x;
sphere.position.z = RANK_COORDINATES[attackRank].z;
sphere.name = "EnclosingSphere" + attackRank;
sphere.rank = attackRank;
sphere.host = host;
sphere.attacks = [];
world[host].forEach(function(attack) {
if (typeof attack === "object") {
attackType = attack.category;
sphere.attacks.push(attack);
if (Object.keys(ATTACK_ANIMATIONS).indexOf(attackType) > -1) {
mappedAttack = ATTACK_ANIMATIONS[attackType];
// Display animation
restartEngine(mappedAttack, RANK_COORDINATES[index].x, RANK_COORDINATES[index].z);
}
}
});
sceneObjects.push(sphere);
scene.add(sphere);
});
});
}
Template.vr.created = function () {
initVariables();
};
Template.vr.rendered = function () {
init();
render();
getAttackers();
};
Template.vr.helpers({
hostAttacks: function() {
var hostAttacks = Session.get('hostAttacks');
var isReadOrUnread = Session.get('filterType');
var filteredAttacks = { attacks: [] };
if (hostAttacks) {
filteredAttacks.rank = hostAttacks.rank;
filteredAttacks.host = hostAttacks.host;
hostAttacks.attacks.forEach(function(attack, index) {
attack.index = index;
if (isReadOrUnread === 'read' && attack.read) {
filteredAttacks.attacks.push(attack);
}
else if (isReadOrUnread === 'unread' && !attack.read) {
filteredAttacks.attacks.push(attack);
}
else if (isReadOrUnread === 'all') {
filteredAttacks.attacks.push(attack);
}
});
return filteredAttacks;
}
},
attackDetails: function() {
return Session.get('attackDetails');
},
displayIndex: function(index) {
return index + 1
},
displayDate: function(date) {
var MM = {Jan:"January", Feb:"February", Mar:"March", Apr:"April",
May:"May", Jun:"June", Jul:"July", Aug:"August", Sep:"September",
Oct:"October", Nov:"November", Dec:"December"};
var parsed_date = String(new Date(date)).replace(
/\w{3} (\w{3}) (\d{2}) (\d{4}) (\d{2}):(\d{2}):[^(]+\(([A-Z]{3})\)/,
function($0,$1,$2,$3,$4,$5,$6){
return MM[$1]+" "+$2+", "+$3+" - "+$4%12+":"+$5+(+$4>12?"PM":"AM")+" "+$6
}
);
return parsed_date
}
});
Template.vr.events({
"click #container": function(e) {
var mouse = {
x: (e.clientX / WIDTH)*2 - 1,
y: (e.clientY / HEIGHT)*2 - 1
};
var mouseVector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
projector.unprojectVector(mouseVector, camera);
var raycaster = new THREE.Raycaster(camera.position, mouseVector.sub( camera.position).normalize() );
var intersects = raycaster.intersectObjects(sceneObjects, true);
var sideNav = $('#attack-sidenav');
if (intersects.length) {
intersects.forEach(function(intersect) {
var attackRank = intersect.object.rank;
var attackRegion = intersect.object.host;
var attacks = intersect.object.attacks;
if (typeof attackRank !== "undefined") {
var sessionAttackObj = {
host: attackRegion,
rank: attackRank,
attacks: attacks
};
Session.set('hostAttacks', sessionAttackObj);
// Open the nav if not already opened
if (!sideNav.hasClass(OPENNAV)) {
sideNav.addClass(OPENNAV);
}
if (Session.get('showDetailedAttack')) {
$('#specific-attack-details').slideToggle();
$('#attacks-list').slideToggle();
Session.set('showDetailedAttack', false);
}
}
});
}
else if(sideNav.hasClass(OPENNAV)) {
sideNav.removeClass(OPENNAV);
}
},
"mousemove": function(e) {
var mouse = {
x: (e.clientX / WIDTH)*2 - 1,
y: (e.clientY / HEIGHT)*2 - 1
};
var mouseVector = new THREE.Vector3(mouse.x, mouse.y, 0.5);
projector.unprojectVector(mouseVector, camera);
var raycaster = new THREE.Raycaster(camera.position, mouseVector.sub( camera.position).normalize());
var intersects = raycaster.intersectObjects(sceneObjects, true);
$('body').removeClass('mousepointer');
if (intersects.length) {
intersects.forEach(function(intersect) {
var attackRank = intersect.object.rank;
if (typeof attackRank !== "undefined") {
$('body').addClass('mousepointer');
}
});
}
},
"change .cbox": function(event) {
var isChecked = $('.cbox').is(':checked');
var attackId = Session.get('attackDetails').id;
var setModifier = { $set: {}};
var element = attackers.findOne({"events.documentid": attackId});
element.events.forEach(function(evt, index) {
if (evt.documentid === attackId) {
setModifier.$set['events.' + index + '.read'] = isChecked;
attackers.update({'_id': element._id}, setModifier);
var hostAttacks = Session.get('hostAttacks');
hostAttacks.attacks.forEach(function(attack) {
if (attack.id === attackId) {
attack.read = isChecked;
}
});
Session.set('hostAttacks', hostAttacks);
}
});
},
"change .filter-type": function (event) {
Session.set('filterType', $('.filter-radios input[name=filter-type]:checked').val());
// filterAttacksType();
},
"click .attacks-list-item": function(event) {
var attackIndex = event.target.getAttribute('data-index');
var hostName = document.getElementById('attacks-host').innerText;
var attackDetails = world[hostName][attackIndex];
Session.set('attackDetails', attackDetails);
Session.set('showDetailedAttack', true);
slideToggle();
},
"click .back-button": function() {
slideToggle();
},
"click .blockip": function(e,t) {
Session.set('blockIPipaddress',($(e.target).attr('data-ipaddress')));
//disable and hook to re-enable the scene controls so they don't grab the mouse and use it
sceneControls.enabled = false;
controls.enabled = false;
$('#modalBlockIPWindow').on('hidden', function () {
sceneControls.enabled=true;
controls.enabled = true;
});
$('#modalBlockIPWindow').modal();
},
});
Template.vr.destroyed = function () {
container.removeChild(renderer.domElement);
scene = null;
camera = null;
renderer = null;
WIDTH = window.innerWidth;
HEIGHT = window.innerHeight;
SPEED = 0.01;
};
function slideToggle() {
$('#specific-attack-details').slideToggle();
$('#attacks-list').slideToggle();
$('#filter-read-unread').slideToggle();
}
}

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

@ -7,7 +7,7 @@ Copyright (c) 2014 Mozilla Corporation
Contributors:
Jeff Bryner jbryner@mozilla.com
Anthony Verez averez@mozilla.com
Yash Mehrotra yashmehrotra95@gmail.com
*/
//collections shared by client/server
@ -199,6 +199,15 @@ if (Meteor.isServer) {
limit:100});
});
Meteor.publish("attackers-summary-landmass", function () {
//limit to the last 100 records by default
//to ease the sync transfer to dc.js/crossfilter
var inModifier = { $in: ["broxss", "brotunnel", "brosqli"]};
return attackers.find({"events.documentsource.category": inModifier},
{sort: {lastseentimestamp: -1},
limit: 100});
});
Meteor.publish("investigations-summary", function () {
return investigations.find({},
{fields: {

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

@ -186,4 +186,10 @@ Router.map(function () {
template:'veristags',
layoutTemplate: 'layout'
});
this.route('vr', {
path: '/landmass',
template: 'vr',
layoutTemplate: 'layout'
});
});

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

@ -6,6 +6,7 @@ Copyright (c) 2014 Mozilla Corporation
Contributors:
Jeff Bryner jbryner@mozilla.com
Avijit Gupta 526avijit@gmail.com
*/
if (Meteor.isServer) {
@ -20,7 +21,8 @@ if (Meteor.isServer) {
'ipintel': ipintel,
'verisstats': verisstats,
'logincounts': logincounts,
'getplugins': getplugins
'getplugins': getplugins,
'getVrJson': getVrJson
});
function saySomething() {
@ -146,4 +148,9 @@ if (Meteor.isServer) {
}
return response
}
function getVrJson() {
var response = Assets.getText('vr.config.json');
return response;
}
};

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

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

@ -6,6 +6,7 @@ Copyright (c) 2014 Mozilla Corporation
Contributors:
Jeff Bryner jbryner@mozilla.com
Avijit Gupta 526avijit@gmail.com
*/
/*base css */
@ -90,6 +91,30 @@ caption, legend {
line-height: 13px;
}
.attackshoverboard {
/*width: 500px;*/
/*height: 500px;*/
/*background-color: green;*/
-moz-transform: scaleY(-1);
-webkit-transform: scaleY(-1);
-o-transform: scaleY(-1);
transform: scaleY(-1);
display: none;
}
.dropdown-submenu{position:relative;}
.dropdown-submenu>.dropdown-menu{top:0;left:100%;-webkit-border-radius:0 6px 6px 6px;-moz-border-radius:0 6px 6px 6px;border-radius:0 6px 6px 6px;}
.dropdown-submenu:active>.dropdown-menu, .dropdown-submenu:hover>.dropdown-menu {
display: block;
right:162px;
}
.dropdown-submenu>a:after{display:block;content:" ";float:right;width:0;height:0;border-color:transparent;border-style:solid;border-width:5px 0 5px 5px;border-left-color:#cccccc;margin-top:5px;margin-right:-10px;}
.dropdown-submenu:active>a:after{border-left-color:#ffffff;}
.dropdown-submenu.pull-left{float:none;}.dropdown-submenu.pull-left>.dropdown-menu{left:-100%;margin-left:10px;-webkit-border-radius:6px 0 6px 6px;-moz-border-radius:6px 0 6px 6px;border-radius:6px 0 6px 6px;}
.attackercallout {
width: 120px;
height: 160px;
@ -140,7 +165,6 @@ caption, legend {
background-color: rgba(245,245,245,.7)
}
/*bootstrap overrides*/
.btn {
@ -175,16 +199,9 @@ input[type="search"] {
}
td{
color:white;
color:white;
}
.brightURL{
color:white;
}
.brightURL:hover{
color:white;
}
.welcome {
text-align: center;
@ -195,7 +212,7 @@ td{
}
/*login ui css to hide the local account/password signup options */
/* uncomment this login ui css to hide the local account/password signup options
.logins-wrapper .svgtextlabel {
font-size: 20px;
color: white;
@ -213,6 +230,11 @@ td{
.or {
display: none;
}
*/
/* don't float the 'create account' link*/
#login-buttons #signup-link{
float: none;
}
/* d3 circle styles */
.successcircle{
@ -515,5 +537,51 @@ circle:hover{
padding: 8px 10px;
}
.vr-sidenav {
color: white;
}
.vr-sidenav .filter-radios label:nth-child(1) {
margin-top: 5px;
}
.vr-sidenav .filter-radios label {
display: block;
text-align: left;
padding-left: 33%;
}
.vr-sidenav #specific-attack-details {
display: none;
}
.vr-sidenav .back-button {
position: absolute;
left: 5px;
top: 5px;
color: white;
font-size: 18px;
}
.vr-sidenav .back-button:hover {
cursor: pointer;
}
.vr-sidenav #attacks-list {
list-style: none;
color: white;
margin-left: -40px;
}
.vr-sidenav #attacks-list .attacks-list-item {
padding: 5px;
}
.vr-sidenav #attacks-list .attacks-list-item:hover {
cursor: pointer;
text-decoration: underline;
}
.mousepointer {
cursor: pointer;
}

Двоичные данные
meteor/public/images/cloud.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 80 KiB

Двоичные данные
meteor/public/images/raindrop2flip.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 667 B

Двоичные данные
meteor/public/images/smokeparticle.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 15 KiB

Двоичные данные
meteor/public/images/star.png Normal file

Двоичный файл не отображается.

После

Ширина:  |  Высота:  |  Размер: 380 B