diff --git a/run.py b/run.py old mode 100755 new mode 100644 index cc5d8ee..36cd7b1 --- a/run.py +++ b/run.py @@ -10,9 +10,12 @@ from sigma.plugins import InstalledSigmaPlugins from sigma.collection import SigmaCollection from sigma.exceptions import SigmaError +from sigma.processing import pipeline +from sigma.processing.pipeline import ProcessingPipeline app = Flask(__name__) plugins = InstalledSigmaPlugins.autodiscover() +pipeline_generic = pipeline.ProcessingPipeline() backends = plugins.backends pipeline_resolver = plugins.get_pipeline_resolver() pipelines = list(pipeline_resolver.list_pipelines()) @@ -56,11 +59,27 @@ def convert(): for p in request.json["pipeline"]: pipeline.append(p) + template_pipeline = "" + if request.json["pipelineYml"]: + try: + template = str(base64.b64decode(request.json["pipelineYml"]), "utf-8") + template_pipeline = pipeline_generic.from_yaml(template) + except: + return Response( + f"YamlError: Malformed Pipeline Yaml", status=400, mimetype="text/html" + ) + target = request.json["target"] format = request.json["format"] backend_class = backends[target] processing_pipeline = pipeline_resolver.resolve(pipeline) + + if isinstance(template_pipeline, ProcessingPipeline): + processing_pipeline += template_pipeline + else: + print("no processing pipeline") + backend: Backend = backend_class(processing_pipeline=processing_pipeline) try: diff --git a/static/css/style.css b/static/css/style.css index 9fc9b03..ac6239b 100644 --- a/static/css/style.css +++ b/static/css/style.css @@ -35,6 +35,7 @@ /* Code Area CSS */ pre:has(> #rule-code), +pre:has(> #pipeline-code), pre:has(> #query-code) { min-height: 200px; cursor: text; @@ -46,6 +47,12 @@ pre:has(> #rule-code:empty)::after { width: 20px; } +pre:has(> #pipeline-code:empty)::after { + content: "start writing your post processing pipeline..."; + color: #c5c8c6; + width: 20px; +} + div[class*="language-"], code[class*="language-"], code[class*="language-"] *, diff --git a/static/js/index.js b/static/js/index.js index 037c02f..630d72e 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -23,7 +23,7 @@ new TomSelect("#select-pipeline", { labelField: "label" }); -// inital stuff todo when page is loaded +// initial stuff todo when page is loaded window.onload = function () { // Get the fragment section from the current URL, without the '#' character const fragment = window.location.hash.substring(1); @@ -47,6 +47,12 @@ window.onload = function () { sigmaJar.updateCode(rule) } + // check if pipelineYml parameter is in url + if(urlParameter.has('pipelineYml')){ + let pipelineYml = atob(urlParameter.get('pipelineYml')); + pipelineJar.updateCode(pipelineYml) + } + let backendSelect = document.getElementById("select-backend"); // get parameter backend from url and check if it's a valid option if(urlParameter.has('backend') && backendSelect.querySelectorAll('option[value$="' + urlParameter.get('backend') + '"]').length > 0) { @@ -81,7 +87,7 @@ window.onload = function () { // load cli command generateCli(); // inital conversion of example rule - convert(sigmaJar.toString()); + convert(sigmaJar.toString(), pipelineJar.toString()); }; // define onchange handler for select dropdowns @@ -89,17 +95,17 @@ document.getElementById("select-backend").onchange = function () { filterFormatOptions(); filterPipelineOptions(); generateCli(); - convert(sigmaJar.toString()); + convert(sigmaJar.toString(), pipelineJar.toString()); }; document.getElementById("select-format").onchange = function () { generateCli(); - convert(sigmaJar.toString()); + convert(sigmaJar.toString(), pipelineJar.toString()); }; document.getElementById("select-pipeline").onchange = function () { generateCli(); - convert(sigmaJar.toString()); + convert(sigmaJar.toString(), pipelineJar.toString()); }; // define onclick handler for buttons @@ -109,15 +115,48 @@ document.getElementById("query-copy-btn").onclick = function () { document.getElementById("rule-share-btn").onclick = function () { generateShareLink(); }; +document.getElementById("tab-rule").onclick = function () { + showTab("tab-rule", "rule-code"); +}; +document.getElementById("tab-pipeline").onclick = function () { + showTab("tab-pipeline", "pipeline-code"); +}; + +function showTab(tabId, codeId){ + var i, tabcontent, tablinks; + var tab = document.getElementById(tabId); + var code = document.getElementById(codeId); + + // hide all code areas + tabcontent = document.getElementsByClassName("tab-code"); + for (i = 0; i < tabcontent.length; i++) { + tabcontent[i].classList.add('hidden'); + } + + // remove color from all tabs + tablinks = document.getElementsByClassName("file-tab"); + for (i = 0; i < tablinks.length; i++) { + tablinks[i].classList.remove('bg-sigma-blue'); + tablinks[i].classList.remove('text-sigma-dark'); + } + + // display the selected code area + code.parentElement.classList.remove('hidden'); + + // change color of tab button to indicate selected code area + tab.classList.add('bg-sigma-blue'); + tab.classList.add('text-sigma-dark'); +} function generateShareLink() { let backend = getSelectValue("select-backend"); let format = getSelectValue("select-format"); let pipelines = getSelectValue("select-pipeline"); let rule = encodeURIComponent(btoa(sigmaJar.toString())); + let pipelineYml = encodeURIComponent(btoa(pipelineJar.toString())); // generate link with parameters - let shareParams = "#backend=" + backend + "&format=" + format + "&pipeline=" + pipelines.join(";") + "&rule=" + rule; + let shareParams = "#backend=" + backend + "&format=" + format + "&pipeline=" + pipelines.join(";") + "&rule=" + rule + "&pipelineYml=" + pipelineYml; let shareUrl = location.protocol + "//" + location.host + "/" + shareParams; window.history.pushState({}, null, shareParams); @@ -167,28 +206,33 @@ function generateCli() { let pipelines = getSelectValue("select-pipeline"); cliCommand = "sigma convert"; - if (pipelines.length === 0) { + if (pipelines.length === 0 && pipelineJar.toString().length == 0) { cliCommand = cliCommand + " --without-pipeline "; } pipelines.forEach((e) => { cliCommand = cliCommand + " -p " + e; }); + if(pipelineJar.toString().length > 0){ + cliCommand = cliCommand + " -p pipeline.yml"; + } + cliCommand = cliCommand + " -t " + backend + " -f " + format + " rule.yml"; cliCode.innerHTML = cliCommand; Prism.highlightElement(cliCode); // rerun code highlighting } -function convert(sigmaRule) { +function convert(sigmaRule, customPipeline) { let queryCode = document.getElementById("query-code"); let backend = getSelectValue("select-backend"); let format = getSelectValue("select-format"); let pipelines = getSelectValue("select-pipeline"); - + // create json object const params = { rule: btoa(sigmaRule), + pipelineYml: btoa(customPipeline), pipeline: pipelines, target: backend, format: format diff --git a/templates/index.html b/templates/index.html index 8f046de..c473115 100644 --- a/templates/index.html +++ b/templates/index.html @@ -85,10 +85,15 @@

+ + rule.yml + + pipeline.yml +

-
title: Suspicious SYSTEM User Process Creation
+          
title: Suspicious SYSTEM User Process Creation
 id: 2617e7ed-adb7-40ba-b0f3-8f9945fe6c09
 status: test
 description: Detects a suspicious process creation as SYSTEM user (suspicious program or command line parameter)
@@ -162,7 +167,9 @@
     - Scripts and administrative tools used in the monitored environment
     - Monitoring activity
 level: high
+ +

@@ -173,6 +180,7 @@

             the generated query should be displayed here :)
+ @@ -195,10 +203,19 @@ import { withLineNumbers } from 'https://medv.io/codejar/linenumbers.js' + window.sigmaJar = CodeJar(document.querySelector('#rule-code'), el => Prism.highlightElement(el)) sigmaJar.onUpdate(sigmaRule => { if (sigmaRule.length > 0) { - convert(sigmaRule) + convert(sigmaRule, pipelineJar.toString()); + } + }) + + window.pipelineJar = CodeJar(document.querySelector('#pipeline-code'), el => Prism.highlightElement(el)) + pipelineJar.onUpdate(pipelineYml => { + generateCli(); + if (pipelineYml.length > 0) { + convert(sigmaJar.toString(), pipelineYml); } })