diff --git a/src/takajo.nim b/src/takajo.nim index decfc40..8ca5b3d 100644 --- a/src/takajo.nim +++ b/src/takajo.nim @@ -97,7 +97,7 @@ when isMainModule: const example_vt_hash_lookup = " vt-hash-lookup -a --hashList case-1-MD5-hashes.txt -r 1000 -o results.csv --jsonOutput responses.json\p" const example_vt_ip_lookup = " vt-ip-lookup -a --ipList ipAddresses.txt -r 1000 -o results.csv --jsonOutput responses.json\p" - clCfg.useMulti = "Version: 2.7.0 Dev Build\pUsage: takajo.exe \p\pCommands:\p$subcmds\pCommand help: $command help \p\p" & + clCfg.useMulti = "Version: 2.7.0 SecTor Releaase\pUsage: takajo.exe \p\pCommands:\p$subcmds\pCommand help: $command help \p\p" & examples & example_automagic & example_extract_credentials & example_extract_scriptblocks & example_html_report & example_html_server & diff --git a/src/takajopkg/htmlReport.nim b/src/takajopkg/htmlReport.nim index 8a69c85..d8adff8 100644 --- a/src/takajopkg/htmlReport.nim +++ b/src/takajopkg/htmlReport.nim @@ -203,7 +203,7 @@ proc htmlReport*(output: string, quiet: bool = false, timeline: string, rulepath # start analysis timeline # obtain datas from SQLite - var query = sql"""select rule_title, rule_file, level, level_order, computer, min(timestamp) as start_date, max(timestamp) as end_date, count(*) as count + var query = sql"""select rule_title, rule_file, level, level_order, computer, min(datetime(timestamp, 'localtime')) as start_date, max(datetime(timestamp, 'localtime')) as end_date, count(*) as count from timelines group by rule_title, level, computer order by level_order diff --git a/src/takajopkg/web/controllers/computers.nim b/src/takajopkg/web/controllers/computers.nim index bc96048..b1c8512 100644 --- a/src/takajopkg/web/controllers/computers.nim +++ b/src/takajopkg/web/controllers/computers.nim @@ -48,8 +48,19 @@ proc computer*(ctx: Context) {.async.} = let rule_title = ctx.request.queryParams.getOrDefault("rule_title", "") if rule_title != "": - custom_query &= " AND rule_title = ?" - params.add(rule_title) + let rule_title_list = rule_title.split(",") + custom_query &= " AND rule_title IN (" + var count = 0 + let rule_title_list_last = len(rule_title_list) - 1 + for rule_title in rule_title_list: + #custom_query &= "'" & rule_title & "'" + custom_query &= "?" + if count != rule_title_list_last: + custom_query &= "," + count += 1 + params.add(rule_title) + custom_query &= ")" + let severities = ctx.request.queryParams.getOrDefault("severities", "") if severities != "": @@ -61,8 +72,8 @@ proc computer*(ctx: Context) {.async.} = severity_query &= dbQuote(severity) custom_query &= " AND level IN (" & severity_query & ")" - echo custom_query - echo params + # echo custom_query + # echo params # # query to DB @@ -71,7 +82,7 @@ proc computer*(ctx: Context) {.async.} = let path = getDBPath(ctx) let db = open(path , "", "", "") - var query = """select rule_title, rule_file, level, level_order, computer, min(timestamp) as start_date, max(timestamp) as end_date, count(*) as count + var query = """select rule_title, rule_file, level, level_order, computer, min(datetime(timestamp, 'localtime')) as start_date, max(datetime(timestamp, 'localtime')) as end_date, count(*) as count from timelines where """ & custom_query & """ group by rule_title, level, computer @@ -125,8 +136,8 @@ proc sidemenu*(ctx: Context) {.async.} = rule_title, computer, COUNT(computer) AS computer_total, - MIN(timestamp) AS first_date, - MAX(timestamp) AS last_date + MIN(datetime(timestamp, 'localtime')) AS first_date, + MAX(datetime(timestamp, 'localtime')) AS last_date FROM timelines GROUP BY level_order, rule_title, computer ORDER BY level_order, rule_title, computer; diff --git a/src/takajopkg/web/controllers/controller.nim b/src/takajopkg/web/controllers/controller.nim index 30a3fad..9a393a5 100644 --- a/src/takajopkg/web/controllers/controller.nim +++ b/src/takajopkg/web/controllers/controller.nim @@ -17,4 +17,7 @@ proc computer_summary*(ctx: Context) {.async.} = proc commonjs*(ctx: Context) {.async.} = - await ctx.staticFileResponse("js/common.js", "src/takajopkg/web/static") \ No newline at end of file + await ctx.staticFileResponse("js/common.js", "src/takajopkg/web/static") + +proc favicon*(ctx: Context) {.async.} = + await ctx.staticFileResponse("img/favicon.png", "src/takajopkg/web/static") \ No newline at end of file diff --git a/src/takajopkg/web/controllers/summary.nim b/src/takajopkg/web/controllers/summary.nim index bba8f3d..d5952e6 100644 --- a/src/takajopkg/web/controllers/summary.nim +++ b/src/takajopkg/web/controllers/summary.nim @@ -56,7 +56,7 @@ proc list*(ctx: Context) {.async.} = severity_query &= dbQuote(severity) custom_query &= " AND level IN (" & severity_query & ")" - echo custom_query + # echo custom_query # # query to DB @@ -118,7 +118,7 @@ proc list*(ctx: Context) {.async.} = var dates_with_most_total_detections = db.getAllRows(sql query, params) query = """SELECT level, level_order, rule_title, computer, COUNT(*) AS alert_count, - MIN(DATE(timestamp)) AS first_seen, MAX(DATE(timestamp)) AS last_seen + MIN(DATE(datetime(timestamp, 'localtime'))) AS first_seen, MAX(DATE(datetime(timestamp, 'localtime'))) AS last_seen FROM timelines GROUP BY level, rule_title, computer ORDER BY level_order DESC diff --git a/src/takajopkg/web/static/computer_summary.htm b/src/takajopkg/web/static/computer_summary.htm index 38a923f..96e7203 100644 --- a/src/takajopkg/web/static/computer_summary.htm +++ b/src/takajopkg/web/static/computer_summary.htm @@ -5,9 +5,8 @@ - Computer Summary - - + Takajo Report + diff --git a/src/takajopkg/web/static/content.htm b/src/takajopkg/web/static/content.htm index d8455c5..d2445ff 100644 --- a/src/takajopkg/web/static/content.htm +++ b/src/takajopkg/web/static/content.htm @@ -5,11 +5,12 @@ - Project + Takajo Report + @@ -68,12 +69,19 @@ } function getComputerData() { + + if (document.getElementById("detection-rule-list-body").innerHTML != "" && areAllUnchecked()) { + alert('No rules are enabled.'); + return + } + let first_date = document.getElementById("first_date").value; let last_date = document.getElementById("last_date").value; let api_endpoint = apiUrl + `computer?computer=${computer}&start_date=${first_date}&end_date=${last_date}`; if (pastdays == true) { api_endpoint += "&pastdays=true"; } + api_endpoint += getCheckedValues(); fetch(api_endpoint) .then(response => { @@ -165,56 +173,68 @@ } return b[7] - a[7]; }); + const tbody = document.getElementById("detection-rule-list-body") - tbody.innerHTML = "" - alerts.forEach(alert => { - const row = document.createElement("tr"); - - // Alert Title - const titleCell = document.createElement("td"); - const titleCellA = document.createElement("a"); - titleCellA.textContent = alert[0]; - titleCellA.classList.add("link"); - titleCellA.target = "_blank"; - global_rules.forEach(rule => { - if (rule[0] == alert[0]) { - titleCellA.href = rule[1]; - return; - } + if (tbody.innerHTML == "") { + alerts.forEach(alert => { + const row = document.createElement("tr"); + + // Checkbox + const checkboxCell = document.createElement("td"); + const checkboxCellCheck = document.createElement('input'); + checkboxCellCheck.type = "checkbox"; + checkboxCellCheck.classList.add("rule_check"); + checkboxCellCheck.checked = true; + checkboxCellCheck.value = alert[0]; + checkboxCell.appendChild(checkboxCellCheck); + row.appendChild(checkboxCell); + + // Alert Title + const titleCell = document.createElement("td"); + const titleCellA = document.createElement("a"); + titleCellA.textContent = alert[0]; + titleCellA.classList.add("link"); + titleCellA.target = "_blank"; + global_rules.forEach(rule => { + if (rule[0] == alert[0]) { + titleCellA.href = rule[1]; + return; + } + }); + titleCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); + titleCell.appendChild(titleCellA); + row.appendChild(titleCell); + + // Severity + const severityCell = document.createElement("td"); + const severityDev = document.createElement("div"); + severityDev.classList.add("inline-block", "rounded-full", "bg-" + severity_color[alert[2]] + "-100", "px-2", "py-1", "text-xs", "font-semibold", "leading-4", "text-" + severity_color[alert[2]] + "-800"); + severityDev.textContent = severity_message[alert[2]]; + severityCell.append(severityDev) + row.appendChild(severityCell); + + // Count + const countCell = document.createElement("td"); + countCell.textContent = alert[7]; + countCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); + row.appendChild(countCell); + + // First Date + const firstDateCell = document.createElement("td"); + firstDateCell.textContent = formatDate(alert[5]); + firstDateCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); + row.appendChild(firstDateCell); + + // Last Date + const lastDateCell = document.createElement("td"); + lastDateCell.textContent = formatDate(alert[6]); + lastDateCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); + row.appendChild(lastDateCell); + + // 行を に追加 + tbody.appendChild(row); }); - titleCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); - titleCell.appendChild(titleCellA); - row.appendChild(titleCell); - - // Severity - const severityCell = document.createElement("td"); - const severityDev = document.createElement("div"); - severityDev.classList.add("inline-block", "rounded-full", "bg-" + severity_color[alert[2]] + "-100", "px-2", "py-1", "text-xs", "font-semibold", "leading-4", "text-" + severity_color[alert[2]] + "-800"); - severityDev.textContent = severity_message[alert[2]]; - severityCell.append(severityDev) - row.appendChild(severityCell); - - // Count - const countCell = document.createElement("td"); - countCell.textContent = alert[7]; - countCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); - row.appendChild(countCell); - - // First Date - const firstDateCell = document.createElement("td"); - firstDateCell.textContent = formatDate(alert[5]); - firstDateCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); - row.appendChild(firstDateCell); - - // Last Date - const lastDateCell = document.createElement("td"); - lastDateCell.textContent = formatDate(alert[6]); - lastDateCell.classList.add("min-w-[180px]", "py-3", "pe-3", "text-start", "text-sm", "font-semibold", "uppercase", "tracking-wider", "text-slate-700"); - row.appendChild(lastDateCell); - - // 行を に追加 - tbody.appendChild(row); - }); + } }) .catch(error => { @@ -521,7 +541,7 @@

- Information + Informational
@@ -534,6 +554,8 @@

  + +  

Detection Rule List

+ + +
+ + - - - - - + + + + + + - - +
Alert TitleSeverityCountFirst DateLast DateAlert TitleSeverityCountFirst DateLast Date
@@ -606,6 +641,40 @@

Detection Rule List

}); }); + + function checkAllCheckboxes() { + const checkboxes = document.querySelectorAll('.rule_check'); + checkboxes.forEach(checkbox => { + if (checkbox.type === 'checkbox') { + checkbox.checked = true; + } + }); + } + + function uncheckAllCheckboxes() { + const checkboxes = document.querySelectorAll('.rule_check'); + checkboxes.forEach(checkbox => { + if (checkbox.type === 'checkbox') { + checkbox.checked = false; + } + }); + } + + function areAllChecked() { + const checkboxes = document.querySelectorAll('.rule_check'); + return Array.from(checkboxes).every(checkbox => checkbox.checked); + } + + function areAllUnchecked(className) { + const checkboxes = document.querySelectorAll('.rule_check'); + return Array.from(checkboxes).every(checkbox => !checkbox.checked); + } + + function getCheckedValues() { + const checkboxes = document.querySelectorAll('.rule_check:checked'); + const values = Array.from(checkboxes).map(checkbox => checkbox.value); + return '&rule_title=' + values.map(value => `${encodeURIComponent(value)}`).join(','); + } diff --git a/src/takajopkg/web/static/index.htm b/src/takajopkg/web/static/index.htm index 5d74b45..5d7eade 100644 --- a/src/takajopkg/web/static/index.htm +++ b/src/takajopkg/web/static/index.htm @@ -5,7 +5,8 @@ - Project + Takajo Report + diff --git a/src/takajopkg/web/urls.nim b/src/takajopkg/web/urls.nim index a04f0d1..de9e51f 100644 --- a/src/takajopkg/web/urls.nim +++ b/src/takajopkg/web/urls.nim @@ -10,6 +10,7 @@ const urlPatterns* = @[ pattern("/computer", controller.computer), pattern("/computer/summary", controller.computer_summary), pattern("/js/common.js", controller.commonjs), + pattern("/img/favicon.png", controller.favicon), pattern("/api/computer", computers.computer), pattern("/api/computer/summary", computers.summary), pattern("/api/summary", summary.list),