Projects STRLCPY LogonTracer Commits 2025b65e
🤬
  • Updated timeline view

    Changed timeline view to the new tab.
    Added method to search by clicking accounts.
  • Loading...
  • shusei tomonaga committed 6 years ago
    2025b65e
    1 parent aa955293
Revision indexing in progress... (symbol navigation in revisions will be accurate after indexed)
  • ■ ■ ■ ■ ■
    .gitignore
    1  -static/*
    2  -!.gitkeep
     1 +*.pyc
     2 +*~
     3 +*.bak
    3 4   
  • ■ ■ ■ ■ ■ ■
    logontracer.py
    skipped 135 lines
    136 136   return render_template("index.html", server_ip=NEO4J_SERVER, neo4j_password=NEO4J_PASSWORD, neo4j_user=NEO4J_USER)
    137 137   
    138 138   
     139 +# Timeline view
     140 +@app.route('/timeline')
     141 +def timeline():
     142 + return render_template("timeline.html", server_ip=NEO4J_SERVER, neo4j_password=NEO4J_PASSWORD, neo4j_user=NEO4J_USER)
     143 + 
     144 + 
    139 145  # Web application logs
    140 146  @app.route('/log')
    141 147  def logs():
    skipped 386 lines
  • ■ ■ ■ ■ ■
    static/.gitkeep
    1  - 
  • ■ ■ ■ ■ ■ ■
    static/script.js
     1 +function buildGraph(graph, path) {
     2 + for (idx in path) {
     3 + if (Object.keys(path[idx]).length == 3) {
     4 + objid = parseInt(path[idx].identity.low) + 100;
     5 + } else {
     6 + objid = parseInt(path[idx].identity.low) + 1000;
     7 + }
     8 + 
     9 + // Node
     10 + if (Object.keys(path[idx]).length == 3) {
     11 + var ndupflg = false;
     12 + for (nidx in graph.nodes) {
     13 + if (graph.nodes[nidx].data.objid == objid) {
     14 + ndupflg = true;
     15 + }
     16 + }
     17 + if (ndupflg) {
     18 + continue;
     19 + }
     20 + 
     21 + if (path[idx].labels[0] == "Username") {
     22 + nname = path[idx].properties.user
     23 + nfsize = "10"
     24 + nshape = "ellipse"
     25 + nwidth = "25"
     26 + nheight = "25"
     27 + ntype = "User"
     28 + if (path[idx].properties.rights == "system") {
     29 + ncolor = "#ff0000"
     30 + nbcolor = "#ffc0cb"
     31 + nfcolor = "#ff69b4"
     32 + nprivilege = "SYSTEM"
     33 + } else {
     34 + ncolor = "#0000cd"
     35 + nbcolor = "#cee1ff"
     36 + nfcolor = "#6da0f2"
     37 + nprivilege = "Normal"
     38 + }
     39 + }
     40 + if (path[idx].labels[0] == "IPAddress") {
     41 + nname = path[idx].properties.IP
     42 + nshape = "diamond"
     43 + nwidth = "25"
     44 + nheight = "25"
     45 + nfsize = "8"
     46 + ncolor = "#2e8b57"
     47 + nbcolor = "#98fb98"
     48 + nfcolor = "#3cb371"
     49 + ntype = "Host"
     50 + }
     51 + graph.nodes.push({
     52 + "data": {
     53 + "id": objid,
     54 + "objid": objid,
     55 + "nlabel": nname,
     56 + "ncolor": ncolor,
     57 + "nbcolor": nbcolor,
     58 + "nfcolor": nfcolor,
     59 + "nwidth": nwidth,
     60 + "nheight": nheight,
     61 + "nfsize": nfsize,
     62 + "nshape": nshape,
     63 + "label": path[idx].labels[0],
     64 + "nprivilege": nprivilege,
     65 + "ntype": ntype,
     66 + "nsid": path[idx].properties.sid
     67 + }
     68 + });
     69 + } else {
     70 + // Relationship
     71 + var ldupflg = false;
     72 + var label_count = document.getElementById("label-count").checked;
     73 + var label_type = document.getElementById("label-type").checked;
     74 + var label_status = document.getElementById("label-status").checked;
     75 + var ename = path[idx].properties.id.low;
     76 + if (label_count) {
     77 + ename += " : " + path[idx].properties.count.low;
     78 + }
     79 + if (label_type) {
     80 + ename += " : " + path[idx].properties.logintype;
     81 + }
     82 + if (label_status) {
     83 + ename += " : " + path[idx].properties.status;
     84 + }
     85 + for (nidx in graph.edges) {
     86 + if (graph.edges[nidx].data.objid == objid) {
     87 + ldupflg = true;
     88 + }
     89 + }
     90 + if (ldupflg) {
     91 + continue;
     92 + }
     93 + graph.edges.push({
     94 + "data": {
     95 + "id": objid,
     96 + "source": parseInt(path[parseInt(idx) - 1].identity.low) + 100,
     97 + "target": parseInt(path[parseInt(idx) + 1].identity.low) + 100,
     98 + "objid": objid,
     99 + "elabel": ename,
     100 + "label": path[idx].type,
     101 + "distance": 5,
     102 + "ntype": "edge",
     103 + "eid": path[idx].properties.id.low,
     104 + "count": path[idx].properties.count.low,
     105 + "logontype": path[idx].properties.logintype,
     106 + "status": path[idx].properties.status
     107 + }
     108 + });
     109 + }
     110 + }
     111 + 
     112 + return (graph);
     113 +}
     114 + 
     115 +function drawGraph(graph, rootNode) {
     116 + var flagGrid = document.getElementById("modeGrid").checked;
     117 + var flagCose = document.getElementById("modeCose").checked;
     118 + var flagCircle = document.getElementById("modeCircle").checked;
     119 + var flagMode = "";
     120 + 
     121 + if (flagGrid) {
     122 + flagMode = "grid";
     123 + }
     124 + if (flagCose) {
     125 + flagMode = "cose";
     126 + }
     127 + if (flagCircle) {
     128 + flagMode = "circle";
     129 + }
     130 + 
     131 + cy = cytoscape({
     132 + container: document.getElementById("cy"),
     133 + boxSelectionEnabled: false,
     134 + style: cytoscape.stylesheet()
     135 + .selector('node').css({
     136 + "content": "data(nlabel)",
     137 + "width": "data(nwidth)",
     138 + "height": "data(nheight)",
     139 + "color": "data(ncolor)",
     140 + "font-size": "data(nfsize)",
     141 + "background-color": "data(nbcolor)",
     142 + "border-color": "data(nfcolor)",
     143 + "border-style": "solid",
     144 + "border-width": 3,
     145 + "text-valign": "center",
     146 + "text-outline-width": 1,
     147 + "text-outline-color": "data(nbcolor)",
     148 + "shape": "data(nshape)"
     149 + })
     150 + .selector(':selected').css({
     151 + "width": 25,
     152 + "height": 25,
     153 + "border-width": 4,
     154 + "border-color": "#404040"
     155 + })
     156 + .selector('edge').css({
     157 + "content": "data(elabel)",
     158 + "font-size": "8",
     159 + "curve-style": "bezier",
     160 + "target-arrow-shape": "triangle",
     161 + "width": 2,
     162 + "line-color": "#ddd",
     163 + "target-arrow-color": "#ddd"
     164 + })
     165 + .selector('.highlighted').css({
     166 + "background-color": "#61bffc",
     167 + "line-color": "#61bfcc",
     168 + "transition-property": "background-color, line-color, target-arrow-color",
     169 + "transition-duration": "0.5s"
     170 + }),
     171 + elements: graph,
     172 + layout: {
     173 + name: flagMode,
     174 + directed: true,
     175 + roots: rootNode,
     176 + animate: true,
     177 + padding: 10
     178 + }
     179 + });
     180 + 
     181 + cy.nodes().forEach(function(ele) {
     182 + ele.qtip({
     183 + content: {
     184 + title: "<b>Node Details</b>",
     185 + text: qtipNode(ele)
     186 + },
     187 + style: {
     188 + classes: "qtip-bootstrap"
     189 + },
     190 + position: {
     191 + my: "top center",
     192 + at: "bottom center",
     193 + target: ele
     194 + }
     195 + });
     196 + });
     197 + 
     198 + cy.edges().forEach(function(ele) {
     199 + ele.qtip({
     200 + content: {
     201 + title: "<b>Event Details</b>",
     202 + text: qtipEdge(ele)
     203 + },
     204 + style: {
     205 + classes: "qtip-bootstrap"
     206 + },
     207 + position: {
     208 + my: "top center",
     209 + at: "bottom center",
     210 + target: ele
     211 + }
     212 + });
     213 + });
     214 +}
     215 + 
     216 +function qtipNode(ndata) {
     217 + var qtext = 'Name: ' + ndata._private.data["nlabel"];
     218 + if (ndata._private.data["ntype"] == "User") {
     219 + qtext += '<br>Privilege: ' + ndata._private.data["nprivilege"];
     220 + qtext += '<br>SID: ' + ndata._private.data["nsid"];
     221 + }
     222 + qtext += '<br><button type="button" class="btn btn-primary btn-xs" onclick="createRankQuery(\'' + ndata._private.data["nlabel"] + '\',\'' + ndata._private.data["ntype"] + '\')">search</button>';
     223 + 
     224 + return qtext;
     225 +}
     226 + 
     227 +function qtipEdge(ndata) {
     228 + var qtext = "";
     229 + if (ndata._private.data["eid"] == 4624) {
     230 + qtext = "<b>Successful logon</b><br>";
     231 + }
     232 + if (ndata._private.data["eid"] == 4625) {
     233 + qtext = "<b>Logon failure</b><br>";
     234 + }
     235 + if (ndata._private.data["eid"] == 4768) {
     236 + qtext = "<b>Kerberos Authentication (TGT Request)</b><br>";
     237 + }
     238 + if (ndata._private.data["eid"] == 4769) {
     239 + qtext = "<b>Kerberos Service Ticket (ST Request)</b><br>";
     240 + }
     241 + if (ndata._private.data["eid"] == 4776) {
     242 + qtext = "<b>NTLM Authentication</b><br>";
     243 + }
     244 + qtext += "Count: " + ndata._private.data["count"];
     245 + qtext += "<br>Logon Type: " + ndata._private.data["logontype"];
     246 + qtext += "<br>Status: " + ndata._private.data["status"];
     247 + return qtext;
     248 +}
     249 + 
     250 +function createAllQuery() {
     251 + eidStr = getQueryID();
     252 + eidStr = eidStr.slice(4);
     253 + queryStr = 'MATCH (user)-[event]-(ip) WHERE ' + eidStr + ' RETURN user, event, ip';
     254 + //console.log(queryStr);
     255 + executeQuery(queryStr);
     256 +}
     257 + 
     258 +function createSystemQuery() {
     259 + eidStr = getQueryID();
     260 + queryStr = 'MATCH (user)-[event]-(ip) WHERE user.rights = "system" ' + eidStr + ' RETURN user, event, ip';
     261 + //console.log(queryStr);
     262 + executeQuery(queryStr);
     263 +}
     264 + 
     265 +function createRDPQuery() {
     266 + eidStr = getQueryID();
     267 + queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 10 ' + eidStr + ' RETURN user, event, ip';
     268 + //console.log(queryStr);
     269 + executeQuery(queryStr);
     270 +}
     271 + 
     272 +function createNetQuery() {
     273 + eidStr = getQueryID();
     274 + queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 3 ' + eidStr + ' RETURN user, event, ip';
     275 + //console.log(queryStr);
     276 + executeQuery(queryStr);
     277 +}
     278 + 
     279 +function createBatchQuery() {
     280 + eidStr = getQueryID();
     281 + queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 4 ' + eidStr + ' RETURN user, event, ip';
     282 + //console.log(queryStr);
     283 + executeQuery(queryStr);
     284 +}
     285 + 
     286 +function createServiceQuery() {
     287 + eidStr = getQueryID();
     288 + queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 5 ' + eidStr + ' RETURN user, event, ip';
     289 + //console.log(queryStr);
     290 + executeQuery(queryStr);
     291 +}
     292 + 
     293 +function create14068Query() {
     294 + queryStr = 'MATCH (user)-[event]-(ip) WHERE event.status = "0xf" AND event.id = 4769 RETURN user, event, ip'
     295 + //console.log(queryStr);
     296 + executeQuery(queryStr);
     297 +}
     298 + 
     299 +function createFailQuery() {
     300 + queryStr = 'MATCH (user)-[event]-(ip) WHERE event.id = 4625 RETURN user, event, ip'
     301 + //console.log(queryStr);
     302 + executeQuery(queryStr);
     303 +}
     304 + 
     305 +function createRankQuery(setStr, qType) {
     306 + if (qType == "User") {
     307 + whereStr = 'user.user = "' + setStr + '" ';
     308 + }
     309 + if (qType == "Host") {
     310 + whereStr = 'ip.IP = "' + setStr + '" ';
     311 + }
     312 + 
     313 + eidStr = getQueryID()
     314 + 
     315 + queryStr = 'MATCH (user)-[event]-(ip) WHERE (' + whereStr + ') ' + eidStr + ' RETURN user, event, ip';
     316 + //console.log(queryStr);
     317 + executeQuery(queryStr);
     318 +}
     319 + 
     320 +function getQueryID() {
     321 + var id4624Ch = document.getElementById("id4624").checked;
     322 + var id4625Ch = document.getElementById("id4625").checked;
     323 + var id4768Ch = document.getElementById("id4768").checked;
     324 + var id4769Ch = document.getElementById("id4769").checked;
     325 + var id4776Ch = document.getElementById("id4776").checked;
     326 + var countInt = document.getElementById("count-input").value;
     327 + var eidStr = "AND ("
     328 + if (id4624Ch) {
     329 + eidStr = eidStr + "event.id = 4624 OR ";
     330 + }
     331 + if (id4625Ch) {
     332 + eidStr = eidStr + "event.id = 4625 OR ";
     333 + }
     334 + if (id4768Ch) {
     335 + eidStr = eidStr + "event.id = 4768 OR ";
     336 + }
     337 + if (id4769Ch) {
     338 + eidStr = eidStr + "event.id = 4769 OR ";
     339 + }
     340 + if (id4776Ch) {
     341 + eidStr = eidStr + "event.id = 4776 OR ";
     342 + }
     343 + eidStr = eidStr.slice(0, -4) + ")";
     344 + eidStr = eidStr + " AND event.count > " + countInt;
     345 + 
     346 + return eidStr;
     347 +}
     348 + 
     349 +function createQuery() {
     350 + var selectVal = document.getElementById("InputSelect").value;
     351 + var setStr = document.getElementById("query-input").value;
     352 + 
     353 + if (selectVal == "Username") {
     354 + whereStr = 'user.user =~ "' + setStr + '" ';
     355 + } else {
     356 + whereStr = 'ip.IP =~ "' + setStr + '" ';
     357 + }
     358 + 
     359 + for (i = 1; i <= currentNumber; i++) {
     360 + if (document.getElementById("query-input" + i).value) {
     361 + ruleStr = document.getElementById("InputRule" + i).value;
     362 + if (document.getElementById("InputSelect" + i).value == "Username") {
     363 + whereStr += ruleStr + ' user.user =~ "' + document.getElementById("query-input" + i).value + '" ';
     364 + } else {
     365 + whereStr += ruleStr + ' ip.IP =~ "' + document.getElementById("query-input" + i).value + '" ';
     366 + }
     367 + }
     368 + }
     369 + 
     370 + eidStr = getQueryID()
     371 + queryStr = 'MATCH (user)-[event]-(ip) WHERE (' + whereStr + ') ' + eidStr + ' RETURN user, event, ip';
     372 + //console.log(queryStr);
     373 + executeQuery(queryStr);
     374 +}
     375 + 
     376 +function executeQuery(queryStr) {
     377 + var graph = {
     378 + "nodes": [],
     379 + "edges": []
     380 + };
     381 + 
     382 + session.run(queryStr)
     383 + .subscribe({
     384 + onNext: function(record) {
     385 + //console.log(record.get('user'), record.get('event'), record.get('ip'));
     386 + graph = buildGraph(graph, [record.get("user"), record.get("event"), record.get("ip")])
     387 + },
     388 + onCompleted: function() {
     389 + session.close();
     390 + if (graph.nodes.length == 0) {
     391 + searchError();
     392 + } else {
     393 + //console.log(graph);
     394 + rootNode = graph.nodes[0].id;
     395 + drawGraph(graph, rootNode);
     396 + }
     397 + },
     398 + onError: function(error) {
     399 + console.log("Error: ", error);
     400 + }
     401 + });
     402 +}
     403 + 
     404 +function pruserBack() {
     405 + rankpageUser -= 1;
     406 + if (rankpageUser < 0) {
     407 + rankpageUser = 0;
     408 + }
     409 + pagerankQuery(userqueryStr, "User", rankpageUser);
     410 +}
     411 + 
     412 +function pruserNext() {
     413 + rankpageUser += 1;
     414 + if (rankpageUser < 0) {
     415 + rankpageUser = 0;
     416 + }
     417 + pagerankQuery(userqueryStr, "User", rankpageUser);
     418 +}
     419 + 
     420 +function prhostBack() {
     421 + rankpageHost -= 1;
     422 + if (rankpageHost < 0) {
     423 + rankpageHost = 0;
     424 + }
     425 + pagerankQuery(ipqueryStr, "Host", rankpageHost);
     426 +}
     427 + 
     428 +function prhostNext() {
     429 + rankpageHost += 1;
     430 + if (rankpageHost < 0) {
     431 + rankpageHost = 0;
     432 + }
     433 + pagerankQuery(ipqueryStr, "Host", rankpageHost);
     434 +}
     435 + 
     436 +function pagerankQuery(queryStr, dataType, currentPage) {
     437 + var nodes = new Array();
     438 + var html = '<div><table class="table table-striped"><thead><tr class="col-sm-2 col-md-2">\
     439 + <th class="col-sm-1 col-md-1">Rank</th><th class="col-sm-1 col-md-1">' + dataType +
     440 + '</th></tr></thead><tbody class="col-sm-2 col-md-2">';
     441 + session.run(queryStr)
     442 + .subscribe({
     443 + onNext: function(record) {
     444 + nodeData = record.get("node");
     445 + if (dataType == "User") {
     446 + nodes.push([nodeData.properties.user, nodeData.properties.rank]);
     447 + }
     448 + if (dataType == "Host") {
     449 + nodes.push([nodeData.properties.IP, nodeData.properties.rank]);
     450 + }
     451 + },
     452 + onCompleted: function() {
     453 + session.close();
     454 + nodes.sort(function(a, b) {
     455 + var aa = a[1];
     456 + var bb = b[1];
     457 + if (aa < bb) {
     458 + return 1;
     459 + }
     460 + if (aa > bb) {
     461 + return -1;
     462 + }
     463 + return 0;
     464 + });
     465 + for (i = 10 * currentPage; i < nodes.length; i++) {
     466 + if (i >= 10 * currentPage + 10) {
     467 + break;
     468 + }
     469 + html += '<tr><td>' + (i + 1) + '</td><td><a onclick="createRankQuery(\'' + nodes[i][0] + '\', \'' + dataType + '\')">' + nodes[i][0] + '</a></td></tr>';
     470 + //console.log(nodes[i][0]);
     471 + //console.log(hosts[i][0]);
     472 + }
     473 + html += '</tbody></table></div>';
     474 + 
     475 + if (dataType == "User") {
     476 + var rankElem = document.getElementById("rankUser");
     477 + }
     478 + if (dataType == "Host") {
     479 + var rankElem = document.getElementById("rankHost");
     480 + }
     481 + rankElem.innerHTML = html;
     482 + },
     483 + onError: function(error) {
     484 + console.log("Error: ", error);
     485 + }
     486 + });
     487 +}
     488 + 
     489 +function exportCSV() {
     490 + var queryStr = 'MATCH (user:Username)-[event]-(ip:IPAddress) RETURN user, ip, event';
     491 + var events = new Array();
     492 + 
     493 + session.run(queryStr)
     494 + .subscribe({
     495 + onNext: function(record) {
     496 + eventData = record.get("event");
     497 + userData = record.get("user");
     498 + ipData = record.get("ip");
     499 + events.push([userData.properties.user, ipData.properties.IP,
     500 + eventData.properties.id, eventData.properties.logintype,
     501 + eventData.properties.status, eventData.properties.count
     502 + ]);
     503 + },
     504 + onCompleted: function() {
     505 + session.close();
     506 + var rowData = "username,host,id,logontype,status,count\r\n";
     507 + for (i = 0; i < events.length; i++) {
     508 + rowData += events[i][0] + ",";
     509 + rowData += events[i][1] + ",";
     510 + rowData += events[i][2] + ",";
     511 + rowData += events[i][3] + ",";
     512 + rowData += events[i][4] + ",";
     513 + rowData += events[i][5] + "\r\n";
     514 + }
     515 + var downLoadLink = document.createElement("a");
     516 + downLoadLink.download = "image.csv";
     517 + downLoadLink.href = URL.createObjectURL(new Blob([rowData], {
     518 + type: "application.csv"
     519 + }));
     520 + downLoadLink.dataset.downloadurl = ["application/csv", downLoadLink.download, downLoadLink.href].join(":");
     521 + downLoadLink.click();
     522 + },
     523 + onError: function(error) {
     524 + console.log("Error: ", error);
     525 + }
     526 + });
     527 +}
     528 + 
     529 +function exportJSON() {
     530 + var jsonData = "data:application/json,";
     531 + jsonData += encodeURIComponent(JSON.stringify(cy.json()));
     532 + var exptag = document.getElementById('export-json');
     533 + exptag.href = jsonData;
     534 +}
     535 + 
     536 +function exportPNG() {
     537 + var png64 = cy.png();
     538 + var exptag = document.getElementById('export-png');
     539 + exptag.href = png64;
     540 +}
     541 + 
     542 +function exportJPEG() {
     543 + var jpg64 = cy.png();
     544 + var exptag = document.getElementById('export-jpeg');
     545 + exptag.href = jpg64;
     546 +}
     547 + 
     548 +function downloadCSV(csvType) {
     549 + var queryStr = 'MATCH (date:Date) MATCH (user:Username) RETURN date, user';
     550 + var users = new Array();
     551 + 
     552 + session.run(queryStr)
     553 + .subscribe({
     554 + onNext: function(record) {
     555 + nodeData = record.get("user");
     556 + dateData = record.get("date");
     557 + users.push([nodeData.properties.user, nodeData.properties.counts,
     558 + nodeData.properties.counts4624, nodeData.properties.counts4625,
     559 + nodeData.properties.counts4768, nodeData.properties.counts4769,
     560 + nodeData.properties.counts4776
     561 + ]);
     562 + starttime = dateData.properties.start;
     563 + endtime = dateData.properties.end;
     564 + },
     565 + onCompleted: function() {
     566 + session.close();
     567 + 
     568 + var startDate = new Date(starttime);
     569 + var rangeHours = Math.floor((Date.parse(endtime) - Date.parse(starttime)) / (1000 * 60 * 60)) + 1;
     570 + var rawDate = "username,";
     571 + if (csvType == "detail") {
     572 + rawDate += "id,";
     573 + }
     574 + var countData = "";
     575 + for (i = 0; i < rangeHours; i++) {
     576 + rawDate += startDate.toISOString() + ",";
     577 + startDate.setHours(startDate.getHours() + 1);
     578 + }
     579 + 
     580 + if (csvType == "summary") {
     581 + for (i = 0; i < users.length; i++) {
     582 + countData += users[i][0] + "," + users[i][1] + "\r\n";
     583 + }
     584 + } else if (csvType == "detail") {
     585 + for (i = 0; i < users.length; i++) {
     586 + countData += users[i][0];
     587 + for (j = 2; j <= 6; j++) {
     588 + if (j == 2) {
     589 + countData += ",4624,"
     590 + } else if (j == 3) {
     591 + countData += ",4625,"
     592 + } else if (j == 4) {
     593 + countData += ",4768,"
     594 + } else if (j == 5) {
     595 + countData += ",4769,"
     596 + } else if (j == 6) {
     597 + countData += ",4776,"
     598 + }
     599 + countData += users[i][j] + "\r\n";
     600 + }
     601 + }
     602 + }
     603 + 
     604 + rawDate += "\r\n" + countData
     605 + var downLoadLink = document.createElement("a");
     606 + downLoadLink.download = "timeline.csv";
     607 + downLoadLink.href = URL.createObjectURL(new Blob([rawDate], {
     608 + type: "application.csv"
     609 + }));
     610 + downLoadLink.dataset.downloadurl = ["application/csv", downLoadLink.download, downLoadLink.href].join(":");
     611 + downLoadLink.click();
     612 + },
     613 + onError: function(error) {
     614 + console.log("Error: ", error);
     615 + }
     616 + });
     617 +}
     618 + 
     619 +function downloadSummary() {
     620 + downloadCSV("summary")
     621 +}
     622 + 
     623 +function downloadDetail() {
     624 + downloadCSV("detail")
     625 +}
     626 + 
     627 +function createTimeline(queryStr, tableType) {
     628 + var users = new Array();
     629 + var starttime = "";
     630 + var endtime = "";
     631 + var weekTbl = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
     632 + var bgcolorTbl = new Array("#ff7f50", "#efefef", "#efefef", "#efefef", "#efefef", "#efefef", "#b0c4de");
     633 + 
     634 + if (tableType == "all") {
     635 + var span = 'rowspan = "4"';
     636 + }
     637 + if (tableType == "search") {
     638 + var span = 'rowspan = "4" colspan="2"';
     639 + }
     640 + var html = '<div class="table-responsive"><table class="table table-bordered table-condensed table-striped" style="background-color:#EEE;"><thead><tr>\
     641 + <th ' + span + '>Username</th>';
     642 + 
     643 + session.run(queryStr)
     644 + .subscribe({
     645 + onNext: function(record) {
     646 + dateData = record.get("date");
     647 + nodeData = record.get("user");
     648 + users.push([nodeData.properties.user, nodeData.properties.counts, nodeData.properties.detect, nodeData.properties.rights, nodeData.properties.counts4624,
     649 + nodeData.properties.counts4625, nodeData.properties.counts4768, nodeData.properties.counts4769, nodeData.properties.counts4776
     650 + ]);
     651 + starttime = dateData.properties.start;
     652 + endtime = dateData.properties.end;
     653 + },
     654 + onCompleted: function() {
     655 + session.close();
     656 + var startDate = new Date(starttime);
     657 + var rangeHours = Math.floor((Date.parse(endtime) - Date.parse(starttime)) / (1000 * 60 * 60)) + 1;
     658 + var thisyear = startDate.getFullYear();
     659 + var thismonth = startDate.getMonth();
     660 + var thisday = startDate.getDate();
     661 + var thishour = startDate.getHours();
     662 + var thisdow = startDate.getDay();
     663 + var nextyear = null;
     664 + var nrangeHours = 0;
     665 + var weekd = 0;
     666 + for (i = 1; i <= rangeHours; i++) {
     667 + startDate.setHours(startDate.getHours() + 1);
     668 + if (startDate.getFullYear() != thisyear) {
     669 + html += '<th colspan="' + (i - nrangeHours) + '">' + thisyear + '</th>';
     670 + thisyear = startDate.getFullYear();
     671 + nrangeHours = i;
     672 + }
     673 + }
     674 + html += '<th colspan="' + (rangeHours - nrangeHours) + '">' + thisyear + '</th></tr><tr>';
     675 + 
     676 + nrangeHours = 0;
     677 + startDate = new Date(starttime);
     678 + for (i = 1; i <= rangeHours; i++) {
     679 + startDate.setHours(startDate.getHours() + 1);
     680 + if (startDate.getMonth() != thismonth) {
     681 + html += '<th colspan="' + (i - nrangeHours) + '">' + (thismonth + 1) + '</th>';
     682 + thismonth = startDate.getMonth();
     683 + nrangeHours = i;
     684 + }
     685 + }
     686 + html += '<th colspan="' + (rangeHours - nrangeHours) + '">' + (thismonth + 1) + '</th></tr><tr>';
     687 + 
     688 + nrangeHours = 0;
     689 + startDate = new Date(starttime);
     690 + for (i = 1; i <= rangeHours; i++) {
     691 + startDate.setHours(startDate.getHours() + 1);
     692 + if (startDate.getDate() != thisday) {
     693 + html += '<th bgcolor="' + bgcolorTbl[thisdow + weekd] + '" colspan="' + (i - nrangeHours) + '">' + thisday + '(' + weekTbl[thisdow + weekd] + ')</th>';
     694 + if (thisdow + weekd >= 6) {
     695 + thisdow = 0 - (weekd + 1);
     696 + }
     697 + thisday = startDate.getDate();
     698 + nrangeHours = i;
     699 + weekd += 1;
     700 + }
     701 + }
     702 + html += '<th bgcolor="' + bgcolorTbl[thisdow + weekd] + '" colspan="' + (rangeHours - nrangeHours) + '">' + thisday + '(' + weekTbl[thisdow + weekd] + ')</th></tr><tr>';
     703 + 
     704 + for (i = 0; i < rangeHours; i++) {
     705 + html += '<th>' + thishour + '</th>';
     706 + thishour += 1;
     707 + if (thishour >= 24) {
     708 + thishour = 0;
     709 + }
     710 + }
     711 + 
     712 + html += '</tr></thead><tbody>';
     713 + 
     714 + if (tableType == "all") {
     715 + for (i = 0; i < users.length; i++) {
     716 + if (users[i][3] == "system") {
     717 + html += '<tr><td><a onclick="clickTimeline(\'' + users[i][0] + '\')"><font color="#ff7f50">' + users[i][0] + '</font></a></td>';
     718 + } else {
     719 + html += '<tr><td><a onclick="clickTimeline(\'' + users[i][0] + '\')">' + users[i][0] + '</a></td>';
     720 + }
     721 + rowdata = users[i][1].split(",");
     722 + alerts = users[i][2].split(",");
     723 + for (j = 0; j < rowdata.length; j++) {
     724 + if (alerts[j] > 17) {
     725 + html += '<td bgcolor="#ff5aee">' + rowdata[j].split(".")[0] + '</td>';
     726 + } else if (alerts[j] > 16) {
     727 + html += '<td bgcolor="#ff8aee">' + rowdata[j].split(".")[0] + '</td>';
     728 + } else if (alerts[j] > 13) {
     729 + html += '<td bgcolor="#ffbaee">' + rowdata[j].split(".")[0] + '</td>';
     730 + } else if (alerts[j] > 10) {
     731 + html += '<td bgcolor="#ffeaee">' + rowdata[j].split(".")[0] + '</td>';
     732 + } else {
     733 + html += '<td>' + rowdata[j].split(".")[0] + '</td>';
     734 + }
     735 + }
     736 + html += '</tr>';
     737 + }
     738 + }
     739 + 
     740 + if (tableType == "search") {
     741 + for (i = 0; i < users.length; i++) {
     742 + if (users[i][3] == "system") {
     743 + html += '<tr><td rowspan = "5"><a onclick="clickTimeline(\'' + users[i][0] + '\')"><font color="#ff7f50">' + users[i][0] + '</font></a></td>';
     744 + } else {
     745 + html += '<tr><td rowspan = "5"><a onclick="clickTimeline(\'' + users[i][0] + '\')">' + users[i][0] + '</a></td>';
     746 + }
     747 + 
     748 + for (j = 4; j <= 8; j++) {
     749 + rowdata = users[i][j].split(",");
     750 + alerts = users[i][2].split(",");
     751 + if (j == 4) {
     752 + html += '<td>4624</td>';
     753 + } else if (j == 5) {
     754 + html += '<td>4625</td>';
     755 + } else if (j == 6) {
     756 + html += '<td>4768</td>';
     757 + } else if (j == 7) {
     758 + html += '<td>4769</td>';
     759 + } else if (j == 8) {
     760 + html += '<td>4776</td>';
     761 + }
     762 + for (k = 0; k < rowdata.length; k++) {
     763 + if (alerts[k] > 17) {
     764 + html += '<td bgcolor="#ff5aee">' + rowdata[k].split(".")[0] + '</td>';
     765 + } else if (alerts[k] > 16) {
     766 + html += '<td bgcolor="#ff8aee">' + rowdata[k].split(".")[0] + '</td>';
     767 + } else if (alerts[k] > 13) {
     768 + html += '<td bgcolor="#ffbaee">' + rowdata[k].split(".")[0] + '</td>';
     769 + } else if (alerts[k] > 10) {
     770 + html += '<td bgcolor="#ffeaee">' + rowdata[k].split(".")[0] + '</td>';
     771 + } else {
     772 + html += '<td>' + rowdata[k].split(".")[0] + '</td>';
     773 + }
     774 + }
     775 + html += '</tr>';
     776 + }
     777 + }
     778 + }
     779 + html += '</tbody></table></div>';
     780 + 
     781 + var timelineElem = document.getElementById("cy");
     782 + timelineElem.innerHTML = html;
     783 + },
     784 + onError: function(error) {
     785 + console.log("Error: ", error);
     786 + }
     787 + });
     788 +}
     789 + 
     790 +function createAlltimeline() {
     791 + var queryStr = 'MATCH (date:Date) MATCH (user:Username) RETURN date, user';
     792 + createTimeline(queryStr, "all");
     793 +}
     794 + 
     795 +function searchTimeline() {
     796 + var selectVal = document.getElementById("InputSelect").value;
     797 + var setStr = document.getElementById("query-input").value;
     798 + 
     799 + if (selectVal == "Username") {
     800 + whereStr = 'user.user =~ "' + setStr + '" ';
     801 + } else {
     802 + searchError();
     803 + }
     804 + 
     805 + for (i = 1; i <= currentNumber; i++) {
     806 + if (document.getElementById("query-input" + i).value) {
     807 + if (document.getElementById("InputSelect" + i).value == "Username") {
     808 + whereStr += 'or user.user =~ "' + document.getElementById("query-input" + i).value + '" ';
     809 + } else {
     810 + searchError();
     811 + }
     812 + }
     813 + }
     814 + var queryStr = 'MATCH (date:Date) MATCH (user:Username) WHERE (' + whereStr + ') RETURN date, user';
     815 + createTimeline(queryStr, "search");
     816 +}
     817 + 
     818 +function clickTimeline(setStr) {
     819 + whereStr = 'user.user =~ "' + setStr + '" ';
     820 + 
     821 + var queryStr = 'MATCH (date:Date) MATCH (user:Username) WHERE (' + whereStr + ') RETURN date, user';
     822 + createTimeline(queryStr, "search");
     823 +}
     824 + 
     825 +function searchError() {
     826 + var elemMsg = document.getElementById("error");
     827 + elemMsg.innerHTML =
     828 + '<div class="alert alert-warning alert-dismissible" id="alertfadeout" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="close">\
     829 + <span aria-hidden="true">×</span></button><strong>WARNING</strong>: Search failed!</div>';
     830 + $(document).ready(function() {
     831 + $('#alertfadeout').fadeIn(2000).delay(4000).fadeOut(2000);
     832 + });
     833 +}
     834 + 
     835 +function file_upload() {
     836 + var upfile = document.getElementById("lefile");
     837 + var timezone = document.getElementById("utcTime").value;
     838 + document.getElementById("uploadBar").innerHTML = '';
     839 + document.getElementById("status").innerHTML = '';
     840 + 
     841 + var formData = new FormData();
     842 + for (var i = 0; i < upfile.files.length; i++) {
     843 + sendFile = "file" + i
     844 + formData.append(sendFile, upfile.files[i]);
     845 + }
     846 + formData.append("timezone", timezone);
     847 + var xmlhttp = new XMLHttpRequest();
     848 + xmlhttp.upload.addEventListener("progress", progressHandler, false);
     849 + xmlhttp.addEventListener("load", completeHandler, false);
     850 + xmlhttp.addEventListener("error", errorHandler, false);
     851 + xmlhttp.addEventListener("abort", abortHandler, false);
     852 + xmlhttp.open("POST", "upload", true);
     853 + xmlhttp.send(formData);
     854 +}
     855 + 
     856 +function progressHandler(event) {
     857 + var percent = (event.loaded / event.total) * 100;
     858 + document.getElementById("uploadBar").innerHTML = '<h4>Upload ...</h4><div class="progress"><div class="progress-bar progress-bar-striped active" role="progressbar" style="width: ' + Math.round(percent) + '%;">' + Math.round(percent) + '%</div></div>';
     859 +}
     860 + 
     861 +var parse_status = false;
     862 + 
     863 +function completeHandler(event) {
     864 + if (event.target.responseText == "FAIL") {
     865 + document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: Upload Failed!</div>';
     866 + }
     867 + if (event.target.responseText == "SUCCESS") {
     868 + parse_status = false
     869 + document.getElementById("uploadBar").innerHTML = '<h4>Upload ...</h4><div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" style="width: 100%;">SUCCESS</div></div>';
     870 + var loop = function() {
     871 + if (parse_status == false) {
     872 + setTimeout(loop, 2000);
     873 + }
     874 + parseEVTX();
     875 + }
     876 + loop();
     877 + }
     878 +}
     879 + 
     880 +function errorHandler(event) {
     881 + document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: Upload Failed!</div>';
     882 +}
     883 + 
     884 +function abortHandler(event) {
     885 + document.getElementById("status").innerHTML = '<div class="alert alert-info">Upload Aborted</div>';
     886 +}
     887 + 
     888 +function parseEVTX() {
     889 + var xmlhttp2 = new XMLHttpRequest();
     890 + xmlhttp2.open("GET", "/log");
     891 + xmlhttp2.send();
     892 + xmlhttp2.onreadystatechange = function() {
     893 + if (xmlhttp2.readyState == 4) {
     894 + if (xmlhttp2.status == 200) {
     895 + var logdata = xmlhttp2.responseText.split(/\r\n|\r|\n/);
     896 + var allrecode = logdata[3].split(" ")[5].replace(".", "");
     897 + var nowdata = logdata[logdata.length - 2];
     898 + if (nowdata.indexOf("Now loading") != -1) {
     899 + var recordnum = nowdata.split(" ")[3];
     900 + var percent = (recordnum / allrecode) * 100;
     901 + document.getElementById("uploadBar").innerHTML = '<h4>Parsing ...</h4><div class="progress"><div class="progress-bar progress-bar-striped active" role="progressbar" style="width: ' + Math.round(percent) + '%;">' + Math.round(percent) + '%</div></div>';
     902 + } else if (nowdata.indexOf("Script end") != -1) {
     903 + document.getElementById("uploadBar").innerHTML = '<h4>Parsing ...</h4><div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" style="width: 100%;">SUCCESS</div></div>';
     904 + document.getElementById("status").innerHTML = '<div class="alert alert-info"><strong>Import Success</strong>: You need to reload the web page.</div>';
     905 + parse_status = true;
     906 + } else if (nowdata.indexOf("[!]") != -1) {
     907 + document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: EVTX parse Failed!</div>';
     908 + parse_status = true;
     909 + }
     910 + } else {
     911 + document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: logontracer.log status = ' + xmlhttp2.status + '</div>';
     912 + parse_status = true;
     913 + }
     914 + }
     915 + }
     916 +}
     917 + 
  • ■ ■ ■ ■ ■
    templates/index.html
    skipped 12 lines
    13 13   <script src="https://cdn.rawgit.com/cytoscape/cytoscape.js-qtip/2.7.1/cytoscape-qtip.js" integrity="sha384-iEsLCgQ6cKWEBnP+3Yd8hsUSvCzDYQU/UUVvXzB10FMtPexDn68x5Sem24bboY4I" crossorigin="anonymous"></script>
    14 14   <!-- Neo4j JavaScript Driver -->
    15 15   <script src="https://cdn.rawgit.com/neo4j/neo4j-javascript-driver/1.4.1/lib/browser/neo4j-web.min.js" integrity="sha384-xu5q3iV0ueZtK1T6RpPoUqv4VlVuEJpax+yyNmlN6CuOtT+SeUe1dqlI7MHpIN0p" crossorigin="anonymous"></script>
     16 + <script src="static/script.js"></script>
    16 17  </head>
    17 18   
    18 19  <body>
    skipped 78 lines
    97 98   <hr>
    98 99   <a>Graph mode</a><br>
    99 100   <div class="btn-group" data-toggle="buttons">
    100  - <label class="btn btn-default active">
     101 + <label class="btn btn-default active">
    101 102   <input type="radio" id="modeGrid" name="graphmode" checked="checked">grid</label>
    102  - <label class="btn btn-default">
     103 + <label class="btn btn-default">
    103 104   <input type="radio" id="modeCose" name="graphmode">cose</label>
    104 105   <label class="btn btn-default">
    105 106   <input type="radio" id="modeCircle" name="graphmode">circle</label>
    106 107   </div>
    107 108   <hr>
    108 109   <a>Timeline</a><br>
    109  - <div class="list-group">
    110  - <button type="button" class="list-group-item" onclick="createAlltimeline()">Create All Users</button>
    111  - <button type="button" class="list-group-item" onclick="searchTimeline()">Search</button>
    112  - </div>
    113  - <div class="btn-group">
    114  - <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
    115  - Download <span class="caret"></span>
    116  - </button>
    117  - <ul class="dropdown-menu" role="menu">
    118  - <li role="presentation"><a onclick="downloadSummary()">Summary</a></li>
    119  - <li role="presentation"><a onclick="downloadDetail()">Details</a></li>
    120  - </ul>
    121  - </div>
     110 + <button class="btn btn-default" onClick="window.open('timeline')">Create All Users</button>
    122 111   <hr>
    123 112   <a>Upload</a><br>
    124 113   <button class="btn btn-default" data-toggle="modal" data-target="#UploadEVTX">Upload EVTX File</button>
    skipped 16 lines
    141 130   </ul>
    142 131   </div>
    143 132   </div>
    144  - <!-- Upload -->
    145  - <div class="modal fade" id="UploadEVTX" tabindex="-1">
    146  - <div class="modal-dialog">
    147  - <div class="modal-content">
    148  - <div class="modal-header">
    149  - <button type="button" class="close" data-dismiss="modal"><span>×</span></button>
    150  - <h4 class="modal-title">Upload EVTX File</h4>
    151  - </div>
    152  - <div class="modal-body">
    153  - <div id="zoneTime"></div>
    154  - <div class="input-group">
    155  - <input multiple id="lefile" type="file" style="display:none">
    156  - <input type="text" id="evtx_name" class="form-control" placeholder="select file (multi files) ...">
    157  - <span class="input-group-btn"><button type="button" class="btn btn-info" onclick="$('input[id=lefile]').click();">Browse</button></span>
    158  - </div>
    159  - <div id="uploadBar"></div>
    160  - <div id="status"></div>
     133 + </div>
     134 + <!-- Upload -->
     135 + <div class="modal fade" id="UploadEVTX" tabindex="-1">
     136 + <div class="modal-dialog">
     137 + <div class="modal-content">
     138 + <div class="modal-header">
     139 + <button type="button" class="close" data-dismiss="modal"><span>×</span></button>
     140 + <h4 class="modal-title">Upload EVTX File</h4>
     141 + </div>
     142 + <div class="modal-body">
     143 + <div id="zoneTime"></div>
     144 + <div class="input-group">
     145 + <input multiple id="lefile" type="file" style="display:none">
     146 + <input type="text" id="evtx_name" class="form-control" placeholder="select file (multi files) ...">
     147 + <span class="input-group-btn"><button type="button" class="btn btn-info" onclick="$('input[id=lefile]').click();">Browse</button></span>
    161 148   </div>
    162  - <div class="modal-footer">
    163  - <button type="submit" class="btn btn-primary" onclick="file_upload()">Upload</button>
    164  - <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    165  - <a href="log" target="_blank"><button type="button" class="btn btn-default">Log</button></a>
    166  - </div>
     149 + <div id="uploadBar"></div>
     150 + <div id="status"></div>
     151 + </div>
     152 + <div class="modal-footer">
     153 + <button type="submit" class="btn btn-primary" onclick="file_upload()">Upload</button>
     154 + <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
     155 + <a href="log" target="_blank"><button type="button" class="btn btn-default">Log</button></a>
    167 156   </div>
    168 157   </div>
    169 158   </div>
    170  - <script type="text/javascript">
    171  - var neo = neo4j.default;
    172  - //Neo4j access settings
    173  - var driver = neo.driver("bolt://{{ server_ip }}", neo.auth.basic("{{ neo4j_user }}", "{{ neo4j_password }}"));
    174  - var session = driver.session();
    175  - var cy = cytoscape();
    176  - var rankpageUser = 0
    177  - var rankpageHost = 0
     159 + </div>
     160 + <script type="text/javascript">
     161 + var neo = neo4j.default;
     162 + //Neo4j access settings
     163 + var driver = neo.driver("bolt://{{ server_ip }}", neo.auth.basic("{{ neo4j_user }}", "{{ neo4j_password }}"));
     164 + var session = driver.session();
     165 + var cy = cytoscape();
     166 + var rankpageUser = 0
     167 + var rankpageHost = 0
    178 168   
    179  - var userqueryStr = 'MATCH (node:Username) RETURN node';
    180  - var ipqueryStr = 'MATCH (node:IPAddress) RETURN node';
    181  - pagerankQuery(userqueryStr, "User", rankpageUser);
    182  - pagerankQuery(ipqueryStr, "Host", rankpageHost);
     169 + var userqueryStr = 'MATCH (node:Username) RETURN node';
     170 + var ipqueryStr = 'MATCH (node:IPAddress) RETURN node';
     171 + pagerankQuery(userqueryStr, "User", rankpageUser);
     172 + pagerankQuery(ipqueryStr, "Host", rankpageHost);
    183 173   
    184  - var currentNumber = 0;
    185  - var ItemField = {
    186  - currentNumber: 0,
    187  - itemTemplate: '<label class="sr-only" for="InputSelect">select</label>\
     174 + var currentNumber = 0;
     175 + var ItemField = {
     176 + currentNumber: 0,
     177 + itemTemplate: '<label class="sr-only" for="InputSelect">select</label>\
    188 178   <select class="form-control" id="InputSelect_count_">\
    189 179   <option>Username</option><option>Host</option></select>\
    190 180   <input class="form-control" type="text" id="query-input_count_" size="10">\
    191 181   <label class="sr-only" for="InputSelect">select</label>\
    192 182   <select class="form-control" id="InputRule_count_">\
    193 183   <option>OR</option><option>AND</option></select>',
    194  - add: function() {
    195  - currentNumber++;
    196  - if (currentNumber <= 10) {
    197  - var new_item = this.itemTemplate.replace(/_count_/mg, currentNumber);
    198  - var new_area = document.createElement("div");
    199  - new_area.setAttribute("id", "item" + currentNumber);
    200  - var field = document.getElementById('itemForm');
    201  - field.appendChild(new_area);
    202  - document.getElementById('item' + currentNumber).innerHTML = new_item;
    203  - }
    204  - },
    205  - del: function() {
    206  - if (currentNumber == 0) {
    207  - return;
    208  - }
     184 + add: function() {
     185 + currentNumber++;
     186 + if (currentNumber <= 10) {
     187 + var new_item = this.itemTemplate.replace(/_count_/mg, currentNumber);
     188 + var new_area = document.createElement("div");
     189 + new_area.setAttribute("id", "item" + currentNumber);
    209 190   var field = document.getElementById('itemForm');
    210  - field.removeChild(field.lastChild);
    211  - currentNumber--;
    212  - }
    213  - }
    214  - 
    215  - var downMenu = '<div class="col-xs-3"><select class="form-control" id="utcTime"><option>UTC</option>';
    216  - for (i = +14; i >= -12; i--) {
    217  - downMenu += '<option>' + i + '</option>';
    218  - }
    219  - downMenu += '</select></div>';
    220  - document.getElementById("zoneTime").innerHTML = downMenu;
    221  - 
    222  - function buildGraph(graph, path) {
    223  - for (idx in path) {
    224  - if (Object.keys(path[idx]).length == 3) {
    225  - objid = parseInt(path[idx].identity.low) + 100;
    226  - } else {
    227  - objid = parseInt(path[idx].identity.low) + 1000;
    228  - }
    229  - 
    230  - // Node
    231  - if (Object.keys(path[idx]).length == 3) {
    232  - var ndupflg = false;
    233  - for (nidx in graph.nodes) {
    234  - if (graph.nodes[nidx].data.objid == objid) {
    235  - ndupflg = true;
    236  - }
    237  - }
    238  - if (ndupflg) {
    239  - continue;
    240  - }
    241  - 
    242  - if (path[idx].labels[0] == "Username") {
    243  - nname = path[idx].properties.user
    244  - nfsize = "10"
    245  - nshape = "ellipse"
    246  - nwidth = "25"
    247  - nheight = "25"
    248  - ntype = "User"
    249  - if (path[idx].properties.rights == "system") {
    250  - ncolor = "#ff0000"
    251  - nbcolor = "#ffc0cb"
    252  - nfcolor = "#ff69b4"
    253  - nprivilege = "SYSTEM"
    254  - } else {
    255  - ncolor = "#0000cd"
    256  - nbcolor = "#cee1ff"
    257  - nfcolor = "#6da0f2"
    258  - nprivilege = "Normal"
    259  - }
    260  - }
    261  - if (path[idx].labels[0] == "IPAddress") {
    262  - nname = path[idx].properties.IP
    263  - nshape = "diamond"
    264  - nwidth = "25"
    265  - nheight = "25"
    266  - nfsize = "8"
    267  - ncolor = "#2e8b57"
    268  - nbcolor = "#98fb98"
    269  - nfcolor = "#3cb371"
    270  - ntype = "Host"
    271  - }
    272  - graph.nodes.push({
    273  - "data": {
    274  - "id": objid,
    275  - "objid": objid,
    276  - "nlabel": nname,
    277  - "ncolor": ncolor,
    278  - "nbcolor": nbcolor,
    279  - "nfcolor": nfcolor,
    280  - "nwidth": nwidth,
    281  - "nheight": nheight,
    282  - "nfsize": nfsize,
    283  - "nshape": nshape,
    284  - "label": path[idx].labels[0],
    285  - "nprivilege": nprivilege,
    286  - "ntype": ntype,
    287  - "nsid": path[idx].properties.sid
    288  - }
    289  - });
    290  - } else {
    291  - // Relationship
    292  - var ldupflg = false;
    293  - var label_count = document.getElementById("label-count").checked;
    294  - var label_type = document.getElementById("label-type").checked;
    295  - var label_status = document.getElementById("label-status").checked;
    296  - var ename = path[idx].properties.id.low;
    297  - if (label_count) {
    298  - ename += " : " + path[idx].properties.count.low;
    299  - }
    300  - if (label_type) {
    301  - ename += " : " + path[idx].properties.logintype;
    302  - }
    303  - if (label_status) {
    304  - ename += " : " + path[idx].properties.status;
    305  - }
    306  - for (nidx in graph.edges) {
    307  - if (graph.edges[nidx].data.objid == objid) {
    308  - ldupflg = true;
    309  - }
    310  - }
    311  - if (ldupflg) {
    312  - continue;
    313  - }
    314  - graph.edges.push({
    315  - "data": {
    316  - "id": objid,
    317  - "source": parseInt(path[parseInt(idx) - 1].identity.low) + 100,
    318  - "target": parseInt(path[parseInt(idx) + 1].identity.low) + 100,
    319  - "objid": objid,
    320  - "elabel": ename,
    321  - "label": path[idx].type,
    322  - "distance": 5,
    323  - "ntype": "edge",
    324  - "eid": path[idx].properties.id.low,
    325  - "count": path[idx].properties.count.low,
    326  - "logontype": path[idx].properties.logintype,
    327  - "status": path[idx].properties.status
    328  - }
    329  - });
    330  - }
    331  - }
    332  - 
    333  - return (graph);
    334  - }
    335  - 
    336  - function drawGraph(graph, rootNode) {
    337  - var flagGrid = document.getElementById("modeGrid").checked;
    338  - var flagCose = document.getElementById("modeCose").checked;
    339  - var flagCircle = document.getElementById("modeCircle").checked;
    340  - var flagMode = "";
    341  - 
    342  - if (flagGrid) {
    343  - flagMode = "grid";
    344  - }
    345  - if (flagCose) {
    346  - flagMode = "cose";
    347  - }
    348  - if (flagCircle) {
    349  - flagMode = "circle";
    350  - }
    351  - 
    352  - cy = cytoscape({
    353  - container: document.getElementById("cy"),
    354  - boxSelectionEnabled: false,
    355  - style: cytoscape.stylesheet()
    356  - .selector('node').css({
    357  - "content": "data(nlabel)",
    358  - "width": "data(nwidth)",
    359  - "height": "data(nheight)",
    360  - "color": "data(ncolor)",
    361  - "font-size": "data(nfsize)",
    362  - "background-color": "data(nbcolor)",
    363  - "border-color": "data(nfcolor)",
    364  - "border-style": "solid",
    365  - "border-width": 3,
    366  - "text-valign": "center",
    367  - "text-outline-width": 1,
    368  - "text-outline-color": "data(nbcolor)",
    369  - "shape": "data(nshape)"
    370  - })
    371  - .selector(':selected').css({
    372  - "width": 25,
    373  - "height": 25,
    374  - "border-width": 4,
    375  - "border-color": "#404040"
    376  - })
    377  - .selector('edge').css({
    378  - "content": "data(elabel)",
    379  - "font-size": "8",
    380  - 'curve-style': 'bezier',
    381  - 'target-arrow-shape': 'triangle',
    382  - 'width': 2,
    383  - 'line-color': '#ddd',
    384  - 'target-arrow-color': '#ddd'
    385  - })
    386  - .selector('.highlighted').css({
    387  - 'background-color': '#61bffc',
    388  - 'line-color': '#61bfcc',
    389  - 'transition-property': 'background-color, line-color, target-arrow-color',
    390  - 'transition-duration': '0.5s'
    391  - }),
    392  - elements: graph,
    393  - layout: {
    394  - name: flagMode,
    395  - directed: true,
    396  - roots: rootNode,
    397  - animate: true,
    398  - padding: 10
    399  - }
    400  - });
    401  - 
    402  - cy.nodes().forEach(function(ele) {
    403  - ele.qtip({
    404  - content: {
    405  - title: "<b>Node Details</b>",
    406  - text: qtipNode(ele)
    407  - },
    408  - style: {
    409  - classes: 'qtip-bootstrap'
    410  - },
    411  - position: {
    412  - my: 'top center',
    413  - at: 'bottom center',
    414  - target: ele
    415  - }
    416  - });
    417  - });
    418  - 
    419  - cy.edges().forEach(function(ele) {
    420  - ele.qtip({
    421  - content: {
    422  - title: "<b>Event Details</b>",
    423  - text: qtipEdge(ele)
    424  - },
    425  - style: {
    426  - classes: 'qtip-bootstrap'
    427  - },
    428  - position: {
    429  - my: 'top center',
    430  - at: 'bottom center',
    431  - target: ele
    432  - }
    433  - });
    434  - });
    435  - }
    436  - 
    437  - function qtipNode(ndata) {
    438  - var qtext = 'Name: ' + ndata._private.data["nlabel"];
    439  - if ( ndata._private.data["ntype"] == "User" ) {
    440  - qtext += '<br>Privilege: ' + ndata._private.data["nprivilege"];
    441  - qtext += '<br>SID: ' + ndata._private.data["nsid"];
     191 + field.appendChild(new_area);
     192 + document.getElementById('item' + currentNumber).innerHTML = new_item;
    442 193   }
    443  - qtext += '<br><button type="button" class="btn btn-primary btn-xs" onclick="createRankQuery(\'' + ndata._private.data["nlabel"] + '\',\'' + ndata._private.data["ntype"] + '\')">search</button>';
    444  - 
    445  - return qtext;
    446  - }
    447  - 
    448  - function qtipEdge(ndata) {
    449  - var qtext = "";
    450  - if ( ndata._private.data["eid"] == 4624 ){
    451  - qtext = "<b>Successful logon</b><br>";
     194 + },
     195 + del: function() {
     196 + if (currentNumber == 0) {
     197 + return;
    452 198   }
    453  - if ( ndata._private.data["eid"] == 4625 ){
    454  - qtext = "<b>Logon failure</b><br>";
    455  - }
    456  - if ( ndata._private.data["eid"] == 4768 ){
    457  - qtext = "<b>Kerberos Authentication (TGT Request)</b><br>";
    458  - }
    459  - if ( ndata._private.data["eid"] == 4769 ){
    460  - qtext = "<b>Kerberos Service Ticket (ST Request)</b><br>";
    461  - }
    462  - if ( ndata._private.data["eid"] == 4776 ){
    463  - qtext = "<b>NTLM Authentication</b><br>";
    464  - }
    465  - qtext += "Count: " + ndata._private.data["count"];
    466  - qtext += "<br>Logon Type: " + ndata._private.data["logontype"];
    467  - qtext += "<br>Status: " + ndata._private.data["status"];
    468  - return qtext;
     199 + var field = document.getElementById('itemForm');
     200 + field.removeChild(field.lastChild);
     201 + currentNumber--;
    469 202   }
     203 + }
    470 204   
    471  - function createAllQuery() {
    472  - eidStr = getQueryID();
    473  - eidStr = eidStr.slice(4);
    474  - queryStr = 'MATCH (user)-[event]-(ip) WHERE ' + eidStr + ' RETURN user, event, ip';
    475  - //console.log(queryStr);
    476  - executeQuery(queryStr);
    477  - }
     205 + var downMenu = '<div class="col-xs-3"><select class="form-control" id="utcTime"><option>UTC</option>';
     206 + for (i = +14; i >= -12; i--) {
     207 + downMenu += '<option>' + i + '</option>';
     208 + }
     209 + downMenu += '</select></div>';
     210 + document.getElementById("zoneTime").innerHTML = downMenu;
    478 211   
    479  - function createSystemQuery() {
    480  - eidStr = getQueryID();
    481  - queryStr = 'MATCH (user)-[event]-(ip) WHERE user.rights = "system" ' + eidStr + ' RETURN user, event, ip';
    482  - //console.log(queryStr);
    483  - executeQuery(queryStr);
    484  - }
    485  - 
    486  - function createRDPQuery() {
    487  - eidStr = getQueryID();
    488  - queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 10 ' + eidStr + ' RETURN user, event, ip';
    489  - //console.log(queryStr);
    490  - executeQuery(queryStr);
    491  - }
    492  - 
    493  - function createNetQuery() {
    494  - eidStr = getQueryID();
    495  - queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 3 ' + eidStr + ' RETURN user, event, ip';
    496  - //console.log(queryStr);
    497  - executeQuery(queryStr);
     212 + $('input[id=lefile]').change(function() {
     213 + var inFile = "";
     214 + var fileList = document.getElementById("lefile").files;
     215 + if (1 < fileList.length) {
     216 + inFile += "selected " + fileList.length + " files."
     217 + } else {
     218 + inFile += fileList[0].name
    498 219   }
    499  - 
    500  - function createBatchQuery() {
    501  - eidStr = getQueryID();
    502  - queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 4 ' + eidStr + ' RETURN user, event, ip';
    503  - //console.log(queryStr);
    504  - executeQuery(queryStr);
    505  - }
    506  - 
    507  - function createServiceQuery() {
    508  - eidStr = getQueryID();
    509  - queryStr = 'MATCH (user)-[event]-(ip) WHERE event.logintype = 5 ' + eidStr + ' RETURN user, event, ip';
    510  - //console.log(queryStr);
    511  - executeQuery(queryStr);
    512  - }
    513  - 
    514  - function create14068Query() {
    515  - queryStr = 'MATCH (user)-[event]-(ip) WHERE event.status = "0xf" AND event.id = 4769 RETURN user, event, ip'
    516  - //console.log(queryStr);
    517  - executeQuery(queryStr);
    518  - }
    519  - 
    520  - function createFailQuery() {
    521  - queryStr = 'MATCH (user)-[event]-(ip) WHERE event.id = 4625 RETURN user, event, ip'
    522  - //console.log(queryStr);
    523  - executeQuery(queryStr);
    524  - }
    525  - 
    526  - function createRankQuery(setStr, qType) {
    527  - if (qType == "User") {
    528  - whereStr = 'user.user = "' + setStr + '" ';
    529  - }
    530  - if (qType == "Host") {
    531  - whereStr = 'ip.IP = "' + setStr + '" ';
    532  - }
    533  - 
    534  - eidStr = getQueryID()
    535  - 
    536  - queryStr = 'MATCH (user)-[event]-(ip) WHERE (' + whereStr + ') ' + eidStr + ' RETURN user, event, ip';
    537  - //console.log(queryStr);
    538  - executeQuery(queryStr);
    539  - }
    540  - 
    541  - function getQueryID() {
    542  - var id4624Ch = document.getElementById("id4624").checked;
    543  - var id4625Ch = document.getElementById("id4625").checked;
    544  - var id4768Ch = document.getElementById("id4768").checked;
    545  - var id4769Ch = document.getElementById("id4769").checked;
    546  - var id4776Ch = document.getElementById("id4776").checked;
    547  - var countInt = document.getElementById("count-input").value;
    548  - var eidStr = "AND ("
    549  - if (id4624Ch) {
    550  - eidStr = eidStr + "event.id = 4624 OR ";
    551  - }
    552  - if (id4625Ch) {
    553  - eidStr = eidStr + "event.id = 4625 OR ";
    554  - }
    555  - if (id4768Ch) {
    556  - eidStr = eidStr + "event.id = 4768 OR ";
    557  - }
    558  - if (id4769Ch) {
    559  - eidStr = eidStr + "event.id = 4769 OR ";
    560  - }
    561  - if (id4776Ch) {
    562  - eidStr = eidStr + "event.id = 4776 OR ";
    563  - }
    564  - eidStr = eidStr.slice(0, -4) + ")";
    565  - eidStr = eidStr + " AND event.count > " + countInt;
    566  - 
    567  - return eidStr;
    568  - }
    569  - 
    570  - function createQuery() {
    571  - var selectVal = document.getElementById("InputSelect").value;
    572  - var setStr = document.getElementById("query-input").value;
    573  - 
    574  - if (selectVal == "Username") {
    575  - whereStr = 'user.user =~ "' + setStr + '" ';
    576  - } else {
    577  - whereStr = 'ip.IP =~ "' + setStr + '" ';
    578  - }
    579  - 
    580  - for (i = 1; i <= currentNumber; i++) {
    581  - if (document.getElementById("query-input" + i).value) {
    582  - ruleStr = document.getElementById("InputRule" + i).value;
    583  - if (document.getElementById("InputSelect" + i).value == "Username") {
    584  - whereStr += ruleStr + ' user.user =~ "' + document.getElementById("query-input" + i).value + '" ';
    585  - } else {
    586  - whereStr += ruleStr + ' ip.IP =~ "' + document.getElementById("query-input" + i).value + '" ';
    587  - }
    588  - }
    589  - }
    590  - 
    591  - eidStr = getQueryID()
    592  - queryStr = 'MATCH (user)-[event]-(ip) WHERE (' + whereStr + ') ' + eidStr + ' RETURN user, event, ip';
    593  - //console.log(queryStr);
    594  - executeQuery(queryStr);
    595  - }
    596  - 
    597  - function executeQuery(queryStr) {
    598  - var graph = {
    599  - "nodes": [],
    600  - "edges": []
    601  - };
    602  - 
    603  - session.run(queryStr)
    604  - .subscribe({
    605  - onNext: function(record) {
    606  - //console.log(record.get('user'), record.get('event'), record.get('ip'));
    607  - graph = buildGraph(graph, [record.get("user"), record.get("event"), record.get("ip")])
    608  - },
    609  - onCompleted: function() {
    610  - session.close();
    611  - if (graph.nodes.length == 0) {
    612  - searchError();
    613  - } else {
    614  - //console.log(graph);
    615  - rootNode = graph.nodes[0].id;
    616  - drawGraph(graph, rootNode);
    617  - }
    618  - },
    619  - onError: function(error) {
    620  - console.log("Error: ", error);
    621  - }
    622  - });
    623  - }
    624  - 
    625  - function pruserBack() {
    626  - rankpageUser -= 1;
    627  - if (rankpageUser < 0) {
    628  - rankpageUser = 0;
    629  - }
    630  - pagerankQuery(userqueryStr, "User", rankpageUser);
    631  - }
    632  - 
    633  - function pruserNext() {
    634  - rankpageUser += 1;
    635  - if (rankpageUser < 0) {
    636  - rankpageUser = 0;
    637  - }
    638  - pagerankQuery(userqueryStr, "User", rankpageUser);
    639  - }
    640  - 
    641  - function prhostBack() {
    642  - rankpageHost -= 1;
    643  - if (rankpageHost < 0) {
    644  - rankpageHost = 0;
    645  - }
    646  - pagerankQuery(ipqueryStr, "Host", rankpageHost);
    647  - }
    648  - 
    649  - function prhostNext() {
    650  - rankpageHost += 1;
    651  - if (rankpageHost < 0) {
    652  - rankpageHost = 0;
    653  - }
    654  - pagerankQuery(ipqueryStr, "Host", rankpageHost);
    655  - }
    656  - 
    657  - function pagerankQuery(queryStr, dataType, currentPage) {
    658  - var nodes = new Array();
    659  - var html = '<div><table class="table table-striped"><thead><tr class="col-sm-2 col-md-2">\
    660  - <th class="col-sm-1 col-md-1">Rank</th><th class="col-sm-1 col-md-1">' + dataType +
    661  - '</th></tr></thead><tbody class="col-sm-2 col-md-2">';
    662  - session.run(queryStr)
    663  - .subscribe({
    664  - onNext: function(record) {
    665  - nodeData = record.get("node");
    666  - if (dataType == "User") {
    667  - nodes.push([nodeData.properties.user, nodeData.properties.rank]);
    668  - }
    669  - if (dataType == "Host") {
    670  - nodes.push([nodeData.properties.IP, nodeData.properties.rank]);
    671  - }
    672  - },
    673  - onCompleted: function() {
    674  - session.close();
    675  - nodes.sort(function(a, b) {
    676  - var aa = a[1];
    677  - var bb = b[1];
    678  - if (aa < bb) {
    679  - return 1;
    680  - }
    681  - if (aa > bb) {
    682  - return -1;
    683  - }
    684  - return 0;
    685  - });
    686  - for (i = 10 * currentPage; i < nodes.length; i++) {
    687  - if (i >= 10 * currentPage + 10) {
    688  - break;
    689  - }
    690  - html += '<tr><td>' + (i + 1) + '</td><td><a onclick="createRankQuery(\'' + nodes[i][0] + '\', \'' + dataType + '\')">' + nodes[i][0] + '</a></td></tr>';
    691  - //console.log(nodes[i][0]);
    692  - //console.log(hosts[i][0]);
    693  - }
    694  - html += '</tbody></table></div>';
    695  - 
    696  - if (dataType == "User") {
    697  - var rankElem = document.getElementById("rankUser");
    698  - }
    699  - if (dataType == "Host") {
    700  - var rankElem = document.getElementById("rankHost");
    701  - }
    702  - rankElem.innerHTML = html;
    703  - },
    704  - onError: function(error) {
    705  - console.log("Error: ", error);
    706  - }
    707  - });
    708  - }
    709  - 
    710  - function exportCSV() {
    711  - var queryStr = 'MATCH (user:Username)-[event]-(ip:IPAddress) RETURN user, ip, event';
    712  - var events = new Array();
    713  - 
    714  - session.run(queryStr)
    715  - .subscribe({
    716  - onNext: function(record) {
    717  - eventData = record.get("event");
    718  - userData = record.get("user");
    719  - ipData = record.get("ip");
    720  - events.push([userData.properties.user, ipData.properties.IP,
    721  - eventData.properties.id, eventData.properties.logintype,
    722  - eventData.properties.status, eventData.properties.count
    723  - ]);
    724  - },
    725  - onCompleted: function() {
    726  - session.close();
    727  - var rowData = "username,host,id,logontype,status,count\r\n";
    728  - for (i = 0; i < events.length; i++) {
    729  - rowData += events[i][0] + ",";
    730  - rowData += events[i][1] + ",";
    731  - rowData += events[i][2] + ",";
    732  - rowData += events[i][3] + ",";
    733  - rowData += events[i][4] + ",";
    734  - rowData += events[i][5] + "\r\n";
    735  - }
    736  - var downLoadLink = document.createElement("a");
    737  - downLoadLink.download = "image.csv";
    738  - downLoadLink.href = URL.createObjectURL(new Blob([rowData], {type: "application.csv"}));
    739  - downLoadLink.dataset.downloadurl = ["application/csv", downLoadLink.download, downLoadLink.href].join(":");
    740  - downLoadLink.click();
    741  - },
    742  - onError: function(error) {
    743  - console.log("Error: ", error);
    744  - }
    745  - });
    746  - }
    747  - 
    748  - function exportJSON() {
    749  - var jsonData = "data:application/json,";
    750  - jsonData += encodeURIComponent(JSON.stringify(cy.json()));
    751  - var exptag = document.getElementById('export-json');
    752  - exptag.href = jsonData;
    753  - }
    754  - 
    755  - function exportPNG() {
    756  - var png64 = cy.png();
    757  - var exptag = document.getElementById('export-png');
    758  - exptag.href = png64;
    759  - }
    760  - 
    761  - function exportJPEG() {
    762  - var jpg64 = cy.png();
    763  - var exptag = document.getElementById('export-jpeg');
    764  - exptag.href = jpg64;
    765  - }
    766  - 
    767  - function downloadCSV(csvType) {
    768  - var queryStr = 'MATCH (date:Date) MATCH (user:Username) RETURN date, user';
    769  - var users = new Array();
    770  - 
    771  - session.run(queryStr)
    772  - .subscribe({
    773  - onNext: function(record) {
    774  - nodeData = record.get("user");
    775  - dateData = record.get("date");
    776  - users.push([nodeData.properties.user, nodeData.properties.counts,
    777  - nodeData.properties.counts4624, nodeData.properties.counts4625,
    778  - nodeData.properties.counts4768, nodeData.properties.counts4769,
    779  - nodeData.properties.counts4776
    780  - ]);
    781  - starttime = dateData.properties.start;
    782  - endtime = dateData.properties.end;
    783  - },
    784  - onCompleted: function() {
    785  - session.close();
    786  - 
    787  - var startDate = new Date(starttime);
    788  - var rangeHours = Math.floor((Date.parse(endtime) - Date.parse(starttime)) / (1000 * 60 * 60)) + 1;
    789  - var rawDate = "username,";
    790  - if (csvType == "detail") {
    791  - rawDate += "id,";
    792  - }
    793  - var countData = "";
    794  - for (i = 0; i < rangeHours; i++) {
    795  - rawDate += startDate.toISOString() + ",";
    796  - startDate.setHours(startDate.getHours() + 1);
    797  - }
    798  - 
    799  - if (csvType == "summary") {
    800  - for (i = 0; i < users.length; i++) {
    801  - countData += users[i][0] + "," + users[i][1] + "\r\n";
    802  - }
    803  - } else if (csvType == "detail") {
    804  - for (i = 0; i < users.length; i++) {
    805  - countData += users[i][0];
    806  - for (j = 2; j <= 6; j++) {
    807  - if (j == 2) {
    808  - countData += ",4624,"
    809  - } else if (j == 3) {
    810  - countData += ",4625,"
    811  - } else if (j == 4) {
    812  - countData += ",4768,"
    813  - } else if (j == 5) {
    814  - countData += ",4769,"
    815  - } else if (j == 6) {
    816  - countData += ",4776,"
    817  - }
    818  - countData += users[i][j] + "\r\n";
    819  - }
    820  - }
    821  - }
    822  - 
    823  - rawDate += "\r\n" + countData
    824  - var downLoadLink = document.createElement("a");
    825  - downLoadLink.download = "timeline.csv";
    826  - downLoadLink.href = URL.createObjectURL(new Blob([rawDate], {type: "application.csv"}));
    827  - downLoadLink.dataset.downloadurl = ["application/csv", downLoadLink.download, downLoadLink.href].join(":");
    828  - downLoadLink.click();
    829  - },
    830  - onError: function(error) {
    831  - console.log("Error: ", error);
    832  - }
    833  - });
    834  - }
    835  - 
    836  - function downloadSummary() {
    837  - downloadCSV("summary")
    838  - }
    839  - 
    840  - function downloadDetail() {
    841  - downloadCSV("detail")
    842  - }
    843  - 
    844  - function createTimeline(queryStr, tableType) {
    845  - var users = new Array();
    846  - var starttime = "";
    847  - var endtime = "";
    848  - var weekTbl = new Array("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat");
    849  - var bgcolorTbl = new Array("#ff7f50", "#efefef", "#efefef", "#efefef", "#efefef", "#efefef", "#b0c4de");
    850  - 
    851  - if (tableType == "all") {
    852  - var span = 'rowspan = "4"';
    853  - }
    854  - if (tableType == "search") {
    855  - var span = 'rowspan = "4" colspan="2"';
    856  - }
    857  - var html = '<div class="table-responsive"><table class="table table-bordered table-condensed table-striped" style="background-color:#EEE;"><thead><tr>\
    858  - <th ' + span + '>Username</th>';
    859  - 
    860  - session.run(queryStr)
    861  - .subscribe({
    862  - onNext: function(record) {
    863  - dateData = record.get("date");
    864  - nodeData = record.get("user");
    865  - users.push([nodeData.properties.user, nodeData.properties.counts, nodeData.properties.detect, nodeData.properties.rights, nodeData.properties.counts4624,
    866  - nodeData.properties.counts4625, nodeData.properties.counts4768, nodeData.properties.counts4769, nodeData.properties.counts4776
    867  - ]);
    868  - starttime = dateData.properties.start;
    869  - endtime = dateData.properties.end;
    870  - },
    871  - onCompleted: function() {
    872  - session.close();
    873  - var startDate = new Date(starttime);
    874  - var rangeHours = Math.floor((Date.parse(endtime) - Date.parse(starttime)) / (1000 * 60 * 60)) + 1;
    875  - var thisyear = startDate.getFullYear();
    876  - var thismonth = startDate.getMonth();
    877  - var thisday = startDate.getDate();
    878  - var thishour = startDate.getHours();
    879  - var thisdow = startDate.getDay();
    880  - var nextyear = null;
    881  - var nrangeHours = 0;
    882  - var weekd = 0;
    883  - for (i = 1; i <= rangeHours; i++) {
    884  - startDate.setHours(startDate.getHours() + 1);
    885  - if (startDate.getFullYear() != thisyear) {
    886  - html += '<th colspan="' + (i - nrangeHours) + '">' + thisyear + '</th>';
    887  - thisyear = startDate.getFullYear();
    888  - nrangeHours = i;
    889  - }
    890  - }
    891  - html += '<th colspan="' + (rangeHours - nrangeHours) + '">' + thisyear + '</th></tr><tr>';
    892  - 
    893  - nrangeHours = 0;
    894  - startDate = new Date(starttime);
    895  - for (i = 1; i <= rangeHours; i++) {
    896  - startDate.setHours(startDate.getHours() + 1);
    897  - if (startDate.getMonth() != thismonth) {
    898  - html += '<th colspan="' + (i - nrangeHours) + '">' + (thismonth + 1) + '</th>';
    899  - thismonth = startDate.getMonth();
    900  - nrangeHours = i;
    901  - }
    902  - }
    903  - html += '<th colspan="' + (rangeHours - nrangeHours) + '">' + (thismonth + 1) + '</th></tr><tr>';
    904  - 
    905  - nrangeHours = 0;
    906  - startDate = new Date(starttime);
    907  - for (i = 1; i <= rangeHours; i++) {
    908  - startDate.setHours(startDate.getHours() + 1);
    909  - if (startDate.getDate() != thisday) {
    910  - html += '<th bgcolor="' + bgcolorTbl[thisdow + weekd] + '" colspan="' + (i - nrangeHours) + '">' + thisday + '(' + weekTbl[thisdow + weekd] + ')</th>';
    911  - if (thisdow + weekd >= 6) {
    912  - thisdow = 0 - (weekd + 1);
    913  - }
    914  - thisday = startDate.getDate();
    915  - nrangeHours = i;
    916  - weekd += 1;
    917  - }
    918  - }
    919  - html += '<th bgcolor="' + bgcolorTbl[thisdow + weekd] + '" colspan="' + (rangeHours - nrangeHours) + '">' + thisday + '(' + weekTbl[thisdow + weekd] + ')</th></tr><tr>';
    920  - 
    921  - for (i = 0; i < rangeHours; i++) {
    922  - html += '<th>' + thishour + '</th>';
    923  - thishour += 1;
    924  - if (thishour >= 24) {
    925  - thishour = 0;
    926  - }
    927  - }
    928  - 
    929  - html += '</tr></thead><tbody>';
    930  - 
    931  - if (tableType == "all") {
    932  - for (i = 0; i < users.length; i++) {
    933  - if (users[i][3] == "system") {
    934  - html += '<tr><td><font color="#ff7f50">' + users[i][0] + '</font></td>';
    935  - } else {
    936  - html += '<tr><td>' + users[i][0] + '</td>';
    937  - }
    938  - rowdata = users[i][1].split(",");
    939  - alerts = users[i][2].split(",");
    940  - for (j = 0; j < rowdata.length; j++) {
    941  - if (alerts[j] > 17) {
    942  - html += '<td bgcolor="#ff5aee">' + rowdata[j].split(".")[0] + '</td>';
    943  - } else if (alerts[j] > 16) {
    944  - html += '<td bgcolor="#ff8aee">' + rowdata[j].split(".")[0] + '</td>';
    945  - } else if (alerts[j] > 13) {
    946  - html += '<td bgcolor="#ffbaee">' + rowdata[j].split(".")[0] + '</td>';
    947  - } else if (alerts[j] > 10) {
    948  - html += '<td bgcolor="#ffeaee">' + rowdata[j].split(".")[0] + '</td>';
    949  - } else {
    950  - html += '<td>' + rowdata[j].split(".")[0] + '</td>';
    951  - }
    952  - }
    953  - html += '</tr>';
    954  - }
    955  - }
    956  - 
    957  - if (tableType == "search") {
    958  - for (i = 0; i < users.length; i++) {
    959  - if (users[i][3] == "system") {
    960  - html += '<tr><td rowspan = "5"><font color="#ff7f50">' + users[i][0] + '</font></td>';
    961  - } else {
    962  - html += '<tr><td rowspan = "5">' + users[i][0] + '</td>';
    963  - }
    964  - 
    965  - for (j = 4; j <= 8; j++) {
    966  - rowdata = users[i][j].split(",");
    967  - alerts = users[i][2].split(",");
    968  - if (j == 4) {
    969  - html += '<td>4624</td>';
    970  - } else if (j == 5) {
    971  - html += '<td>4625</td>';
    972  - } else if (j == 6) {
    973  - html += '<td>4768</td>';
    974  - } else if (j == 7) {
    975  - html += '<td>4769</td>';
    976  - } else if (j == 8) {
    977  - html += '<td>4776</td>';
    978  - }
    979  - for (k = 0; k < rowdata.length; k++) {
    980  - if (alerts[k] > 17) {
    981  - html += '<td bgcolor="#ff5aee">' + rowdata[k].split(".")[0] + '</td>';
    982  - } else if (alerts[k] > 16) {
    983  - html += '<td bgcolor="#ff8aee">' + rowdata[k].split(".")[0] + '</td>';
    984  - } else if (alerts[k] > 13) {
    985  - html += '<td bgcolor="#ffbaee">' + rowdata[k].split(".")[0] + '</td>';
    986  - } else if (alerts[k] > 10) {
    987  - html += '<td bgcolor="#ffeaee">' + rowdata[k].split(".")[0] + '</td>';
    988  - } else {
    989  - html += '<td>' + rowdata[k].split(".")[0] + '</td>';
    990  - }
    991  - }
    992  - html += '</tr>';
    993  - }
    994  - }
    995  - }
    996  - html += '</tbody></table></div>';
    997  - 
    998  - var timelineElem = document.getElementById("cy");
    999  - timelineElem.innerHTML = html;
    1000  - },
    1001  - onError: function(error) {
    1002  - console.log("Error: ", error);
    1003  - }
    1004  - });
    1005  - }
    1006  - 
    1007  - function createAlltimeline() {
    1008  - var queryStr = 'MATCH (date:Date) MATCH (user:Username) RETURN date, user';
    1009  - createTimeline(queryStr, "all");
    1010  - }
    1011  - 
    1012  - function searchTimeline() {
    1013  - var selectVal = document.getElementById("InputSelect").value;
    1014  - var setStr = document.getElementById("query-input").value;
    1015  - 
    1016  - if (selectVal == "Username") {
    1017  - whereStr = 'user.user =~ "' + setStr + '" ';
    1018  - } else {
    1019  - searchError();
    1020  - }
    1021  - 
    1022  - for (i = 1; i <= currentNumber; i++) {
    1023  - if (document.getElementById("query-input" + i).value) {
    1024  - ruleStr = document.getElementById("InputRule" + i).value;
    1025  - if (document.getElementById("InputSelect" + i).value == "Username") {
    1026  - whereStr += ruleStr + ' user.user =~ "' + document.getElementById("query-input" + i).value + '" ';
    1027  - } else {
    1028  - searchError();
    1029  - }
    1030  - }
    1031  - }
    1032  - var queryStr = 'MATCH (date:Date) MATCH (user:Username) WHERE (' + whereStr + ') RETURN date, user';
    1033  - createTimeline(queryStr, "search");
    1034  - }
    1035  - 
    1036  - function searchError() {
    1037  - var elemMsg = document.getElementById("error");
    1038  - elemMsg.innerHTML =
    1039  - '<div class="alert alert-warning alert-dismissible" id="alertfadeout" role="alert"><button type="button" class="close" data-dismiss="alert" aria-label="close">\
    1040  - <span aria-hidden="true">×</span></button><strong>WARNING</strong>: Search failed!</div>';
    1041  - $(document).ready(function() {
    1042  - $('#alertfadeout').fadeIn(2000).delay(4000).fadeOut(2000);
    1043  - });
    1044  - }
    1045  - 
    1046  - function file_upload() {
    1047  - var upfile = document.getElementById("lefile");
    1048  - var timezone = document.getElementById("utcTime").value;
    1049  - document.getElementById("uploadBar").innerHTML = '';
    1050  - document.getElementById("status").innerHTML = '';
    1051  - 
    1052  - var formData = new FormData();
    1053  - for (var i = 0; i < upfile.files.length; i++) {
    1054  - sendFile = "file" + i
    1055  - formData.append(sendFile, upfile.files[i]);
    1056  - }
    1057  - formData.append("timezone", timezone);
    1058  - var xmlhttp = new XMLHttpRequest();
    1059  - xmlhttp.upload.addEventListener("progress", progressHandler, false);
    1060  - xmlhttp.addEventListener("load", completeHandler, false);
    1061  - xmlhttp.addEventListener("error", errorHandler, false);
    1062  - xmlhttp.addEventListener("abort", abortHandler, false);
    1063  - xmlhttp.open("POST", "upload", true);
    1064  - xmlhttp.send(formData);
    1065  - }
    1066  - 
    1067  - function progressHandler(event) {
    1068  - var percent = (event.loaded / event.total) * 100;
    1069  - document.getElementById("uploadBar").innerHTML = '<h4>Upload ...</h4><div class="progress"><div class="progress-bar progress-bar-striped active" role="progressbar" style="width: ' + Math.round(percent) + '%;">' + Math.round(percent) + '%</div></div>';
    1070  - }
    1071  - 
    1072  - var parse_status = false;
    1073  - 
    1074  - function completeHandler(event) {
    1075  - if (event.target.responseText == "FAIL") {
    1076  - document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: Upload Failed!</div>';
    1077  - }
    1078  - if (event.target.responseText == "SUCCESS") {
    1079  - parse_status = false
    1080  - document.getElementById("uploadBar").innerHTML = '<h4>Upload ...</h4><div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" style="width: 100%;">SUCCESS</div></div>';
    1081  - var loop = function() {
    1082  - if (parse_status == false) {
    1083  - setTimeout(loop, 2000);
    1084  - }
    1085  - parseEVTX();
    1086  - }
    1087  - loop();
    1088  - }
    1089  - }
    1090  - 
    1091  - function errorHandler(event) {
    1092  - document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: Upload Failed!</div>';
    1093  - }
    1094  - 
    1095  - function abortHandler(event) {
    1096  - document.getElementById("status").innerHTML = '<div class="alert alert-info">Upload Aborted</div>';
    1097  - }
    1098  - 
    1099  - $('input[id=lefile]').change(function() {
    1100  - var inFile = "";
    1101  - var fileList = document.getElementById("lefile").files;
    1102  - if ( 1 < fileList.length) {
    1103  - inFile += "selected " + fileList.length + " files."
    1104  - } else {
    1105  - inFile += fileList[0].name
    1106  - }
    1107  - $('#evtx_name').val(inFile.replace("C:\\fakepath\\", ""));
    1108  - });
    1109  - 
    1110  - function parseEVTX() {
    1111  - var xmlhttp2 = new XMLHttpRequest();
    1112  - xmlhttp2.open("GET", "/log");
    1113  - xmlhttp2.send();
    1114  - xmlhttp2.onreadystatechange = function() {
    1115  - if (xmlhttp2.readyState == 4) {
    1116  - if (xmlhttp2.status == 200) {
    1117  - var logdata = xmlhttp2.responseText.split(/\r\n|\r|\n/);
    1118  - var allrecode = logdata[3].split(" ")[5].replace(".", "");
    1119  - var nowdata = logdata[logdata.length - 2];
    1120  - if (nowdata.indexOf("Now loading") != -1) {
    1121  - var recordnum = nowdata.split(" ")[3];
    1122  - var percent = (recordnum / allrecode) * 100;
    1123  - document.getElementById("uploadBar").innerHTML = '<h4>Parsing ...</h4><div class="progress"><div class="progress-bar progress-bar-striped active" role="progressbar" style="width: ' + Math.round(percent) + '%;">' + Math.round(percent) + '%</div></div>';
    1124  - } else if (nowdata.indexOf("Script end") != -1) {
    1125  - document.getElementById("uploadBar").innerHTML = '<h4>Parsing ...</h4><div class="progress"><div class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" style="width: 100%;">SUCCESS</div></div>';
    1126  - document.getElementById("status").innerHTML = '<div class="alert alert-info"><strong>Import Success</strong>: You need to reload the web page.</div>';
    1127  - parse_status = true;
    1128  - } else if (nowdata.indexOf("[!]") != -1) {
    1129  - document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: EVTX parse Failed!</div>';
    1130  - parse_status = true;
    1131  - }
    1132  - } else {
    1133  - document.getElementById("status").innerHTML = '<div class="alert alert-danger"><strong>ERROR</strong>: logontracer.log status = ' + xmlhttp2.status + '</div>';
    1134  - parse_status = true;
    1135  - }
    1136  - }
    1137  - }
    1138  - }
    1139  - </script>
     220 + $('#evtx_name').val(inFile.replace("C:\\fakepath\\", ""));
     221 + });
     222 + </script>
    1140 223  </body>
    1141 224   
    1142 225  </html>
    skipped 1 lines
  • ■ ■ ■ ■ ■ ■
    templates/timeline.html
     1 +<!DOCTYPE html>
     2 +<html lang="en">
     3 + 
     4 +<head>
     5 + <meta charset="utf-8">
     6 + <title>LogonTracer</title>
     7 + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
     8 + <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/jquery.qtip.css" integrity="sha384-EG4MkHYaMXjB6f2q1t0Jfs+W6DpGsGZls4D6PYHr9yhXwZf27Z10ReappeV2ZXcU" crossorigin="anonymous">
     9 + <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
     10 + <script src="https://cdnjs.cloudflare.com/ajax/libs/qtip2/2.2.1/jquery.qtip.js" integrity="sha384-6pAYkjo39N26cI9QEzy7zTD9xr9XzSnaWywG02LeFyoJnBEyYvWvqomLU+uGAlaw" crossorigin="anonymous"></script>
     11 + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
     12 + <!-- Neo4j JavaScript Driver -->
     13 + <script src="https://cdn.rawgit.com/neo4j/neo4j-javascript-driver/1.4.1/lib/browser/neo4j-web.min.js" integrity="sha384-xu5q3iV0ueZtK1T6RpPoUqv4VlVuEJpax+yyNmlN6CuOtT+SeUe1dqlI7MHpIN0p" crossorigin="anonymous"></script>
     14 + <script src="static/script.js"></script>
     15 +</head>
     16 + 
     17 +<body>
     18 + <nav class="navbar navbar-default">
     19 + <div class="container-fluid">
     20 + <a class="navbar-brand" href="#">Timeline</a>
     21 + <div class="collapse navbar-collapse">
     22 + <form class="navbar-form navbar-left" role="search">
     23 + <div class="form-group">
     24 + <label class="sr-only" for="InputSelect">select</label>
     25 + <select class="form-control" id="InputSelect">
     26 + <option>Username</option>
     27 + </select>
     28 + <input class="form-control" type="text" value="administrator" id="query-input" size="10">
     29 + <div id="itemForm"></div>
     30 + </div>
     31 + <input type="button" class="btn btn-default" value="+" onclick="ItemField.add();" />
     32 + <input type="button" class="btn btn-default" value="-" onclick="ItemField.del();" />
     33 + <button type="button" class="btn btn-default" onclick="searchTimeline()">search</button>
     34 + <button type="button" class="btn btn-default" onclick="createAlltimeline()">all</button>
     35 + <div class="btn-group">
     36 + <button class="btn btn-default dropdown-toggle" type="button" data-toggle="dropdown" aria-expanded="false">
     37 + Download <span class="caret"></span>
     38 + </button>
     39 + <ul class="dropdown-menu" role="menu">
     40 + <li role="presentation"><a onclick="downloadSummary()">Summary</a></li>
     41 + <li role="presentation"><a onclick="downloadDetail()">Details</a></li>
     42 + </ul>
     43 + </div>
     44 + </form>
     45 + </div>
     46 + </div>
     47 + </nav>
     48 + 
     49 + <div class="container-fluid">
     50 + <div class="row">
     51 + <div class="col-sm-12 col-md-12 main">
     52 + <div id="error"></div>
     53 + <div id="cy" style="height:900px;"></div>
     54 + </div>
     55 + </div>
     56 + </div>
     57 + <script type="text/javascript">
     58 + var neo = neo4j.default;
     59 + //Neo4j access settings
     60 + var driver = neo.driver("bolt://{{ server_ip }}", neo.auth.basic("{{ neo4j_user }}", "{{ neo4j_password }}"));
     61 + var session = driver.session();
     62 + createAlltimeline();
     63 + 
     64 + var currentNumber = 0;
     65 + var ItemField = {
     66 + currentNumber: 0,
     67 + itemTemplate: '<label class="sr-only" for="InputSelect">select</label>\
     68 + <select class="form-control" id="InputSelect_count_">\
     69 + <option>Username</option></select>\
     70 + <input class="form-control" type="text" id="query-input_count_" size="10">',
     71 + add: function() {
     72 + currentNumber++;
     73 + if (currentNumber <= 10) {
     74 + var new_item = this.itemTemplate.replace(/_count_/mg, currentNumber);
     75 + var new_area = document.createElement("div");
     76 + new_area.setAttribute("id", "item" + currentNumber);
     77 + var field = document.getElementById('itemForm');
     78 + field.appendChild(new_area);
     79 + document.getElementById('item' + currentNumber).innerHTML = new_item;
     80 + }
     81 + },
     82 + del: function() {
     83 + if (currentNumber == 0) {
     84 + return;
     85 + }
     86 + var field = document.getElementById('itemForm');
     87 + field.removeChild(field.lastChild);
     88 + currentNumber--;
     89 + }
     90 + }
     91 + </script>
     92 +</body>
     93 + 
     94 +</html>
     95 + 
Please wait...
Page is in error, reload to recover