1 1 function buildGraph(graph, path, root) { 2 + var objidList = [] 2 3 for (idx in path) { 3 4 if (Object.keys(path[idx]).length == 3) { 4 5 objid = parseInt(path[idx].identity.low) + 100; 5 6 } else { 6 7 objid = parseInt(path[idx].identity.low) + 1000; 7 8 } 8 - 9 9 // Node 10 10 if (Object.keys(path[idx]).length == 3) { 11 11 var ndupflg = false; skipped 5 lines 17 17 if (ndupflg) { 18 18 continue; 19 19 } 20 - 21 20 nprivilege = ""; 22 21 nsub = ""; 23 22 ncategory = ""; skipped 92 lines 116 115 }); 117 116 } else { 118 117 // Relationship 119 - var ldupflg = false; 120 - for (nidx in graph.edges) { 121 - if (graph.edges[nidx].data.objid == objid) { 122 - ldupflg = true; 123 - } 124 - } 125 - if (ldupflg) { 118 + if (objidList.indexOf(objid) >= 0) { 126 119 continue; 120 + } else { 121 + objidList.push(objid) 127 122 } 123 + 128 124 if (path[idx].type == "Event") { 129 125 var label_count = document.getElementById("label-count").checked; 130 126 var label_type = document.getElementById("label-type").checked; 131 127 var label_authname = document.getElementById("label-authname").checked; 128 + var sourceid = parseInt(path[parseInt(idx) - 1].identity.low) + 100 129 + var targetid = parseInt(path[parseInt(idx) + 1].identity.low) + 100 130 + 131 + var filterdArray = $.grep(graph.edges, 132 + function(elem, index, array) { 133 + return (!(elem.data.source == sourceid && elem.data.target == targetid && elem.data.label == path[idx].type && 134 + elem.data.eid == path[idx].properties.id && elem.data.logontype == path[idx].properties.logintype && 135 + elem.data.status == path[idx].properties.status && elem.data.authname == path[idx].properties.authname)); 136 + } 137 + ); 138 + var matchArray = $.grep(graph.edges, 139 + function(elem, index, array) { 140 + return (elem.data.source == sourceid && elem.data.target == targetid && elem.data.label == path[idx].type && 141 + elem.data.eid == path[idx].properties.id && elem.data.logontype == path[idx].properties.logintype && 142 + elem.data.status == path[idx].properties.status && elem.data.authname == path[idx].properties.authname); 143 + } 144 + ); 145 + var ecount = parseInt(path[idx].properties.count) 146 + if (Object.keys(matchArray).length) { 147 + ecount = ecount + parseInt(matchArray[0].data.count) 148 + } 149 + graph.edges = filterdArray 132 150 var ename = path[idx].properties.id; 133 151 if (label_count) { 134 152 ename += " : " + path[idx].properties.count; skipped 7 lines 142 160 graph.edges.push({ 143 161 "data": { 144 162 "id": objid, 145 - "source": parseInt(path[parseInt(idx) - 1].identity.low) + 100, 146 - "target": parseInt(path[parseInt(idx) + 1].identity.low) + 100, 163 + "source": sourceid, 164 + "target": targetid, 147 165 "objid": objid, 148 166 "elabel": ename, 149 167 "label": path[idx].type, 150 168 "distance": 5, 151 169 "ntype": "edge", 152 - "eid": path[idx].properties.id, 153 - "count": path[idx].properties.count, 154 - "logontype": path[idx].properties.logintype, 170 + "eid": parseInt ( path[idx].properties.id) , 171 + "count": ecount, 172 + "logontype": String ( path[idx].properties.logintype) , 155 173 "status": path[idx].properties.status, 156 174 "authname": path[idx].properties.authname 157 175 } skipped 13 lines 171 189 } 172 190 } 173 191 } 174 - 175 192 return (graph); 176 193 } 177 194 skipped 3 lines 181 198 var flagCircle = document.getElementById("modeCircle").checked; 182 199 var flagTree = document.getElementById("modeTree").checked; 183 200 var flagMode = ""; 184 - 185 201 if (flagGrid) { 186 202 flagMode = "grid"; 187 203 } skipped 6 lines 194 210 if (flagTree) { 195 211 flagMode = "breadthfirst"; 196 212 } 197 - 198 - 199 213 cy = cytoscape({ 200 214 container: document.getElementById("cy"), 201 215 boxSelectionEnabled: false, skipped 40 lines 242 256 padding: 10 243 257 } 244 258 }); 245 - 246 259 cy.on("layoutstop", function() { 247 260 loading.classList.add("loaded"); 248 261 }); 249 - 250 262 cy.nodes().forEach(function(ele) { 251 263 ele.qtip({ 252 264 content: { skipped 10 lines 263 275 } 264 276 }); 265 277 }); 266 - 267 278 cy.edges().forEach(function(ele) { 268 279 ele.qtip({ 269 280 content: { skipped 12 lines 282 293 }); 283 294 } 284 295 296 + /* 297 + qtipNode 298 + This function generate the description text for each node. 299 + */ 285 300 function qtipNode(ndata) { 286 301 var qtext = 'Name: ' + ndata._private.data["nlabel"]; 287 302 if (ndata._private.data["ntype"] == "User") { skipped 8 lines 296 311 qtext += '<br>Category: ' + ndata._private.data["ncategory"]; 297 312 qtext += '<br>Subcategory: ' + ndata._private.data["nsub"]; 298 313 } 299 - 300 314 if (ndata._private.data["ntype"] != "Policy") { 301 315 qtext += '<br><button type="button" class="btn btn-primary btn-xs" onclick="createRankQuery(\'' + ndata._private.data["nlabel"] + '\',\'' + ndata._private.data["ntype"] + '\')">search</button>'; 302 316 } 303 - 304 317 return qtext; 305 318 } 306 319 320 + /* 321 + qtipEdge 322 + This function generate the description text for each edge. 323 + */ 307 324 function qtipEdge(ndata) { 308 325 var qtext = ""; 309 326 if (ndata._private.data["label"] == "Event") { skipped 24 lines 334 351 return qtext; 335 352 } 336 353 354 + /* 355 + createAllQuery 356 + This function execute neo4j query and show all users in specific time period with graph. 357 + The result is filtered by Event ID selected in the check box. 358 + */ 337 359 function createAllQuery() { 338 - eidStr = getQueryID(); 360 + var eidStr = getQueryID(); 361 + var dateStr = getDateRange(); 339 362 eidStr = eidStr.slice(4); 340 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE ' + eidStr + ' RETURN user, event, ip'; 363 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE ' + eidStr + dateStr + ' RETURN user, event, ip'; 341 364 //console.log(queryStr); 342 365 executeQuery(queryStr, "noRoot"); 343 366 } 344 367 368 + /* 369 + createSystemQuery 370 + This function execute neo4j query and show all system privilege users in specific time period with graph. 371 + The result is filtered by Event ID selected in the check box. 372 + */ 345 373 function createSystemQuery() { 346 - eidStr = getQueryID(); 347 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE user.rights = "system" ' + eidStr + ' RETURN user, event, ip'; 374 + var eidStr = getQueryID(); 375 + var dateStr = getDateRange(); 376 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE user.rights = "system" ' + eidStr + dateStr + ' RETURN user, event, ip'; 348 377 //console.log(queryStr); 349 378 executeQuery(queryStr, "noRoot"); 350 379 } 351 380 381 + /* 382 + createRDPQuery 383 + This function execute neo4j query and show RDP logon users in specific time period with graph. 384 + The result is filtered by Event ID selected in the check box. 385 + */ 352 386 function createRDPQuery() { 353 - eidStr = getQueryID(); 354 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 10 ' + eidStr + ' RETURN user, event, ip'; 387 + var eidStr = getQueryID(); 388 + var dateStr = getDateRange(); 389 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 10 ' + eidStr + dateStr + ' RETURN user, event, ip'; 355 390 //console.log(queryStr); 356 391 executeQuery(queryStr, "noRoot"); 357 392 } 358 393 394 + /* 395 + createNetQuery 396 + This function execute neo4j query and show users who logon via network in specific time period with graph. 397 + The result is filtered by Event ID selected in the check box. 398 + */ 359 399 function createNetQuery() { 360 - eidStr = getQueryID(); 361 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 3 ' + eidStr + ' RETURN user, event, ip'; 400 + var eidStr = getQueryID(); 401 + var dateStr = getDateRange(); 402 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 3 ' + eidStr + dateStr + ' RETURN user, event, ip'; 362 403 //console.log(queryStr); 363 404 executeQuery(queryStr, "noRoot"); 364 405 } 365 406 407 + /* 408 + createBatchQuery 409 + This function execute neo4j query and show users who logon by batch script in specific time period with graph. 410 + The result is filtered by Event ID selected in the check box. 411 + */ 366 412 function createBatchQuery() { 367 - eidStr = getQueryID(); 368 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 4 ' + eidStr + ' RETURN user, event, ip'; 413 + var eidStr = getQueryID(); 414 + var dateStr = getDateRange(); 415 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 4 ' + eidStr + dateStr + ' RETURN user, event, ip'; 369 416 //console.log(queryStr); 370 417 executeQuery(queryStr, "noRoot"); 371 418 } 372 419 420 + /* 421 + createServiceQuery 422 + This function execute neo4j query and show users who logon from windows service in specific time period with graph. 423 + The result is filtered by Event ID selected in the check box. 424 + */ 373 425 function createServiceQuery() { 374 - eidStr = getQueryID(); 375 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 5 ' + eidStr + ' RETURN user, event, ip'; 426 + var eidStr = getQueryID(); 427 + var dateStr = getDateRange(); 428 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.logintype = 5 ' + eidStr + dateStr + ' RETURN user, event, ip'; 376 429 //console.log(queryStr); 377 430 executeQuery(queryStr, "noRoot"); 378 431 } 379 432 433 + /* 434 + create14068Query 435 + This function execute neo4j query and show users who attempted to exploit MS14-068 in specific time period with graph. 436 + */ 380 437 function create14068Query() { 381 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.status =~ ".*0F" AND event.id = 4769 RETURN user, event, ip'; 438 + var dateStr = getDateRange(); 439 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.status =~ ".*0F" AND event.id = 4769 ' + dateStr + ' RETURN user, event, ip'; 382 440 //console.log(queryStr); 383 441 executeQuery(queryStr, "noRoot"); 384 442 } 385 443 444 + /* 445 + createFailQuery 446 + This function execute neo4j query and show users who failed to logon in specific time period with graph. 447 + */ 386 448 function createFailQuery() { 387 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.id = 4625 RETURN user, event, ip'; 449 + var dateStr = getDateRange(); 450 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.id = 4625 ' + dateStr + ' RETURN user, event, ip'; 388 451 //console.log(queryStr); 389 452 executeQuery(queryStr, "noRoot"); 390 453 } 391 454 455 + /* 456 + createNTLMQuery 457 + This function execute neo4j query and show users who login with NTLM authentication in specific time period with graph. 458 + */ 392 459 function createNTLMQuery() { 393 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.id = 4624 and event.authname = "NTLM" and event.logintype = 3 RETURN user, event, ip'; 460 + var dateStr = getDateRange(); 461 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE event.id = 4624 and event.authname = "NTLM" and event.logintype = 3 ' + dateStr + ' RETURN user, event, ip'; 394 462 //console.log(queryStr); 395 463 executeQuery(queryStr, "noRoot"); 396 464 } 397 465 466 + /* 467 + adddelUserQuery 468 + This function execute neo4j query and show users who had be created or deleted in specific time period with graph. 469 + */ 398 470 function adddelUsersQuery() { 399 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (user.status =~ "Created.*") OR (user.status =~ ".*Deleted.*") OR (user.status =~ ".*RemoveGroup.*") OR (user.status =~ ".*AddGroup.*") RETURN user, event, ip'; 471 + var dateStr = getDateRange(); 472 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (user.status =~ "Created.*") OR (user.status =~ ".*Deleted.*") OR (user.status =~ ".*RemoveGroup.*") OR (user.status =~ ".*AddGroup.*") ' + dateStr + ' RETURN user, event, ip'; 400 473 //console.log(queryStr); 401 474 executeQuery(queryStr, "noRoot"); 402 475 } 403 476 477 + /* 478 + dcsQuery 479 + This function execute neo4j query and show users who executed DCSync or DCShadow in specific time period with graph. 480 + */ 404 481 function dcsQuery() { 405 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (user.status =~ ".*DCSync.*") OR (user.status =~ ".*DCShadow.*") RETURN user, event, ip'; 482 + var dateStr = getDateRange(); 483 + var queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (user.status =~ ".*DCSync.*") OR (user.status =~ ".*DCShadow.*") ' + dateStr + ' RETURN user, event, ip'; 406 484 //console.log(queryStr); 407 485 executeQuery(queryStr, "noRoot"); 408 486 } 409 487 488 + /* 489 + dcsQuery 490 + This function execute neo4j query and show users who executed DCSync or DCShadow in specific time period with graph. 491 + */ 410 492 function createDomainQuery() { 411 - queryStr = 'MATCH (user)-[event:Group]-(ip) RETURN user, event, ip'; 493 + var queryStr = 'MATCH (user)-[event:Group]-(ip) RETURN user, event, ip'; 412 494 //console.log(queryStr); 413 495 executeQuery(queryStr, "noRoot"); 414 496 } 415 497 498 + /* 499 + policyQuery 500 + This function execute neo4j query and show users who changed the audit policy in specific time period with graph. 501 + */ 416 502 function policyQuery() { 417 - queryStr = 'MATCH (user)-[event:Policy]-(ip) RETURN user, event, ip'; 503 + var dateStr = getDateRange(); 504 + dateStr = dateStr.slice(5); 505 + queryStr = 'MATCH (user)-[event:Policy]-(ip) WHERE ' + dateStr + ' RETURN user, event, ip'; 418 506 //console.log(queryStr); 419 507 executeQuery(queryStr, "noRoot"); 420 508 } 421 509 422 510 function createRankQuery(setStr, qType) { 511 + var dateStr = getDateRange(); 423 512 if (qType == "User") { 424 513 whereStr = 'user.user = "' + setStr + '" '; 425 514 } skipped 3 lines 429 518 430 519 if (qType != "Domain") { 431 520 eidStr = getQueryID(); 432 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (' + whereStr + ') ' + eidStr + ' RETURN user, event, ip'; 521 + queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (' + whereStr + ') ' + eidStr + dateStr + ' RETURN user, event, ip'; 433 522 } else { 434 523 queryStr = 'MATCH (user)-[event:Group]-(ip) WHERE user.domain = "' + setStr + '" RETURN user, event, ip' 435 524 } skipped 1 lines 437 526 executeQuery(queryStr, setStr); 438 527 } 439 528 529 + /* 530 + getQueryID 531 + This function generate the neo4j query strings to filter Windows Event ID and ID count. 532 + */ 440 533 function getQueryID() { 441 534 var id4624Ch = document.getElementById("id4624").checked; 442 535 var id4625Ch = document.getElementById("id4625").checked; skipped 23 lines 466 559 return eidStr; 467 560 } 468 561 562 + /* 563 + getDateRange 564 + This function generates a neo4j query strings to filter events in specific time period. 565 + */ 566 + function getDateRange() { 567 + var fromDate = new Date(document.getElementById("from-date").value).getTime() / 1000; 568 + var toDate = new Date(document.getElementById("to-date").value).getTime() / 1000; 569 + var dateStr = " AND (event.date >= " + fromDate + " AND event.date <= " + toDate + ")"; 570 + 571 + return dateStr; 572 + } 573 + 574 + /* 575 + createQuery 576 + This function generates a neo4j query strings from search box and execute the query. 577 + */ 469 578 function createQuery() { 470 579 var selectVal = document.getElementById("InputSelect").value; 471 580 var setStr = document.getElementById("query-input").value; 581 + var dateStr = getDateRange(); 472 582 473 583 if (selectVal == "Username") { 474 584 whereStr = 'user.user =~ "' + setStr + '" '; skipped 17 lines 492 602 } 493 603 494 604 eidStr = getQueryID() 495 - queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (' + whereStr + ') ' + eidStr + ' RETURN user, event, ip'; 605 + queryStr = 'MATCH (user)-[event:Event]-(ip) WHERE (' + whereStr + ') ' + eidStr + dateStr + ' RETURN user, event, ip'; 496 606 //console.log(queryStr); 497 607 executeQuery(queryStr, setStr); 498 608 } 499 609 610 + /* 611 + searchPath 612 + This function execute a neo4j query strings to search the shortest path to system privilege in specific time period. 613 + */ 500 614 function searchPath() { 501 615 var setStr = document.getElementById("query-input").value; 616 + var dateStr = getDateRange(); 617 + dateStr = dateStr.slice(5); 502 618 503 619 queryStr = 'MATCH (from:Username) WHERE from.user = "' + setStr + '" \ 504 620 MATCH (to:Username) WHERE to.rights = "system" \ 505 621 MATCH (user:Username) WHERE user IN shortestPath((from)-[:Event*]-(to)) \ 506 622 MATCH (ip:IPAddress) WHERE ip IN shortestPath((from)-[:Event*]-(to)) \ 507 - MATCH (user)-[event]-(ip)\ 623 + MATCH (user)-[event]-(ip) WHERE ' + dateStr + ' \ 508 624 RETURN user, ip, event' 509 625 510 626 //console.log(queryStr); 511 627 executeQuery(queryStr, setStr); 512 628 } 513 629 630 + /* 631 + sendQuery 632 + This function sends the query to neo4j. 633 + If the query success, this function build the graph and draw it from the neo4j query result. 634 + */ 514 635 function sendQuery(queryStr, root) { 515 636 var graph = { 516 637 "nodes": [], skipped 35 lines 552 673 }); 553 674 } 554 675 676 + /* 677 + executeQuery 678 + This function executes the neo4j query. 679 + */ 555 680 function executeQuery(queryStr, root) { 556 - var countStr = queryStr.replace("user, event, ip" , "COUNT(event)"); 681 + var countStr = queryStr.replace("user, event, ip", "COUNT(event)"); 557 682 558 683 session.run(countStr) 559 684 .subscribe({ skipped 19 lines 579 704 }); 580 705 } 581 706 707 + /* 708 + diffQuery 709 + This function compare 2 days events from neo4j. 710 + If the query success, this function build the graph and draw it from the neo4j query result. 711 + */ 712 + function diffQuery() { 713 + var graph1 = { 714 + "nodes": [], 715 + "edges": [] 716 + }; 717 + 718 + root = "noRoot" 719 + var date1st = new Date(document.getElementById("from-day").value).getTime() / 1000; 720 + 721 + queryStr1st = 'MATCH (user)-[event:Event]-(ip) WHERE event.date >= ' + date1st + ' AND event.date <= ' + (date1st + 86400) + ' RETURN user, event, ip'; 722 + 723 + session.run(queryStr1st) 724 + .subscribe({ 725 + onNext: function(record) { 726 + //console.log(record.get('user'), record.get('event'), record.get('ip')); 727 + graph1 = buildGraph(graph1, [record.get("user"), record.get("event"), record.get("ip")], root); 728 + }, 729 + onCompleted: function() { 730 + session.close(); 731 + if (graph1.nodes.length == 0) { 732 + searchError(); 733 + } else { 734 + diffNext(graph1); 735 + } 736 + }, 737 + onError: function(error) { 738 + searchError(); 739 + console.log("Error: ", error); 740 + } 741 + }); 742 + } 743 + 744 + function diffNext(graph1) { 745 + var graph2 = { 746 + "nodes": [], 747 + "edges": [] 748 + }; 749 + 750 + root = "noRoot" 751 + var date2nd = new Date(document.getElementById("to-day").value).getTime() / 1000; 752 + 753 + queryStr2nd = 'MATCH (user)-[event:Event]-(ip) WHERE event.date >= ' + date2nd + ' AND event.date <= ' + (date2nd + 86400) + ' RETURN user, event, ip'; 754 + 755 + var loading = document.getElementById('loading'); 756 + loading.classList.remove('loaded'); 757 + 758 + session.run(queryStr2nd) 759 + .subscribe({ 760 + onNext: function(record) { 761 + //console.log(record.get('user'), record.get('event'), record.get('ip')); 762 + graph2 = buildGraph(graph2, [record.get("user"), record.get("event"), record.get("ip")], root); 763 + }, 764 + onCompleted: function() { 765 + session.close(); 766 + if (graph2.nodes.length == 0) { 767 + searchError(); 768 + loading.classList.add("loaded"); 769 + } else { 770 + graph2.edges = getArrayDiff(graph1, graph2); 771 + graph2.nodes = nodeConcat(graph1, graph2); 772 + if (graph2.edges.length > 0) { 773 + drawGraph(graph2, graph2.nodes[0].data.id); 774 + } else{ 775 + searchError(); 776 + loading.classList.add("loaded"); 777 + } 778 + } 779 + }, 780 + onError: function(error) { 781 + searchError(); 782 + console.log("Error: ", error); 783 + } 784 + }); 785 + } 786 + 787 + function getArrayDiff(arr1, arr2) { 788 + let arr = arr1.edges.concat(arr2.edges); 789 + return arr.filter((v, i)=> { 790 + return !(arr1.edges.findIndex(obj => obj.data.source === v.data.source, obj => obj.data.target === v.data.target) >= 0 && 791 + arr2.edges.findIndex(obj => obj.data.source === v.data.source, obj => obj.data.target === v.data.target) >= 0); 792 + }); 793 + } 794 + 795 + function nodeConcat(arr1, arr2) { 796 + let arr = arr1.nodes.concat(arr2.nodes); 797 + return arr.filter((v, i)=> { 798 + console.log(arr2.edges) 799 + console.log(arr) 800 + return (arr2.edges.findIndex(obj => obj.data.source === v.data.id) >= 0 || 801 + arr2.edges.findIndex(obj => obj.data.target === v.data.id) >= 0); 802 + }); 803 + } 804 + 582 805 var setqueryStr = ""; 806 + 583 807 function contQuery() { 584 808 sendQuery(setqueryStr, "noRoot"); 585 809 } skipped 227 lines 813 1037 var html = '<div class="table-responsive"><table class="table table-bordered table-condensed table-striped table-wrapper" style="background-color:#EEE;"><thead><tr>\ 814 1038 <th ' + span + '>Username</th>'; 815 1039 816 - for (i = 0; i < chartArray.length; i ++) { 1040 + for (i = 0; i < chartArray.length; i++) { 817 1041 if (chartArray[i]) { 818 1042 chartArray[i].destroy(); 819 1043 } skipped 140 lines 960 1184 var timelineElem = document.getElementById("cy"); 961 1185 timelineElem.innerHTML = html; 962 1186 963 - $(function(){ 1187 + $(function() { 964 1188 $(".table.table-wrapper").floatThead({ 965 - responsiveContainer: function($table){ 1189 + responsiveContainer: function($table) { 966 1190 return $table.closest(".table-responsive"); 967 1191 } 968 1192 }); skipped 7 lines 976 1200 } 977 1201 978 1202 var chartArray = new Array(); 1203 + 979 1204 function createTimelineGraph(queryStr) { 980 1205 var users = new Array(); 981 1206 var dates = new Array(); skipped 6 lines 988 1213 dateData = record.get("date"); 989 1214 nodeData = record.get("user"); 990 1215 users.push([nodeData.properties.user, nodeData.properties.counts4624, nodeData.properties.counts4625, nodeData.properties.counts4768, 991 - nodeData.properties.counts4769, nodeData.properties.counts4776, nodeData.properties.detect] ) ; 1216 + nodeData.properties.counts4769, nodeData.properties.counts4776, nodeData.properties.detect 1217 + ]); 992 1218 starttime = dateData.properties.start; 993 1219 endtime = dateData.properties.end; 994 1220 }, skipped 13 lines 1008 1234 type: "line", 1009 1235 data: { 1010 1236 labels: dates, 1011 - datasets: [ 1012 - { 1013 - label: "4624", 1014 - borderColor : "rgb(141, 147, 200)", 1015 - backgroundColor: "rgb(141, 147, 200)", 1016 - pointHoverBorderColor: "rgb(255, 0, 0)", 1017 - lineTension: 0, 1018 - fill: false, 1019 - data: users[i][1].split(","), 1020 - pointRadius: 5, 1021 - pointHoverRadius: 10, 1022 - }, 1023 - { 1024 - label: "4625", 1025 - borderColor : "rgb(89, 195, 225)", 1026 - backgroundColor: "rgb(89, 195, 225)", 1027 - pointHoverBorderColor: "rgb(255, 0, 0)", 1028 - lineTension: 0, 1029 - fill: false, 1030 - data: users[i][2].split(","), 1031 - pointRadius: 5, 1032 - pointHoverRadius: 10, 1033 - }, 1034 - { 1035 - label: "4768", 1036 - borderColor : "rgb(30, 44, 92)", 1037 - backgroundColor: "rgb(30, 44, 92)", 1038 - pointHoverBorderColor: "rgb(255, 0, 0)", 1039 - lineTension: 0, 1040 - fill: false, 1041 - data: users[i][3].split(","), 1042 - pointRadius: 5, 1043 - pointHoverRadius: 10, 1044 - }, 1045 - { 1046 - label: "4769", 1047 - borderColor : "rgb(1, 96, 140)", 1048 - backgroundColor: "rgb(1, 96, 140)", 1049 - pointHoverBorderColor: "rgb(255, 0, 0)", 1050 - lineTension: 0, 1051 - fill: false, 1052 - data: users[i][4].split(","), 1053 - pointRadius: 5, 1054 - pointHoverRadius: 10, 1055 - }, 1056 - { 1057 - label: "4776", 1058 - borderColor : "rgb(0, 158, 150)", 1059 - backgroundColor: "rgb(0, 158, 150)", 1060 - pointHoverBorderColor: "rgb(255, 0, 0)", 1061 - lineTension: 0, 1062 - fill: false, 1063 - data: users[i][5].split(","), 1064 - pointRadius: 5, 1065 - pointHoverRadius: 10, 1066 - }, 1067 - { 1068 - label: "Anomaly Score", 1069 - borderColor : "rgb(230, 0, 57)", 1070 - backgroundColor: "rgb(230, 0, 57)", 1071 - pointHoverBorderColor: "rgb(255, 0, 0)", 1072 - lineTension: 0, 1073 - fill: false, 1074 - data: users[i][6].split(","), 1075 - pointRadius: 5, 1076 - pointHoverRadius: 10, 1077 - yAxisID: "y-right", 1078 - }, 1237 + datasets: [{ 1238 + label: "4624", 1239 + borderColor: "rgb(141, 147, 200)", 1240 + backgroundColor : "rgb(141, 147, 200)", 1241 + pointHoverBorderColor: "rgb(255, 0, 0)", 1242 + lineTension: 0, 1243 + fill: false, 1244 + data: users[i][1].split(","), 1245 + pointRadius: 5, 1246 + pointHoverRadius: 10, 1247 + }, 1248 + { 1249 + label: "4625", 1250 + borderColor: "rgb(89, 195, 225)", 1251 + backgroundColor : "rgb(89, 195, 225)", 1252 + pointHoverBorderColor: "rgb(255, 0, 0)", 1253 + lineTension: 0, 1254 + fill: false, 1255 + data: users[i][2].split(","), 1256 + pointRadius: 5, 1257 + pointHoverRadius: 10, 1258 + }, 1259 + { 1260 + label: "4768", 1261 + borderColor: "rgb(30, 44, 92)", 1262 + backgroundColor : "rgb(30, 44, 92)", 1263 + pointHoverBorderColor: "rgb(255, 0, 0)", 1264 + lineTension: 0, 1265 + fill: false, 1266 + data: users[i][3].split(","), 1267 + pointRadius: 5, 1268 + pointHoverRadius: 10, 1269 + }, 1270 + { 1271 + label: "4769", 1272 + borderColor: "rgb(1, 96, 140)", 1273 + backgroundColor : "rgb(1, 96, 140)", 1274 + pointHoverBorderColor: "rgb(255, 0, 0)", 1275 + lineTension: 0, 1276 + fill: false, 1277 + data: users[i][4].split(","), 1278 + pointRadius: 5, 1279 + pointHoverRadius: 10, 1280 + }, 1281 + { 1282 + label: "4776", 1283 + borderColor: "rgb(0, 158, 150)", 1284 + backgroundColor : "rgb(0, 158, 150)", 1285 + pointHoverBorderColor: "rgb(255, 0, 0)", 1286 + lineTension: 0, 1287 + fill: false, 1288 + data: users[i][5].split(","), 1289 + pointRadius: 5, 1290 + pointHoverRadius: 10, 1291 + }, 1292 + { 1293 + label: "Anomaly Score", 1294 + borderColor: "rgb(230, 0, 57)", 1295 + backgroundColor : "rgb(230, 0, 57)", 1296 + pointHoverBorderColor: "rgb(255, 0, 0)", 1297 + lineTension: 0, 1298 + fill: false, 1299 + data: users[i][6].split(","), 1300 + pointRadius: 5, 1301 + pointHoverRadius: 10, 1302 + yAxisID: "y-right", 1303 + }, 1079 1304 ] 1080 1305 }, 1081 1306 options: { 1082 1307 responsive: true, 1083 1308 legend: { 1084 - position: "bottom", 1309 + position: "bottom", 1085 1310 fontSize: 15, 1086 - }, 1087 - scales: { 1088 - xAxes: [{ 1089 - display: true, 1090 - scaleLabel: { 1091 - display: true, 1311 + }, 1312 + scales: { 1313 + xAxes: [{ 1314 + display: true, 1315 + scaleLabel: { 1316 + display: true, 1092 1317 fontSize: 15, 1093 - labelString: "Date" 1094 - } 1095 - }], 1096 - yAxes: [{ 1097 - display: true, 1098 - scaleLabel: { 1099 - display: true, 1100 - fontSize: 15, 1101 - labelString: "Count" 1102 - } 1103 - }, 1104 - { 1105 - display: true, 1106 - id: "y-right", 1107 - position: "right", 1108 - scaleLabel: { 1109 - display: true, 1110 - fontSize: 15, 1111 - labelString: "Score" 1112 - }, 1113 - ticks: { 1114 - max: 20 1318 + labelString: "Date" 1319 + } 1320 + }], 1321 + yAxes: [{ 1322 + display: true, 1323 + scaleLabel: { 1324 + display: true, 1325 + fontSize: 15, 1326 + labelString: "Count" 1327 + } 1328 + }, 1329 + { 1330 + display: true, 1331 + id: "y-right", 1332 + position: "right", 1333 + scaleLabel: { 1334 + display: true, 1335 + fontSize: 15, 1336 + labelString: "Score" 1337 + }, 1338 + ticks: { 1339 + max: 20 1340 + } 1115 1341 } 1116 - } ] 1117 - }, 1342 + ] 1343 + }, 1118 1344 title: { 1119 - display: true, 1120 - fontSize: 18, 1121 - text: users[i][0] 1345 + display: true, 1346 + fontSize: 18, 1347 + text: users[i][0] 1122 1348 }, 1123 1349 elements: { 1124 - point: { 1125 - pointStyle: "crossRot" 1126 - } 1127 - } 1350 + point: { 1351 + pointStyle: "crossRot" 1352 + } 1353 + } 1128 1354 } 1129 1355 }); 1130 1356 } skipped 8 lines 1139 1365 }); 1140 1366 } 1141 1367 1142 - function addCanvas(users){ 1143 - var canvasArray = new Array();1144 - var obj = document.getElementById("addcanvas");1145 - obj.textContent = null; 1368 + function addCanvas(users) { 1369 + var canvasArray = new Array(); 1370 + var obj = document.getElementById("addcanvas"); 1371 + obj.textContent = null; 1146 1372 1147 - for (i = 1; i <= users.length; i++) {1148 - var canvas = document.createElement("canvas"); 1149 - canvas.id = "canvas" + i; 1150 - canvas.style = "height:400px;"; 1151 - canvasArray.push(canvas); 1373 + for (i = 1; i <= users.length; i++) { 1374 + var canvas = document.createElement("canvas"); 1375 + canvas.id = "canvas" + i; 1376 + canvas.style = "height:400px;"; 1377 + canvasArray.push(canvas); 1152 1378 1153 - obj.appendChild(canvas); 1154 - } 1379 + obj.appendChild(canvas); 1380 + } 1155 1381 1156 - return canvasArray; 1382 + return canvasArray; 1157 1383 } 1158 1384 1159 1385 function createAlltimeline() { skipped 41 lines 1201 1427 } 1202 1428 } 1203 1429 1204 - 1430 + /* 1431 + logdeleteCheck 1432 + push alert if the event log had deleted. 1433 + */ 1205 1434 function logdeleteCheck() { 1206 1435 var queryStr = "MATCH (date:Deletetime) RETURN date"; 1207 1436 var ddata = ""; skipped 23 lines 1231 1460 }); 1232 1461 } 1233 1462 1463 + /* 1464 + searchError 1465 + push alert if search has failed. 1466 + */ 1234 1467 function searchError() { 1235 1468 var elemMsg = document.getElementById("error"); 1236 1469 elemMsg.innerHTML = skipped 4 lines 1241 1474 }); 1242 1475 } 1243 1476 1477 + /* 1478 + file_upload 1479 + Upload EVTX file or XML file to LogonTracer Server. 1480 + */ 1244 1481 function file_upload() { 1245 1482 var upfile = document.getElementById("lefile"); 1246 1483 var timezone = document.getElementById("utcTime").value; skipped 54 lines 1301 1538 document.getElementById("status").innerHTML = '<div class="alert alert-info">Upload Aborted</div>'; 1302 1539 } 1303 1540 1541 + /* 1542 + parseEVTX 1543 + Get EVTX parsing progress from log. 1544 + */ 1304 1545 function parseEVTX() { 1305 1546 var xmlhttp2 = new XMLHttpRequest(); 1306 1547 xmlhttp2.open("GET", "/log"); skipped 24 lines 1331 1572 } 1332 1573 } 1333 1574 1334 - var formatDate = function (date) { 1575 + /* 1576 + loaddate 1577 + load date info from neo4j 1578 + */ 1579 + function loaddate() { 1580 + var queryStr = 'MATCH (date:Date) RETURN date'; 1581 + 1582 + session.run(queryStr) 1583 + .subscribe({ 1584 + onNext: function(record) { 1585 + dateData = record.get("date"); 1586 + starttime = dateData.properties.start; 1587 + endtime = dateData.properties.end; 1588 + }, 1589 + onCompleted: function() { 1590 + session.close(); 1591 + var minDate = new Date(starttime); 1592 + var maxDate = new Date(endtime); 1593 + maxDate.setTime(maxDate.getTime() + 3600000); 1594 + 1595 + var minDay = new Date(starttime); 1596 + var maxDay = new Date(endtime); 1597 + var setminDate = new Date(minDay.getFullYear(), minDay.getMonth(), minDay.getDate()) 1598 + minDay.setTime(setminDate.getTime()); 1599 + var setmaxDate = new Date(maxDay.getFullYear(), maxDay.getMonth(), maxDay.getDate()) 1600 + maxDay.setTime(setmaxDate.getTime()); 1601 + 1602 + $('.fromdate').datetimepicker({ 1603 + locale: "en", 1604 + format: "YYYY-MM-DD HH:00:00", 1605 + useCurrent: false, 1606 + defaultDate: minDate, 1607 + maxDate: maxDate, 1608 + minDate: minDate 1609 + }); 1610 + 1611 + $('.todate').datetimepicker({ 1612 + locale: "en", 1613 + format: "YYYY-MM-DD HH:00:00", 1614 + useCurrent: false, 1615 + defaultDate: maxDate, 1616 + maxDate: maxDate, 1617 + minDate: minDate 1618 + }); 1619 + 1620 + $('.fromday').datetimepicker({ 1621 + locale: "en", 1622 + format: "YYYY-MM-DD", 1623 + useCurrent: false, 1624 + defaultDate: minDay, 1625 + maxDate: maxDay, 1626 + minDate: minDay 1627 + }); 1628 + 1629 + $('.today').datetimepicker({ 1630 + locale: "en", 1631 + format: "YYYY-MM-DD", 1632 + useCurrent: false, 1633 + defaultDate: maxDay, 1634 + maxDate: maxDay, 1635 + minDate: minDay 1636 + }); 1637 + }, 1638 + onError: function(error) { 1639 + console.log("Error: ", error); 1640 + } 1641 + }); 1642 + } 1643 + 1644 + var formatDate = function(date) { 1335 1645 format = "YYYY-MM-DD hh:00:00"; 1336 1646 format = format.replace(/YYYY/g, date.getFullYear()); 1337 1647 format = format.replace(/MM/g, ('0' + (date.getMonth() + 1)).slice(-2)); skipped 6 lines