From 16726b1f48b5d0a2e412fae9716c101956ee0f1a Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 31 Jul 2024 10:07:35 +0000 Subject: [PATCH 01/37] Made base format for new boefje --- boefjes/boefjes/plugins/kat_nikto/__init__.py | 0 .../plugins/kat_nikto/boefje.Dockerfile | 15 +++++++++++ boefjes/boefjes/plugins/kat_nikto/boefje.json | 13 ++++++++++ boefjes/boefjes/plugins/kat_nikto/cover.jpg | Bin 0 -> 62267 bytes .../boefjes/plugins/kat_nikto/description.md | 23 +++++++++++++++++ boefjes/boefjes/plugins/kat_nikto/main.py | 24 ++++++++++++++++++ boefjes/boefjes/plugins/kat_nikto/schema.json | 6 +++++ 7 files changed, 81 insertions(+) create mode 100644 boefjes/boefjes/plugins/kat_nikto/__init__.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile create mode 100644 boefjes/boefjes/plugins/kat_nikto/boefje.json create mode 100644 boefjes/boefjes/plugins/kat_nikto/cover.jpg create mode 100644 boefjes/boefjes/plugins/kat_nikto/description.md create mode 100644 boefjes/boefjes/plugins/kat_nikto/main.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/schema.json diff --git a/boefjes/boefjes/plugins/kat_nikto/__init__.py b/boefjes/boefjes/plugins/kat_nikto/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile new file mode 100644 index 00000000000..0af140a1d0d --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.11-slim + +WORKDIR /app +RUN apt-get update && pip install httpx + +ARG BOEFJE_PATH=./boefjes/plugins/kat_nmap_tcp +ENV PYTHONPATH=/app:$BOEFJE_PATH + +COPY ./images/oci_adapter.py ./ +COPY $BOEFJE_PATH $BOEFJE_PATH + +RUN git clone https://github.com/sullo/nikto +RUN ./nikto/program/nikto.pl -h 46.23.85.171 -o ./output.json + +ENTRYPOINT ["/usr/local/bin/python", "-m", "oci_adapter"] diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.json b/boefjes/boefjes/plugins/kat_nikto/boefje.json new file mode 100644 index 00000000000..12223e76d5c --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.json @@ -0,0 +1,13 @@ +{ + "id": "nikto", + "name": "Nikto", + "description": "Uses Nikto", + "consumes": [ + "IPAddressV4", + "IPAddressV6" + ], + "environment_keys": [], + "scan_level": 3, + "oci_image": "openkat/nikto", + "oci_arguments": [] +} diff --git a/boefjes/boefjes/plugins/kat_nikto/cover.jpg b/boefjes/boefjes/plugins/kat_nikto/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d509564388d68d3189bab55cc28aa5073cc53248 GIT binary patch literal 62267 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 Date: Wed, 7 Aug 2024 04:48:43 +0000 Subject: [PATCH 02/37] Fixed issue of nikto boefje not contacting boefje api --- boefjes/Makefile | 2 +- .../boefjes/plugins/kat_nikto/.dockerignore | 4 + .../plugins/kat_nikto/boefje.Dockerfile | 19 +-- boefjes/boefjes/plugins/kat_nikto/index.js | 118 ++++++++++++++ boefjes/boefjes/plugins/kat_nikto/main.py | 24 --- .../plugins/kat_nikto/package-lock.json | 144 ++++++++++++++++++ .../boefjes/plugins/kat_nikto/package.json | 15 ++ 7 files changed, 292 insertions(+), 34 deletions(-) create mode 100644 boefjes/boefjes/plugins/kat_nikto/.dockerignore create mode 100644 boefjes/boefjes/plugins/kat_nikto/index.js delete mode 100644 boefjes/boefjes/plugins/kat_nikto/main.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/package-lock.json create mode 100644 boefjes/boefjes/plugins/kat_nikto/package.json diff --git a/boefjes/Makefile b/boefjes/Makefile index 579543e3926..afe84575b67 100644 --- a/boefjes/Makefile +++ b/boefjes/Makefile @@ -40,7 +40,7 @@ images: # Build the images for the containerized boefjes # docker build -f images/base.Dockerfile -t ghcr.io/minvws/openkat/dns-records --build-arg BOEFJE_PATH=./boefjes/plugins/kat_dns . docker build -f ./boefjes/plugins/kat_dnssec/boefje.Dockerfile -t ghcr.io/minvws/openkat/dns-sec:latest . docker build -f ./boefjes/plugins/kat_nmap_tcp/boefje.Dockerfile -t ghcr.io/minvws/openkat/nmap:latest . - + docker build -f ./boefjes/plugins/kat_nikto/boefje.Dockerfile -t openkat/nikto . ## ##|------------------------------------------------------------------------| diff --git a/boefjes/boefjes/plugins/kat_nikto/.dockerignore b/boefjes/boefjes/plugins/kat_nikto/.dockerignore new file mode 100644 index 00000000000..476b7d85f6a --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/.dockerignore @@ -0,0 +1,4 @@ +.git +*Dockerfile* +*docker-compose* +node_modules diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile index 0af140a1d0d..ed9308c735e 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -1,15 +1,16 @@ -FROM python:3.11-slim +FROM node:19-bullseye WORKDIR /app -RUN apt-get update && pip install httpx +RUN apt update +RUN apt install -y git -ARG BOEFJE_PATH=./boefjes/plugins/kat_nmap_tcp -ENV PYTHONPATH=/app:$BOEFJE_PATH - -COPY ./images/oci_adapter.py ./ -COPY $BOEFJE_PATH $BOEFJE_PATH RUN git clone https://github.com/sullo/nikto -RUN ./nikto/program/nikto.pl -h 46.23.85.171 -o ./output.json -ENTRYPOINT ["/usr/local/bin/python", "-m", "oci_adapter"] +ARG BOEFJE_PATH=./boefjes/plugins/kat_nikto +COPY $BOEFJE_PATH ./ + +RUN npm ci + +ENTRYPOINT [ "node", "./" ] +# node ./ "http://localhost:8006/api/v0/tasks/ff208697-c332-4b04-919d-755b014e881d" diff --git a/boefjes/boefjes/plugins/kat_nikto/index.js b/boefjes/boefjes/plugins/kat_nikto/index.js new file mode 100644 index 00000000000..ba2dbcee8a3 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/index.js @@ -0,0 +1,118 @@ +import fs from "node:fs"; +import fetch from "node-fetch"; // npm install node-fetch +import { execSync } from "node:child_process"; + +// Getting information from INPUT_URL: http://boefje:8000/api/v0/tasks/6f08f386-0dfe-4cd4-a1b4-91e95411c883 +// Found boefje input with ooi: 46.23.85.171 +// - ***** TLS/SSL support not available (see docs for SSL install) ***** +// - Nikto v2.5.0 +// --------------------------------------------------------------------------- +// + Target IP: 46.23.85.171 +// + Target Hostname: 46.23.85.171 +// + Target Port: 80 +// + Start Time: 2024-08-05 09:55:56 (GMT0) +// --------------------------------------------------------------------------- +// + Server: nginx/1.18.0 (Ubuntu) +// + /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/ +// + No CGI Directories found (use '-C all' to force check all possible dirs) +// + nginx/1.18.0 appears to be outdated (current is at least 1.25.3). +// + 8108 requests: 0 error(s) and 2 item(s) reported on remote host +// + End Time: 2024-08-05 09:56:14 (GMT0) (18 seconds) +// --------------------------------------------------------------------------- +// + 1 host(s) tested +// Encoding: [{"host":"46.23.85.171","ip":"46.23.85.171","port":"80","banner":"","vulnerabilities":[{"id": "999103","references": "https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/","method":"GET","url":"/","msg":"The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type."},{"id": "600575","method":"HEAD","url":"/","msg":"nginx/1.18.0 appears to be outdated (current is at least 1.25.3)."}]}] +// FINISHING... +// SENDING OUT WITH: +// {"status":"COMPLETED","files":[{"content":"W3siaG9zdCI6IjQ2LjIzLjg1LjE3MSIsImlwIjoiNDYuMjMuODUuMTcxIiwicG9ydCI6IjgwIiwiYmFubmVyIjoiIiwidnVsbmVyYWJpbGl0aWVzIjpbeyJpZCI6ICI5OTkxMDMiLCJyZWZlcmVuY2VzIjogImh0dHBzOi8vd3d3Lm5ldHNwYXJrZXIuY29tL3dlYi12dWxuZXJhYmlsaXR5LXNjYW5uZXIvdnVsbmVyYWJpbGl0aWVzL21pc3NpbmctY29udGVudC10eXBlLWhlYWRlci8iLCJtZXRob2QiOiJHRVQiLCJ1cmwiOiIvIiwibXNnIjoiVGhlIFgtQ29udGVudC1UeXBlLU9wdGlvbnMgaGVhZGVyIGlzIG5vdCBzZXQuIFRoaXMgY291bGQgYWxsb3cgdGhlIHVzZXIgYWdlbnQgdG8gcmVuZGVyIHRoZSBjb250ZW50IG9mIHRoZSBzaXRlIGluIGEgZGlmZmVyZW50IGZhc2hpb24gdG8gdGhlIE1JTUUgdHlwZS4ifSx7ImlkIjogIjYwMDU3NSIsIm1ldGhvZCI6IkhFQUQiLCJ1cmwiOiIvIiwibXNnIjoibmdpbngvMS4xOC4wIGFwcGVhcnMgdG8gYmUgb3V0ZGF0ZWQgKGN1cnJlbnQgaXMgYXQgbGVhc3QgMS4yNS4zKS4ifV19XQ==","tags":[]}]} +// % Total % Received % Xferd Average Speed Time Time Time Current +// Dload Upload Total Spent Left Speed + +// 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +// 100 903 100 158 100 745 8777 41388 --:--:-- --:--:-- --:--:-- 53117 +// {"detail":[{"type":"json_invalid","loc":["body",1],"msg":"JSON decode error","input":{},"ctx":{"error":"Expecting property name enclosed in double quotes"}}]} +// FINISHED + +function b64encode(inp) { + console.log(`Encoding: ${inp}`); + return Buffer.from(inp).toString("base64"); +} + +let out; +let output_url; + +async function main() { + const input_url = process.argv[process.argv.length - 1]; + console.log(`Getting information from INPUT_URL: ${input_url}`); + try { + var boefje_input = JSON.parse( + execSync(`curl --request GET --url ${input_url} -s`).toString(), + ); + } catch (error) { + console.error("FIRST FETCH WENT WRONG"); + console.error(error); + return; + } + + output_url = boefje_input.output_url; + const ooi = boefje_input.boefje_meta.arguments.input.address; + console.log(`Found boefje input with ooi: ${ooi}`); + + execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { + stdio: "inherit", + }); + + const file_contents = fs.readFileSync("./output.json").toString(); + return { + status: "COMPLETED", + files: [ + { + content: b64encode(file_contents), + tags: [], + }, + ], + }; +} + +main() + .then((value) => { + out = value; + }) + .catch((reason) => { + out = { + status: "FAILED", + files: [ + { + content: b64encode(reason), + tags: ["error/boefje"], + }, + ], + }; + }) + .finally(async () => { + console.log("FINISHING..."); + if (out == undefined) return; + + try { + console.log("SENDING OUT WITH:"); + console.log(JSON.stringify(out)); + console.log(output_url); + const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( + out, + ).replaceAll('"', '\\"')}`; + console.log(cmd); + try { + const x = execSync(cmd).toString(); + console.log(x); + console.log("FINISHED"); + } catch (error) { + console.error(error.status); // Might be 127 in your example. + console.error(error.message); // Holds the message you typically want. + console.error(error.stderr); // Holds the stderr output. Use `.toString()`. + console.error(error.stdout); // Holds the stdout output. Use `.toString()`. + } + } catch (error) { + console.error("SECOND FETCH WENT WRONG"); + console.error(error); + return; + } + }); diff --git a/boefjes/boefjes/plugins/kat_nikto/main.py b/boefjes/boefjes/plugins/kat_nikto/main.py deleted file mode 100644 index 971f9fddaf2..00000000000 --- a/boefjes/boefjes/plugins/kat_nikto/main.py +++ /dev/null @@ -1,24 +0,0 @@ -import json -import logging -import os - -from pydantic import BaseModel - - -class Vulnerability(BaseModel): - id: str - method: str - msg: str - - -def run(boefje_meta: dict): - file_path = os.path.join("./", "output.json") - if not os.path.isfile(file_path): - raise Exception("output.json file does not exist. Has the kat_nikto image given an error?") - - with open(file_path) as f: - json_data = json.loads(f.read())[0] - found_vulnerabilities = [Vulnerability.model_validate(x) for x in json_data["vulnerabilities"]] - logging.info(found_vulnerabilities) - - return [(set(), "a")] diff --git a/boefjes/boefjes/plugins/kat_nikto/package-lock.json b/boefjes/boefjes/plugins/kat_nikto/package-lock.json new file mode 100644 index 00000000000..5efc27623a6 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/package-lock.json @@ -0,0 +1,144 @@ +{ + "name": "kat-nikto", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "kat-nikto", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-fetch": "^3.3.2" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + } + }, + "dependencies": { + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, + "web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" + } + } +} diff --git a/boefjes/boefjes/plugins/kat_nikto/package.json b/boefjes/boefjes/plugins/kat_nikto/package.json new file mode 100644 index 00000000000..a922f16073b --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/package.json @@ -0,0 +1,15 @@ +{ + "name": "kat-nikto", + "version": "1.0.0", + "description": "", + "type": "module", + "main": "index.js", + "scripts": { + "run": "node index.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "node-fetch": "^3.3.2" + } +} From 09882a6a1c8902cc4e2c06286ed7861632032050 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Tue, 13 Aug 2024 07:52:16 +0000 Subject: [PATCH 03/37] Added `oci_adapter.js` to better mirror the python's implementation --- boefjes/boefjes/plugins/kat_nikto/boefje.json | 3 +- boefjes/boefjes/plugins/kat_nikto/index.js | 118 --------------- boefjes/boefjes/plugins/kat_nikto/main.js | 43 ++++++ .../boefjes/plugins/kat_nikto/oci_adapter.js | 78 ++++++++++ .../plugins/kat_nikto/package-lock.json | 139 +++--------------- .../boefjes/plugins/kat_nikto/package.json | 11 +- 6 files changed, 145 insertions(+), 247 deletions(-) delete mode 100644 boefjes/boefjes/plugins/kat_nikto/index.js create mode 100644 boefjes/boefjes/plugins/kat_nikto/main.js create mode 100644 boefjes/boefjes/plugins/kat_nikto/oci_adapter.js diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.json b/boefjes/boefjes/plugins/kat_nikto/boefje.json index 12223e76d5c..f10f492bb60 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.json +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.json @@ -4,7 +4,8 @@ "description": "Uses Nikto", "consumes": [ "IPAddressV4", - "IPAddressV6" + "IPAddressV6", + "Hostname" ], "environment_keys": [], "scan_level": 3, diff --git a/boefjes/boefjes/plugins/kat_nikto/index.js b/boefjes/boefjes/plugins/kat_nikto/index.js deleted file mode 100644 index ba2dbcee8a3..00000000000 --- a/boefjes/boefjes/plugins/kat_nikto/index.js +++ /dev/null @@ -1,118 +0,0 @@ -import fs from "node:fs"; -import fetch from "node-fetch"; // npm install node-fetch -import { execSync } from "node:child_process"; - -// Getting information from INPUT_URL: http://boefje:8000/api/v0/tasks/6f08f386-0dfe-4cd4-a1b4-91e95411c883 -// Found boefje input with ooi: 46.23.85.171 -// - ***** TLS/SSL support not available (see docs for SSL install) ***** -// - Nikto v2.5.0 -// --------------------------------------------------------------------------- -// + Target IP: 46.23.85.171 -// + Target Hostname: 46.23.85.171 -// + Target Port: 80 -// + Start Time: 2024-08-05 09:55:56 (GMT0) -// --------------------------------------------------------------------------- -// + Server: nginx/1.18.0 (Ubuntu) -// + /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/ -// + No CGI Directories found (use '-C all' to force check all possible dirs) -// + nginx/1.18.0 appears to be outdated (current is at least 1.25.3). -// + 8108 requests: 0 error(s) and 2 item(s) reported on remote host -// + End Time: 2024-08-05 09:56:14 (GMT0) (18 seconds) -// --------------------------------------------------------------------------- -// + 1 host(s) tested -// Encoding: [{"host":"46.23.85.171","ip":"46.23.85.171","port":"80","banner":"","vulnerabilities":[{"id": "999103","references": "https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/","method":"GET","url":"/","msg":"The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type."},{"id": "600575","method":"HEAD","url":"/","msg":"nginx/1.18.0 appears to be outdated (current is at least 1.25.3)."}]}] -// FINISHING... -// SENDING OUT WITH: -// {"status":"COMPLETED","files":[{"content":"W3siaG9zdCI6IjQ2LjIzLjg1LjE3MSIsImlwIjoiNDYuMjMuODUuMTcxIiwicG9ydCI6IjgwIiwiYmFubmVyIjoiIiwidnVsbmVyYWJpbGl0aWVzIjpbeyJpZCI6ICI5OTkxMDMiLCJyZWZlcmVuY2VzIjogImh0dHBzOi8vd3d3Lm5ldHNwYXJrZXIuY29tL3dlYi12dWxuZXJhYmlsaXR5LXNjYW5uZXIvdnVsbmVyYWJpbGl0aWVzL21pc3NpbmctY29udGVudC10eXBlLWhlYWRlci8iLCJtZXRob2QiOiJHRVQiLCJ1cmwiOiIvIiwibXNnIjoiVGhlIFgtQ29udGVudC1UeXBlLU9wdGlvbnMgaGVhZGVyIGlzIG5vdCBzZXQuIFRoaXMgY291bGQgYWxsb3cgdGhlIHVzZXIgYWdlbnQgdG8gcmVuZGVyIHRoZSBjb250ZW50IG9mIHRoZSBzaXRlIGluIGEgZGlmZmVyZW50IGZhc2hpb24gdG8gdGhlIE1JTUUgdHlwZS4ifSx7ImlkIjogIjYwMDU3NSIsIm1ldGhvZCI6IkhFQUQiLCJ1cmwiOiIvIiwibXNnIjoibmdpbngvMS4xOC4wIGFwcGVhcnMgdG8gYmUgb3V0ZGF0ZWQgKGN1cnJlbnQgaXMgYXQgbGVhc3QgMS4yNS4zKS4ifV19XQ==","tags":[]}]} -// % Total % Received % Xferd Average Speed Time Time Time Current -// Dload Upload Total Spent Left Speed - -// 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 -// 100 903 100 158 100 745 8777 41388 --:--:-- --:--:-- --:--:-- 53117 -// {"detail":[{"type":"json_invalid","loc":["body",1],"msg":"JSON decode error","input":{},"ctx":{"error":"Expecting property name enclosed in double quotes"}}]} -// FINISHED - -function b64encode(inp) { - console.log(`Encoding: ${inp}`); - return Buffer.from(inp).toString("base64"); -} - -let out; -let output_url; - -async function main() { - const input_url = process.argv[process.argv.length - 1]; - console.log(`Getting information from INPUT_URL: ${input_url}`); - try { - var boefje_input = JSON.parse( - execSync(`curl --request GET --url ${input_url} -s`).toString(), - ); - } catch (error) { - console.error("FIRST FETCH WENT WRONG"); - console.error(error); - return; - } - - output_url = boefje_input.output_url; - const ooi = boefje_input.boefje_meta.arguments.input.address; - console.log(`Found boefje input with ooi: ${ooi}`); - - execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { - stdio: "inherit", - }); - - const file_contents = fs.readFileSync("./output.json").toString(); - return { - status: "COMPLETED", - files: [ - { - content: b64encode(file_contents), - tags: [], - }, - ], - }; -} - -main() - .then((value) => { - out = value; - }) - .catch((reason) => { - out = { - status: "FAILED", - files: [ - { - content: b64encode(reason), - tags: ["error/boefje"], - }, - ], - }; - }) - .finally(async () => { - console.log("FINISHING..."); - if (out == undefined) return; - - try { - console.log("SENDING OUT WITH:"); - console.log(JSON.stringify(out)); - console.log(output_url); - const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( - out, - ).replaceAll('"', '\\"')}`; - console.log(cmd); - try { - const x = execSync(cmd).toString(); - console.log(x); - console.log("FINISHED"); - } catch (error) { - console.error(error.status); // Might be 127 in your example. - console.error(error.message); // Holds the message you typically want. - console.error(error.stderr); // Holds the stderr output. Use `.toString()`. - console.error(error.stdout); // Holds the stdout output. Use `.toString()`. - } - } catch (error) { - console.error("SECOND FETCH WENT WRONG"); - console.error(error); - return; - } - }); diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js new file mode 100644 index 00000000000..729d4798914 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -0,0 +1,43 @@ +import fs from "node:fs"; +import { execSync } from "node:child_process"; + +/** + * @param {{}} boefje_meta The string input to base64 encode + * @returns {(string | string[])[][]} + */ +export default function (boefje_meta) { + // Depending on what OOI triggered this task, the hostname / address will be in a different location + const object_type = boefje_meta.arguments.input.object_type; + let ooi = ""; + if (["IPAddressV4", "IPAddressV6"].includes(object_type)) + ooi = boefje_meta.arguments.input.address; + else if (object_type == "Hostname") ooi = boefje_meta.arguments.input.name; + else throw new Error("Unexpected boefje_meta"); + + console.log(`Found boefje input with ooi: ${ooi}`); + + // Running nikto and outputting to a file + try { + execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { + stdio: "inherit", + }); + } catch (e) { + console.error(e); + throw new Error( + "Something went wrong running the nikto command.\n" + e.message, + ); + } + + // Reading the file created by nikto + try { + var file_contents = fs.readFileSync("./output.json").toString(); + } catch (e) { + console.error(e); + throw new Error( + "Something went wrong reading the file from the nikto command.\n" + + e.message, + ); + } + console.log("File contents: " + file_contents); + return [[[], file_contents]]; +} diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js new file mode 100644 index 00000000000..a578bf88b3e --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -0,0 +1,78 @@ +import { execSync } from "node:child_process"; +import run from "./main.js"; + +/** + * @param {string} inp The string input to base64 encode + */ +function b64encode(inp) { + console.log(`Encoding: ${inp}`); + return Buffer.from(inp).toString("base64"); +} + +let out; +let output_url; + +async function main() { + const input_url = process.argv[process.argv.length - 1]; + + // Getting the boefje input + try { + var boefje_input = JSON.parse( + execSync(`curl --request GET --url ${input_url} -s`).toString(), + ); + } catch (error) { + console.error(`Getting boefje input went wrong with URL: ${input_url}`); + throw new Error(error); + } + + output_url = boefje_input.output_url; + const raws = run(boefje_input.boefje_meta); + console.log("RAWS: " + JSON.stringify(raws)); + return { + status: "COMPLETED", + files: raws.map((x) => { + return { + content: b64encode(x[1]), + tags: x[0], + }; + }), + }; +} + +main() + .then((value) => { + out = value; + }) + .catch((reason) => { + out = { + status: "FAILED", + files: [ + { + content: b64encode("main caught an error: " + reason), + tags: ["error/boefje"], + }, + ], + }; + }) + .finally(async () => { + console.log("Finishing with: " + out); + if (out == undefined) return console.error("Somehow `out` was not set."); + + try { + console.log("SENDING OUT WITH: " + JSON.stringify(out)); + const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( + out, + ).replaceAll('"', '\\"')}`; + console.log(cmd); + try { + execSync(cmd).toString(); + console.log("FINISHED"); + } catch (error) { + console.error( + "Something went wrong outputting to the boefje api: " + error.message, + ); + } + } catch (error) { + console.error("SECOND FETCH WENT WRONG: " + error); + } + }); diff --git a/boefjes/boefjes/plugins/kat_nikto/package-lock.json b/boefjes/boefjes/plugins/kat_nikto/package-lock.json index 5efc27623a6..daa0ba14207 100644 --- a/boefjes/boefjes/plugins/kat_nikto/package-lock.json +++ b/boefjes/boefjes/plugins/kat_nikto/package-lock.json @@ -7,138 +7,37 @@ "": { "name": "kat-nikto", "version": "1.0.0", - "license": "ISC", "dependencies": { - "node-fetch": "^3.3.2" + "@types/node": "^22.1.0" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "undici-types": "~6.13.0" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "engines": { - "node": ">= 8" - } + "node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" } }, "dependencies": { - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "undici-types": "~6.13.0" } }, - "web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" + "undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" } } } diff --git a/boefjes/boefjes/plugins/kat_nikto/package.json b/boefjes/boefjes/plugins/kat_nikto/package.json index a922f16073b..890572426c1 100644 --- a/boefjes/boefjes/plugins/kat_nikto/package.json +++ b/boefjes/boefjes/plugins/kat_nikto/package.json @@ -1,15 +1,10 @@ { "name": "kat-nikto", "version": "1.0.0", - "description": "", "type": "module", - "main": "index.js", - "scripts": { - "run": "node index.js" - }, - "author": "", - "license": "ISC", + "main": "oci_adapter.js", + "author": "cynalytics", "dependencies": { - "node-fetch": "^3.3.2" + "@types/node": "^22.1.0" } } From 022ac4e1a86ab8819fc21dd7b5d311ff91ac2b68 Mon Sep 17 00:00:00 2001 From: noamblitz Date: Mon, 19 Aug 2024 12:24:36 +0200 Subject: [PATCH 04/37] generic cve normalier --- .../plugins/kat_cve_normalizer/__init__.py | 0 .../plugins/kat_cve_normalizer/normalize.py | 20 +++++++++++++++++++ .../kat_cve_normalizer/normalizer.json | 10 ++++++++++ 3 files changed, 30 insertions(+) create mode 100644 boefjes/boefjes/plugins/kat_cve_normalizer/__init__.py create mode 100644 boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py create mode 100644 boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/__init__.py b/boefjes/boefjes/plugins/kat_cve_normalizer/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py new file mode 100644 index 00000000000..faf2e79a7ef --- /dev/null +++ b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py @@ -0,0 +1,20 @@ +from collections.abc import Iterable + +from boefjes.job_models import NormalizerOutput +from octopoes.models import Reference +from octopoes.models.ooi.findings import CVEFindingType, Finding + + +def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: + ooi = Reference.from_str(input_ooi["primary_key"]) + cve_id = raw.decode() + + if cve_id: + finding_type = CVEFindingType(id=cve_id) + finding = Finding( + finding_type=finding_type.reference, + ooi=ooi, + description=f"CVE {cve_id} is found on this OOI", + ) + yield finding_type + yield finding diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json new file mode 100644 index 00000000000..cb777e04a7b --- /dev/null +++ b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json @@ -0,0 +1,10 @@ +{ + "id": "kat_generic_cve_normalize", + "consumes": [ + "cve/id" + ], + "produces": [ + "Finding", + "CVEFindingType" + ] +} From 7572d1e0a474cbfd8f37f34e767ef7769cf3cde9 Mon Sep 17 00:00:00 2001 From: noamblitz Date: Mon, 19 Aug 2024 12:24:57 +0200 Subject: [PATCH 05/37] switch to generic cve normalizer --- .../plugins/kat_cve_2023_34039/main.py | 9 +-------- .../plugins/kat_cve_2023_34039/normalize.py | 19 ------------------- .../kat_cve_2023_34039/normalizer.json | 10 ---------- 3 files changed, 1 insertion(+), 37 deletions(-) delete mode 100644 boefjes/boefjes/plugins/kat_cve_2023_34039/normalize.py delete mode 100644 boefjes/boefjes/plugins/kat_cve_2023_34039/normalizer.json diff --git a/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py b/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py index f6e580e1468..4c4642e79ac 100644 --- a/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py +++ b/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py @@ -51,14 +51,7 @@ def run(boefje_meta: BoefjeMeta) -> list[tuple[set, str | bytes]]: coutput = os.system(" ".join(ssh_command)) # noqa: S605 if coutput not in (0, 32512): # 0 = it worked, 32512 = `exit` does not exists but we did connect continue - return [ - ( - set(), - "\n".join( - (str(coutput), f"{key_file} is allowed access to vRealize Network Insight on {ip}:{port}") - ), - ) - ] + return [({"cve/id"}, "CVE-2023-34039")] except Exception: # noqa: S112 continue diff --git a/boefjes/boefjes/plugins/kat_cve_2023_34039/normalize.py b/boefjes/boefjes/plugins/kat_cve_2023_34039/normalize.py deleted file mode 100644 index b379e8158f1..00000000000 --- a/boefjes/boefjes/plugins/kat_cve_2023_34039/normalize.py +++ /dev/null @@ -1,19 +0,0 @@ -from collections.abc import Iterable - -from boefjes.job_models import NormalizerOutput -from octopoes.models import Reference -from octopoes.models.ooi.findings import CVEFindingType, Finding - - -def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: - ooi = Reference.from_str(input_ooi["primary_key"]) - - if "is allowed access to vRealize Network Insight " in raw.decode(): - finding_type = CVEFindingType(id="CVE-2023-34039") - finding = Finding( - finding_type=finding_type.reference, - ooi=ooi, - description="Service is most likely vulnerable to CVE-2023-34039", - ) - yield finding_type - yield finding diff --git a/boefjes/boefjes/plugins/kat_cve_2023_34039/normalizer.json b/boefjes/boefjes/plugins/kat_cve_2023_34039/normalizer.json deleted file mode 100644 index 4cbb1bddda9..00000000000 --- a/boefjes/boefjes/plugins/kat_cve_2023_34039/normalizer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "kat_cve_2023_normalize", - "consumes": [ - "boefje/CVE-2023-34039" - ], - "produces": [ - "Finding", - "CVEFindingType" - ] -} From a1765f1c65534f94b912329a409ff080474254ba Mon Sep 17 00:00:00 2001 From: noamblitz Date: Mon, 19 Aug 2024 12:35:20 +0200 Subject: [PATCH 06/37] also output orignal boefje output --- boefjes/boefjes/plugins/kat_cve_2023_34039/main.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py b/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py index 4c4642e79ac..63f37a24ef2 100644 --- a/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py +++ b/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py @@ -51,7 +51,15 @@ def run(boefje_meta: BoefjeMeta) -> list[tuple[set, str | bytes]]: coutput = os.system(" ".join(ssh_command)) # noqa: S605 if coutput not in (0, 32512): # 0 = it worked, 32512 = `exit` does not exists but we did connect continue - return [({"cve/id"}, "CVE-2023-34039")] + return [ + ( + set(), + "\n".join( + (str(coutput), f"{key_file} is allowed access to vRealize Network Insight on {ip}:{port}") + ), + ), + ({"cve/id"}, "CVE-2023-34039"), + ] except Exception: # noqa: S112 continue From 6f84904d1fb2323bbfe3b134a78a680bad0b8e0c Mon Sep 17 00:00:00 2001 From: noamblitz Date: Mon, 19 Aug 2024 13:08:02 +0200 Subject: [PATCH 07/37] update docs on generic cve normalizer --- .../development_tutorial/creating_a_boefje.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md b/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md index 719c885c7de..f55e831a3f8 100644 --- a/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md +++ b/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md @@ -126,6 +126,8 @@ def run(boefje_meta: dict) -> list[tuple[set, bytes | str]]: The most important part is the return value we send back. This is what will be used by our normalizer to create our new OOIs. +For ease of development, we added a generic CVE normalizer. When we just want to create a CVE finding on the input OOI, we can return the CVE ID as a string with `cve/id` as mime-type. + --- The final task of creating a boefje is specifying what DockerFile our boefje should use. We can do this inside the file located in `boefjes/Makefile`. From 0e057bb017f3ad490d6e64b4637d5c75e5abfa61 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Thu, 22 Aug 2024 09:26:33 +0000 Subject: [PATCH 08/37] Cleaned up code --- boefjes/boefjes/plugins/kat_nikto/oci_adapter.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index a578bf88b3e..d1cd586f164 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -2,7 +2,8 @@ import { execSync } from "node:child_process"; import run from "./main.js"; /** - * @param {string} inp The string input to base64 encode + * @param {string} inp The string input to base64 + * @returns {string} */ function b64encode(inp) { console.log(`Encoding: ${inp}`); @@ -30,12 +31,10 @@ async function main() { console.log("RAWS: " + JSON.stringify(raws)); return { status: "COMPLETED", - files: raws.map((x) => { - return { - content: b64encode(x[1]), - tags: x[0], - }; - }), + files: raws.map((x) => ({ + content: b64encode(x[1]), + tags: x[0], + })), }; } @@ -56,7 +55,7 @@ main() }) .finally(async () => { console.log("Finishing with: " + out); - if (out == undefined) return console.error("Somehow `out` was not set."); + if (out == undefined) return console.error("`out` is undefined."); try { console.log("SENDING OUT WITH: " + JSON.stringify(out)); From 50e85aeb0e69aca1bc5a58fec4c2a47d30c39d1c Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Thu, 22 Aug 2024 11:57:09 +0000 Subject: [PATCH 09/37] Added normalizer to kat_nikto boefje --- .../boefjes/plugins/kat_nikto/normalize.py | 28 +++++++++++++++++++ .../boefjes/plugins/kat_nikto/normalizer.json | 10 +++++++ 2 files changed, 38 insertions(+) create mode 100644 boefjes/boefjes/plugins/kat_nikto/normalize.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/normalizer.json diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py new file mode 100644 index 00000000000..f16c571c895 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -0,0 +1,28 @@ +import json +import logging +from collections.abc import Iterable + +from boefjes.job_models import NormalizerOutput +from octopoes.models import Reference +from octopoes.models.ooi.software import Software, SoftwareInstance + + +def scan_outdated_software(data: dict, ooi_ref): + for scan in data: + for vulnerability in scan["vulnerabilities"]: + # If the scanned vulnerability has to do with outdated software + if vulnerability["id"].startswith("6"): + software_name, found_version = vulnerability["msg"].split()[0].split("/") + + software = Software(name=software_name, version=found_version) + yield software + yield SoftwareInstance(ooi=ooi_ref, software=software.reference) + + +def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: + logging.info(input_ooi) + data = json.loads(raw) + + ooi_ref = Reference.from_str(input_ooi["primary_key"]) + + yield from scan_outdated_software(data, ooi_ref) diff --git a/boefjes/boefjes/plugins/kat_nikto/normalizer.json b/boefjes/boefjes/plugins/kat_nikto/normalizer.json new file mode 100644 index 00000000000..7e9e2f5ae09 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/normalizer.json @@ -0,0 +1,10 @@ +{ + "id": "kat_nikto_normalize", + "consumes": [ + "boefje/nikto" + ], + "produces": [ + "Software", + "SoftwareInstance" + ] +} From 6af750e7eb72fc742054793b0600478afe80f7f9 Mon Sep 17 00:00:00 2001 From: noamblitz <43830693+noamblitz@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:18:38 +0200 Subject: [PATCH 10/37] Update boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json Co-authored-by: Jan Klopper --- boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json index cb777e04a7b..e58247fb5f2 100644 --- a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json +++ b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json @@ -1,7 +1,7 @@ { "id": "kat_generic_cve_normalize", "consumes": [ - "cve/id" + "openkat/finding" ], "produces": [ "Finding", From 7b62c257e7b408c234c2fbdcc92506de343e3a53 Mon Sep 17 00:00:00 2001 From: noamblitz <43830693+noamblitz@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:18:46 +0200 Subject: [PATCH 11/37] Update boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json Co-authored-by: Jan Klopper --- boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json index e58247fb5f2..ec7e54b209c 100644 --- a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json +++ b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json @@ -1,5 +1,5 @@ { - "id": "kat_generic_cve_normalize", + "id": "kat_generic_finding_normalize", "consumes": [ "openkat/finding" ], From 45c000f5ff5f34fa3f689be5dd25da0091e28d02 Mon Sep 17 00:00:00 2001 From: noamblitz <43830693+noamblitz@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:18:53 +0200 Subject: [PATCH 12/37] Update docs/source/developer_documentation/development_tutorial/creating_a_boefje.md Co-authored-by: Jan Klopper --- .../development_tutorial/creating_a_boefje.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md b/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md index f55e831a3f8..23894b9bbd2 100644 --- a/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md +++ b/docs/source/developer_documentation/development_tutorial/creating_a_boefje.md @@ -126,7 +126,7 @@ def run(boefje_meta: dict) -> list[tuple[set, bytes | str]]: The most important part is the return value we send back. This is what will be used by our normalizer to create our new OOIs. -For ease of development, we added a generic CVE normalizer. When we just want to create a CVE finding on the input OOI, we can return the CVE ID as a string with `cve/id` as mime-type. +For ease of development, we added a generic finding normalizer. When we just want to create a CVE or other type of finding on the input OOI, we can return the CVE ID, CWE ID or KAT ID as a string with `openkat/finding` as mime-type. --- From ac6ca62da74d4e4d4a31f2a5bd8978003354e36d Mon Sep 17 00:00:00 2001 From: noamblitz <43830693+noamblitz@users.noreply.github.com> Date: Thu, 22 Aug 2024 14:18:59 +0200 Subject: [PATCH 13/37] Update boefjes/boefjes/plugins/kat_cve_2023_34039/main.py Co-authored-by: Jan Klopper --- boefjes/boefjes/plugins/kat_cve_2023_34039/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py b/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py index 63f37a24ef2..d5bd7f4795a 100644 --- a/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py +++ b/boefjes/boefjes/plugins/kat_cve_2023_34039/main.py @@ -58,7 +58,7 @@ def run(boefje_meta: BoefjeMeta) -> list[tuple[set, str | bytes]]: (str(coutput), f"{key_file} is allowed access to vRealize Network Insight on {ip}:{port}") ), ), - ({"cve/id"}, "CVE-2023-34039"), + ({"openkat/finding"}, "CVE-2023-34039"), ] except Exception: # noqa: S112 From 5ae981e376888fb40ecbb36f33e38c205908fc78 Mon Sep 17 00:00:00 2001 From: noamblitz Date: Thu, 22 Aug 2024 14:29:02 +0200 Subject: [PATCH 14/37] allow comma seperated list of all findingtypes --- .../plugins/kat_cve_normalizer/normalize.py | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py index faf2e79a7ef..256fda3a8c0 100644 --- a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py +++ b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py @@ -1,20 +1,38 @@ +import re from collections.abc import Iterable from boefjes.job_models import NormalizerOutput from octopoes.models import Reference -from octopoes.models.ooi.findings import CVEFindingType, Finding +from octopoes.models.ooi.findings import CVEFindingType, Finding, KATFindingType, RetireJSFindingType, SnykFindingType def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: ooi = Reference.from_str(input_ooi["primary_key"]) - cve_id = raw.decode() + finding_ids_str = raw.decode() + finding_ids_list = [fid.strip().upper() for fid in finding_ids_str.split(",")] - if cve_id: - finding_type = CVEFindingType(id=cve_id) - finding = Finding( - finding_type=finding_type.reference, - ooi=ooi, - description=f"CVE {cve_id} is found on this OOI", - ) - yield finding_type - yield finding + # Validating CVE format (e.g., CVE-YYYY-NNNNN) + cve_pattern = re.compile(r"CVE-\d{4}-\d{4,7}") + + finding_type_mapping = { + "CVE-": CVEFindingType, + "KAT-": KATFindingType, + "SNYK-": SnykFindingType, + "RETIREJS-": RetireJSFindingType, + } + + for finding_id in finding_ids_list: + if finding_id.startswith("CVE-") and not cve_pattern.match(finding_id): + continue # skip incorrect cves + + for prefix, FindingTypeClass in finding_type_mapping.items(): + if finding_id.startswith(prefix): + finding_type = FindingTypeClass(id=finding_id) + finding = Finding( + finding_type=finding_type.reference, + ooi=ooi, + description=f"{finding_id} is found on this OOI", + ) + yield finding_type + yield finding + break From 09ea726393e4f5ff0b9df364be365ba1b2be46c4 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 09:38:32 +0000 Subject: [PATCH 15/37] Added new OOI that has information about outdated software --- boefjes/boefjes/plugins/kat_nikto/normalize.py | 17 +++++++++++++++-- octopoes/octopoes/models/ooi/software.py | 16 ++++++++++++++++ octopoes/octopoes/models/types.py | 4 ++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py index f16c571c895..49a06eb7d7d 100644 --- a/boefjes/boefjes/plugins/kat_nikto/normalize.py +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -1,10 +1,11 @@ import json import logging +import re from collections.abc import Iterable from boefjes.job_models import NormalizerOutput from octopoes.models import Reference -from octopoes.models.ooi.software import Software, SoftwareInstance +from octopoes.models.ooi.software import OutdatedSoftwareInstance, Software, SoftwareInstance def scan_outdated_software(data: dict, ooi_ref): @@ -14,9 +15,21 @@ def scan_outdated_software(data: dict, ooi_ref): if vulnerability["id"].startswith("6"): software_name, found_version = vulnerability["msg"].split()[0].split("/") + # REGEX: get the text between "least " and ")" to get the latest version + match = re.search(r"least (.*)\)", vulnerability["msg"]) + if match is None: + logging.error("No version number found on supposedly outdated software") + continue + newest_version = match.group(1) software = Software(name=software_name, version=found_version) + software_instance = SoftwareInstance(ooi=ooi_ref, software=software.reference) yield software - yield SoftwareInstance(ooi=ooi_ref, software=software.reference) + yield software_instance + yield OutdatedSoftwareInstance( + ooi=ooi_ref, + software_instance=software_instance.reference, + newest_version=newest_version, + ) def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: diff --git a/octopoes/octopoes/models/ooi/software.py b/octopoes/octopoes/models/ooi/software.py index 91a7fbddf47..cfc0357e2e7 100644 --- a/octopoes/octopoes/models/ooi/software.py +++ b/octopoes/octopoes/models/ooi/software.py @@ -43,3 +43,19 @@ def format_reference_human_readable(cls, reference: Reference) -> str: ooi_reference = Reference.from_str("|".join(parts[0:-4])) software_reference = Reference.from_str("|".join(parts[-4:])) return f"{software_reference.human_readable} @ {ooi_reference.human_readable}" + + +class OutdatedSoftwareInstance(OOI): + object_type: Literal["OutdatedSoftwareInstance"] = "OutdatedSoftwareInstance" + + _natural_key_attrs = ["ooi", "software", "newest_version"] + + ooi: Reference = ReferenceField(OOI, max_issue_scan_level=0, max_inherit_scan_level=1) + software_instance: Reference = ReferenceField(SoftwareInstance, max_issue_scan_level=1, max_inherit_scan_level=0) + newest_version: str | None = None + + @classmethod + def format_reference_human_readable(cls, reference: Reference) -> str: + return reference.human_readable + + # TODO: create `format_reference_human_readable` to include `newest_version` diff --git a/octopoes/octopoes/models/types.py b/octopoes/octopoes/models/types.py index aa99b0f1399..4137b692eb1 100644 --- a/octopoes/octopoes/models/types.py +++ b/octopoes/octopoes/models/types.py @@ -60,7 +60,7 @@ from octopoes.models.ooi.question import Question from octopoes.models.ooi.reports import Report, ReportData from octopoes.models.ooi.service import IPService, Service, TLSCipher -from octopoes.models.ooi.software import Software, SoftwareInstance +from octopoes.models.ooi.software import OutdatedSoftwareInstance, Software, SoftwareInstance from octopoes.models.ooi.web import ( RESTAPI, URL, @@ -107,7 +107,7 @@ ConcreteNetworkType = Network | IPAddressV4 | IPAddressV6 | AutonomousSystem | IPV4NetBlock | IPV6NetBlock | IPPort NetworkType = ConcreteNetworkType | IPAddress ServiceType = Service | IPService | TLSCipher -SoftwareType = Software | SoftwareInstance +SoftwareType = Software | SoftwareInstance | OutdatedSoftwareInstance WebType = ( Website | URL From 1322be6d1190e2d283de4ff756b6407005869bf6 Mon Sep 17 00:00:00 2001 From: noamblitz Date: Fri, 23 Aug 2024 12:32:03 +0200 Subject: [PATCH 16/37] use direct mapping --- .../plugins/kat_cve_normalizer/normalize.py | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py index 256fda3a8c0..0cc68c03f71 100644 --- a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py +++ b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py @@ -5,34 +5,34 @@ from octopoes.models import Reference from octopoes.models.ooi.findings import CVEFindingType, Finding, KATFindingType, RetireJSFindingType, SnykFindingType +CVE_PATTERN = re.compile(r"CVE-\d{4}-\d{4,7}") + def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: ooi = Reference.from_str(input_ooi["primary_key"]) finding_ids_str = raw.decode() finding_ids_list = [fid.strip().upper() for fid in finding_ids_str.split(",")] - # Validating CVE format (e.g., CVE-YYYY-NNNNN) - cve_pattern = re.compile(r"CVE-\d{4}-\d{4,7}") - finding_type_mapping = { - "CVE-": CVEFindingType, - "KAT-": KATFindingType, - "SNYK-": SnykFindingType, - "RETIREJS-": RetireJSFindingType, + "CVE": CVEFindingType, + "KAT": KATFindingType, + "SNYK": SnykFindingType, + "RETIREJS": RetireJSFindingType, } for finding_id in finding_ids_list: - if finding_id.startswith("CVE-") and not cve_pattern.match(finding_id): - continue # skip incorrect cves - - for prefix, FindingTypeClass in finding_type_mapping.items(): - if finding_id.startswith(prefix): - finding_type = FindingTypeClass(id=finding_id) - finding = Finding( - finding_type=finding_type.reference, - ooi=ooi, - description=f"{finding_id} is found on this OOI", - ) - yield finding_type - yield finding - break + parts = finding_id.split("-") + prefix = parts[0] + + if prefix in finding_type_mapping: + if prefix == "CVE" and not CVE_PATTERN.match(finding_id): + continue # skip incorrect cves + + finding_type = finding_type_mapping[prefix](id=finding_id) + finding = Finding( + finding_type=finding_type.reference, + ooi=ooi, + description=f"{finding_id} is found on this OOI", + ) + yield finding_type + yield finding From d57565a151f9b2c6720b31ec432ac7ad90b10c01 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 11:17:30 +0000 Subject: [PATCH 17/37] Rewrote `oci_adapter.js` to work like `oci_adapter.py` does --- .../boefjes/plugins/kat_nikto/oci_adapter.js | 74 ++++++++----------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index d1cd586f164..18c7d8fb73f 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -10,10 +10,7 @@ function b64encode(inp) { return Buffer.from(inp).toString("base64"); } -let out; -let output_url; - -async function main() { +function main() { const input_url = process.argv[process.argv.length - 1]; // Getting the boefje input @@ -26,52 +23,41 @@ async function main() { throw new Error(error); } - output_url = boefje_input.output_url; - const raws = run(boefje_input.boefje_meta); - console.log("RAWS: " + JSON.stringify(raws)); - return { - status: "COMPLETED", - files: raws.map((x) => ({ - content: b64encode(x[1]), - tags: x[0], - })), - }; -} - -main() - .then((value) => { - out = value; - }) - .catch((reason) => { + let out = undefined; + let output_url = boefje_input.output_url; + try { + // Getting the raw files + const raws = run(boefje_input.boefje_meta); + out = { + status: "COMPLETED", + files: raws.map((x) => ({ + content: b64encode(x[1]), + tags: x[0], + })), + }; + } catch (error) { out = { status: "FAILED", files: [ { - content: b64encode("main caught an error: " + reason), + content: b64encode("Boefje caught an error: " + error.message), tags: ["error/boefje"], }, ], }; - }) - .finally(async () => { - console.log("Finishing with: " + out); - if (out == undefined) return console.error("`out` is undefined."); + } + + // Example command + /* + curl --request POST \ + --url http://boefje/api/v0/tasks/7342e8dd-b945-4185-aaec-787205b7b664 \ + --header 'Content-Type: application/json' \ + --data '{"status":"COMPLETED","files":[{"content":"BASE_64_ENCODED_CONTENT","tags":[]}]}' + */ + const out_json = JSON.stringify(out); + const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data '${out_json}'`; + + execSync(cmd); +} - try { - console.log("SENDING OUT WITH: " + JSON.stringify(out)); - const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( - out, - ).replaceAll('"', '\\"')}`; - console.log(cmd); - try { - execSync(cmd).toString(); - console.log("FINISHED"); - } catch (error) { - console.error( - "Something went wrong outputting to the boefje api: " + error.message, - ); - } - } catch (error) { - console.error("SECOND FETCH WENT WRONG: " + error); - } - }); +main(); From 0712f4de1b5dc8426a0ebab9adbad8fb1b78c774 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 11:31:28 +0000 Subject: [PATCH 18/37] Fixed example url --- boefjes/boefjes/plugins/kat_nikto/oci_adapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index 18c7d8fb73f..2ab82c478f1 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -50,7 +50,7 @@ function main() { // Example command /* curl --request POST \ - --url http://boefje/api/v0/tasks/7342e8dd-b945-4185-aaec-787205b7b664 \ + --url http://boefje:8000/api/v0/tasks/7342e8dd-b945-4185-aaec-787205b7b664 \ --header 'Content-Type: application/json' \ --data '{"status":"COMPLETED","files":[{"content":"BASE_64_ENCODED_CONTENT","tags":[]}]}' */ From b3a32526800afbecd53ba20f24044a15a302919a Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 31 Jul 2024 10:07:35 +0000 Subject: [PATCH 19/37] Made base format for new boefje --- boefjes/boefjes/plugins/kat_nikto/__init__.py | 0 .../plugins/kat_nikto/boefje.Dockerfile | 15 +++++++++++ boefjes/boefjes/plugins/kat_nikto/boefje.json | 13 ++++++++++ boefjes/boefjes/plugins/kat_nikto/cover.jpg | Bin 0 -> 62267 bytes .../boefjes/plugins/kat_nikto/description.md | 23 +++++++++++++++++ boefjes/boefjes/plugins/kat_nikto/main.py | 24 ++++++++++++++++++ boefjes/boefjes/plugins/kat_nikto/schema.json | 6 +++++ 7 files changed, 81 insertions(+) create mode 100644 boefjes/boefjes/plugins/kat_nikto/__init__.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile create mode 100644 boefjes/boefjes/plugins/kat_nikto/boefje.json create mode 100644 boefjes/boefjes/plugins/kat_nikto/cover.jpg create mode 100644 boefjes/boefjes/plugins/kat_nikto/description.md create mode 100644 boefjes/boefjes/plugins/kat_nikto/main.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/schema.json diff --git a/boefjes/boefjes/plugins/kat_nikto/__init__.py b/boefjes/boefjes/plugins/kat_nikto/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile new file mode 100644 index 00000000000..0af140a1d0d --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -0,0 +1,15 @@ +FROM python:3.11-slim + +WORKDIR /app +RUN apt-get update && pip install httpx + +ARG BOEFJE_PATH=./boefjes/plugins/kat_nmap_tcp +ENV PYTHONPATH=/app:$BOEFJE_PATH + +COPY ./images/oci_adapter.py ./ +COPY $BOEFJE_PATH $BOEFJE_PATH + +RUN git clone https://github.com/sullo/nikto +RUN ./nikto/program/nikto.pl -h 46.23.85.171 -o ./output.json + +ENTRYPOINT ["/usr/local/bin/python", "-m", "oci_adapter"] diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.json b/boefjes/boefjes/plugins/kat_nikto/boefje.json new file mode 100644 index 00000000000..12223e76d5c --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.json @@ -0,0 +1,13 @@ +{ + "id": "nikto", + "name": "Nikto", + "description": "Uses Nikto", + "consumes": [ + "IPAddressV4", + "IPAddressV6" + ], + "environment_keys": [], + "scan_level": 3, + "oci_image": "openkat/nikto", + "oci_arguments": [] +} diff --git a/boefjes/boefjes/plugins/kat_nikto/cover.jpg b/boefjes/boefjes/plugins/kat_nikto/cover.jpg new file mode 100644 index 0000000000000000000000000000000000000000..d509564388d68d3189bab55cc28aa5073cc53248 GIT binary patch literal 62267 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 Date: Wed, 7 Aug 2024 04:48:43 +0000 Subject: [PATCH 20/37] Fixed issue of nikto boefje not contacting boefje api --- boefjes/Makefile | 2 +- .../boefjes/plugins/kat_nikto/.dockerignore | 4 + .../plugins/kat_nikto/boefje.Dockerfile | 19 +-- boefjes/boefjes/plugins/kat_nikto/index.js | 118 ++++++++++++++ boefjes/boefjes/plugins/kat_nikto/main.py | 24 --- .../plugins/kat_nikto/package-lock.json | 144 ++++++++++++++++++ .../boefjes/plugins/kat_nikto/package.json | 15 ++ 7 files changed, 292 insertions(+), 34 deletions(-) create mode 100644 boefjes/boefjes/plugins/kat_nikto/.dockerignore create mode 100644 boefjes/boefjes/plugins/kat_nikto/index.js delete mode 100644 boefjes/boefjes/plugins/kat_nikto/main.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/package-lock.json create mode 100644 boefjes/boefjes/plugins/kat_nikto/package.json diff --git a/boefjes/Makefile b/boefjes/Makefile index 09e5fc21b47..e9e3e08906e 100644 --- a/boefjes/Makefile +++ b/boefjes/Makefile @@ -40,7 +40,7 @@ images: # Build the images for the containerized boefjes # docker build -f images/base.Dockerfile -t ghcr.io/minvws/openkat/dns-records --build-arg BOEFJE_PATH=./boefjes/plugins/kat_dns . docker build -f ./boefjes/plugins/kat_dnssec/boefje.Dockerfile -t ghcr.io/minvws/openkat/dns-sec:latest . docker build -f ./boefjes/plugins/kat_nmap_tcp/boefje.Dockerfile -t ghcr.io/minvws/openkat/nmap:latest . - + docker build -f ./boefjes/plugins/kat_nikto/boefje.Dockerfile -t openkat/nikto . ## ##|------------------------------------------------------------------------| diff --git a/boefjes/boefjes/plugins/kat_nikto/.dockerignore b/boefjes/boefjes/plugins/kat_nikto/.dockerignore new file mode 100644 index 00000000000..476b7d85f6a --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/.dockerignore @@ -0,0 +1,4 @@ +.git +*Dockerfile* +*docker-compose* +node_modules diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile index 0af140a1d0d..ed9308c735e 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -1,15 +1,16 @@ -FROM python:3.11-slim +FROM node:19-bullseye WORKDIR /app -RUN apt-get update && pip install httpx +RUN apt update +RUN apt install -y git -ARG BOEFJE_PATH=./boefjes/plugins/kat_nmap_tcp -ENV PYTHONPATH=/app:$BOEFJE_PATH - -COPY ./images/oci_adapter.py ./ -COPY $BOEFJE_PATH $BOEFJE_PATH RUN git clone https://github.com/sullo/nikto -RUN ./nikto/program/nikto.pl -h 46.23.85.171 -o ./output.json -ENTRYPOINT ["/usr/local/bin/python", "-m", "oci_adapter"] +ARG BOEFJE_PATH=./boefjes/plugins/kat_nikto +COPY $BOEFJE_PATH ./ + +RUN npm ci + +ENTRYPOINT [ "node", "./" ] +# node ./ "http://localhost:8006/api/v0/tasks/ff208697-c332-4b04-919d-755b014e881d" diff --git a/boefjes/boefjes/plugins/kat_nikto/index.js b/boefjes/boefjes/plugins/kat_nikto/index.js new file mode 100644 index 00000000000..ba2dbcee8a3 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/index.js @@ -0,0 +1,118 @@ +import fs from "node:fs"; +import fetch from "node-fetch"; // npm install node-fetch +import { execSync } from "node:child_process"; + +// Getting information from INPUT_URL: http://boefje:8000/api/v0/tasks/6f08f386-0dfe-4cd4-a1b4-91e95411c883 +// Found boefje input with ooi: 46.23.85.171 +// - ***** TLS/SSL support not available (see docs for SSL install) ***** +// - Nikto v2.5.0 +// --------------------------------------------------------------------------- +// + Target IP: 46.23.85.171 +// + Target Hostname: 46.23.85.171 +// + Target Port: 80 +// + Start Time: 2024-08-05 09:55:56 (GMT0) +// --------------------------------------------------------------------------- +// + Server: nginx/1.18.0 (Ubuntu) +// + /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/ +// + No CGI Directories found (use '-C all' to force check all possible dirs) +// + nginx/1.18.0 appears to be outdated (current is at least 1.25.3). +// + 8108 requests: 0 error(s) and 2 item(s) reported on remote host +// + End Time: 2024-08-05 09:56:14 (GMT0) (18 seconds) +// --------------------------------------------------------------------------- +// + 1 host(s) tested +// Encoding: [{"host":"46.23.85.171","ip":"46.23.85.171","port":"80","banner":"","vulnerabilities":[{"id": "999103","references": "https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/","method":"GET","url":"/","msg":"The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type."},{"id": "600575","method":"HEAD","url":"/","msg":"nginx/1.18.0 appears to be outdated (current is at least 1.25.3)."}]}] +// FINISHING... +// SENDING OUT WITH: +// {"status":"COMPLETED","files":[{"content":"W3siaG9zdCI6IjQ2LjIzLjg1LjE3MSIsImlwIjoiNDYuMjMuODUuMTcxIiwicG9ydCI6IjgwIiwiYmFubmVyIjoiIiwidnVsbmVyYWJpbGl0aWVzIjpbeyJpZCI6ICI5OTkxMDMiLCJyZWZlcmVuY2VzIjogImh0dHBzOi8vd3d3Lm5ldHNwYXJrZXIuY29tL3dlYi12dWxuZXJhYmlsaXR5LXNjYW5uZXIvdnVsbmVyYWJpbGl0aWVzL21pc3NpbmctY29udGVudC10eXBlLWhlYWRlci8iLCJtZXRob2QiOiJHRVQiLCJ1cmwiOiIvIiwibXNnIjoiVGhlIFgtQ29udGVudC1UeXBlLU9wdGlvbnMgaGVhZGVyIGlzIG5vdCBzZXQuIFRoaXMgY291bGQgYWxsb3cgdGhlIHVzZXIgYWdlbnQgdG8gcmVuZGVyIHRoZSBjb250ZW50IG9mIHRoZSBzaXRlIGluIGEgZGlmZmVyZW50IGZhc2hpb24gdG8gdGhlIE1JTUUgdHlwZS4ifSx7ImlkIjogIjYwMDU3NSIsIm1ldGhvZCI6IkhFQUQiLCJ1cmwiOiIvIiwibXNnIjoibmdpbngvMS4xOC4wIGFwcGVhcnMgdG8gYmUgb3V0ZGF0ZWQgKGN1cnJlbnQgaXMgYXQgbGVhc3QgMS4yNS4zKS4ifV19XQ==","tags":[]}]} +// % Total % Received % Xferd Average Speed Time Time Time Current +// Dload Upload Total Spent Left Speed + +// 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 +// 100 903 100 158 100 745 8777 41388 --:--:-- --:--:-- --:--:-- 53117 +// {"detail":[{"type":"json_invalid","loc":["body",1],"msg":"JSON decode error","input":{},"ctx":{"error":"Expecting property name enclosed in double quotes"}}]} +// FINISHED + +function b64encode(inp) { + console.log(`Encoding: ${inp}`); + return Buffer.from(inp).toString("base64"); +} + +let out; +let output_url; + +async function main() { + const input_url = process.argv[process.argv.length - 1]; + console.log(`Getting information from INPUT_URL: ${input_url}`); + try { + var boefje_input = JSON.parse( + execSync(`curl --request GET --url ${input_url} -s`).toString(), + ); + } catch (error) { + console.error("FIRST FETCH WENT WRONG"); + console.error(error); + return; + } + + output_url = boefje_input.output_url; + const ooi = boefje_input.boefje_meta.arguments.input.address; + console.log(`Found boefje input with ooi: ${ooi}`); + + execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { + stdio: "inherit", + }); + + const file_contents = fs.readFileSync("./output.json").toString(); + return { + status: "COMPLETED", + files: [ + { + content: b64encode(file_contents), + tags: [], + }, + ], + }; +} + +main() + .then((value) => { + out = value; + }) + .catch((reason) => { + out = { + status: "FAILED", + files: [ + { + content: b64encode(reason), + tags: ["error/boefje"], + }, + ], + }; + }) + .finally(async () => { + console.log("FINISHING..."); + if (out == undefined) return; + + try { + console.log("SENDING OUT WITH:"); + console.log(JSON.stringify(out)); + console.log(output_url); + const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( + out, + ).replaceAll('"', '\\"')}`; + console.log(cmd); + try { + const x = execSync(cmd).toString(); + console.log(x); + console.log("FINISHED"); + } catch (error) { + console.error(error.status); // Might be 127 in your example. + console.error(error.message); // Holds the message you typically want. + console.error(error.stderr); // Holds the stderr output. Use `.toString()`. + console.error(error.stdout); // Holds the stdout output. Use `.toString()`. + } + } catch (error) { + console.error("SECOND FETCH WENT WRONG"); + console.error(error); + return; + } + }); diff --git a/boefjes/boefjes/plugins/kat_nikto/main.py b/boefjes/boefjes/plugins/kat_nikto/main.py deleted file mode 100644 index 971f9fddaf2..00000000000 --- a/boefjes/boefjes/plugins/kat_nikto/main.py +++ /dev/null @@ -1,24 +0,0 @@ -import json -import logging -import os - -from pydantic import BaseModel - - -class Vulnerability(BaseModel): - id: str - method: str - msg: str - - -def run(boefje_meta: dict): - file_path = os.path.join("./", "output.json") - if not os.path.isfile(file_path): - raise Exception("output.json file does not exist. Has the kat_nikto image given an error?") - - with open(file_path) as f: - json_data = json.loads(f.read())[0] - found_vulnerabilities = [Vulnerability.model_validate(x) for x in json_data["vulnerabilities"]] - logging.info(found_vulnerabilities) - - return [(set(), "a")] diff --git a/boefjes/boefjes/plugins/kat_nikto/package-lock.json b/boefjes/boefjes/plugins/kat_nikto/package-lock.json new file mode 100644 index 00000000000..5efc27623a6 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/package-lock.json @@ -0,0 +1,144 @@ +{ + "name": "kat-nikto", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "kat-nikto", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "node-fetch": "^3.3.2" + } + }, + "node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "paypal", + "url": "https://paypal.me/jimmywarting" + } + ], + "dependencies": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + }, + "engines": { + "node": "^12.20 || >= 14.13" + } + }, + "node_modules/formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "dependencies": { + "fetch-blob": "^3.1.2" + }, + "engines": { + "node": ">=12.20.0" + } + }, + "node_modules/node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/jimmywarting" + }, + { + "type": "github", + "url": "https://paypal.me/jimmywarting" + } + ], + "engines": { + "node": ">=10.5.0" + } + }, + "node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "node_modules/web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", + "engines": { + "node": ">= 8" + } + } + }, + "dependencies": { + "data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" + }, + "fetch-blob": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", + "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", + "requires": { + "node-domexception": "^1.0.0", + "web-streams-polyfill": "^3.0.3" + } + }, + "formdata-polyfill": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", + "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", + "requires": { + "fetch-blob": "^3.1.2" + } + }, + "node-domexception": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", + "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" + }, + "node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "requires": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + } + }, + "web-streams-polyfill": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" + } + } +} diff --git a/boefjes/boefjes/plugins/kat_nikto/package.json b/boefjes/boefjes/plugins/kat_nikto/package.json new file mode 100644 index 00000000000..a922f16073b --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/package.json @@ -0,0 +1,15 @@ +{ + "name": "kat-nikto", + "version": "1.0.0", + "description": "", + "type": "module", + "main": "index.js", + "scripts": { + "run": "node index.js" + }, + "author": "", + "license": "ISC", + "dependencies": { + "node-fetch": "^3.3.2" + } +} From 4d790c75427b45fd72900a4b410a4bb6d19f5ee0 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Tue, 13 Aug 2024 07:52:16 +0000 Subject: [PATCH 21/37] Added `oci_adapter.js` to better mirror the python's implementation --- boefjes/boefjes/plugins/kat_nikto/boefje.json | 3 +- boefjes/boefjes/plugins/kat_nikto/index.js | 118 --------------- boefjes/boefjes/plugins/kat_nikto/main.js | 43 ++++++ .../boefjes/plugins/kat_nikto/oci_adapter.js | 78 ++++++++++ .../plugins/kat_nikto/package-lock.json | 139 +++--------------- .../boefjes/plugins/kat_nikto/package.json | 11 +- 6 files changed, 145 insertions(+), 247 deletions(-) delete mode 100644 boefjes/boefjes/plugins/kat_nikto/index.js create mode 100644 boefjes/boefjes/plugins/kat_nikto/main.js create mode 100644 boefjes/boefjes/plugins/kat_nikto/oci_adapter.js diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.json b/boefjes/boefjes/plugins/kat_nikto/boefje.json index 12223e76d5c..f10f492bb60 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.json +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.json @@ -4,7 +4,8 @@ "description": "Uses Nikto", "consumes": [ "IPAddressV4", - "IPAddressV6" + "IPAddressV6", + "Hostname" ], "environment_keys": [], "scan_level": 3, diff --git a/boefjes/boefjes/plugins/kat_nikto/index.js b/boefjes/boefjes/plugins/kat_nikto/index.js deleted file mode 100644 index ba2dbcee8a3..00000000000 --- a/boefjes/boefjes/plugins/kat_nikto/index.js +++ /dev/null @@ -1,118 +0,0 @@ -import fs from "node:fs"; -import fetch from "node-fetch"; // npm install node-fetch -import { execSync } from "node:child_process"; - -// Getting information from INPUT_URL: http://boefje:8000/api/v0/tasks/6f08f386-0dfe-4cd4-a1b4-91e95411c883 -// Found boefje input with ooi: 46.23.85.171 -// - ***** TLS/SSL support not available (see docs for SSL install) ***** -// - Nikto v2.5.0 -// --------------------------------------------------------------------------- -// + Target IP: 46.23.85.171 -// + Target Hostname: 46.23.85.171 -// + Target Port: 80 -// + Start Time: 2024-08-05 09:55:56 (GMT0) -// --------------------------------------------------------------------------- -// + Server: nginx/1.18.0 (Ubuntu) -// + /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/ -// + No CGI Directories found (use '-C all' to force check all possible dirs) -// + nginx/1.18.0 appears to be outdated (current is at least 1.25.3). -// + 8108 requests: 0 error(s) and 2 item(s) reported on remote host -// + End Time: 2024-08-05 09:56:14 (GMT0) (18 seconds) -// --------------------------------------------------------------------------- -// + 1 host(s) tested -// Encoding: [{"host":"46.23.85.171","ip":"46.23.85.171","port":"80","banner":"","vulnerabilities":[{"id": "999103","references": "https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/","method":"GET","url":"/","msg":"The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type."},{"id": "600575","method":"HEAD","url":"/","msg":"nginx/1.18.0 appears to be outdated (current is at least 1.25.3)."}]}] -// FINISHING... -// SENDING OUT WITH: -// {"status":"COMPLETED","files":[{"content":"W3siaG9zdCI6IjQ2LjIzLjg1LjE3MSIsImlwIjoiNDYuMjMuODUuMTcxIiwicG9ydCI6IjgwIiwiYmFubmVyIjoiIiwidnVsbmVyYWJpbGl0aWVzIjpbeyJpZCI6ICI5OTkxMDMiLCJyZWZlcmVuY2VzIjogImh0dHBzOi8vd3d3Lm5ldHNwYXJrZXIuY29tL3dlYi12dWxuZXJhYmlsaXR5LXNjYW5uZXIvdnVsbmVyYWJpbGl0aWVzL21pc3NpbmctY29udGVudC10eXBlLWhlYWRlci8iLCJtZXRob2QiOiJHRVQiLCJ1cmwiOiIvIiwibXNnIjoiVGhlIFgtQ29udGVudC1UeXBlLU9wdGlvbnMgaGVhZGVyIGlzIG5vdCBzZXQuIFRoaXMgY291bGQgYWxsb3cgdGhlIHVzZXIgYWdlbnQgdG8gcmVuZGVyIHRoZSBjb250ZW50IG9mIHRoZSBzaXRlIGluIGEgZGlmZmVyZW50IGZhc2hpb24gdG8gdGhlIE1JTUUgdHlwZS4ifSx7ImlkIjogIjYwMDU3NSIsIm1ldGhvZCI6IkhFQUQiLCJ1cmwiOiIvIiwibXNnIjoibmdpbngvMS4xOC4wIGFwcGVhcnMgdG8gYmUgb3V0ZGF0ZWQgKGN1cnJlbnQgaXMgYXQgbGVhc3QgMS4yNS4zKS4ifV19XQ==","tags":[]}]} -// % Total % Received % Xferd Average Speed Time Time Time Current -// Dload Upload Total Spent Left Speed - -// 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0 -// 100 903 100 158 100 745 8777 41388 --:--:-- --:--:-- --:--:-- 53117 -// {"detail":[{"type":"json_invalid","loc":["body",1],"msg":"JSON decode error","input":{},"ctx":{"error":"Expecting property name enclosed in double quotes"}}]} -// FINISHED - -function b64encode(inp) { - console.log(`Encoding: ${inp}`); - return Buffer.from(inp).toString("base64"); -} - -let out; -let output_url; - -async function main() { - const input_url = process.argv[process.argv.length - 1]; - console.log(`Getting information from INPUT_URL: ${input_url}`); - try { - var boefje_input = JSON.parse( - execSync(`curl --request GET --url ${input_url} -s`).toString(), - ); - } catch (error) { - console.error("FIRST FETCH WENT WRONG"); - console.error(error); - return; - } - - output_url = boefje_input.output_url; - const ooi = boefje_input.boefje_meta.arguments.input.address; - console.log(`Found boefje input with ooi: ${ooi}`); - - execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { - stdio: "inherit", - }); - - const file_contents = fs.readFileSync("./output.json").toString(); - return { - status: "COMPLETED", - files: [ - { - content: b64encode(file_contents), - tags: [], - }, - ], - }; -} - -main() - .then((value) => { - out = value; - }) - .catch((reason) => { - out = { - status: "FAILED", - files: [ - { - content: b64encode(reason), - tags: ["error/boefje"], - }, - ], - }; - }) - .finally(async () => { - console.log("FINISHING..."); - if (out == undefined) return; - - try { - console.log("SENDING OUT WITH:"); - console.log(JSON.stringify(out)); - console.log(output_url); - const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( - out, - ).replaceAll('"', '\\"')}`; - console.log(cmd); - try { - const x = execSync(cmd).toString(); - console.log(x); - console.log("FINISHED"); - } catch (error) { - console.error(error.status); // Might be 127 in your example. - console.error(error.message); // Holds the message you typically want. - console.error(error.stderr); // Holds the stderr output. Use `.toString()`. - console.error(error.stdout); // Holds the stdout output. Use `.toString()`. - } - } catch (error) { - console.error("SECOND FETCH WENT WRONG"); - console.error(error); - return; - } - }); diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js new file mode 100644 index 00000000000..729d4798914 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -0,0 +1,43 @@ +import fs from "node:fs"; +import { execSync } from "node:child_process"; + +/** + * @param {{}} boefje_meta The string input to base64 encode + * @returns {(string | string[])[][]} + */ +export default function (boefje_meta) { + // Depending on what OOI triggered this task, the hostname / address will be in a different location + const object_type = boefje_meta.arguments.input.object_type; + let ooi = ""; + if (["IPAddressV4", "IPAddressV6"].includes(object_type)) + ooi = boefje_meta.arguments.input.address; + else if (object_type == "Hostname") ooi = boefje_meta.arguments.input.name; + else throw new Error("Unexpected boefje_meta"); + + console.log(`Found boefje input with ooi: ${ooi}`); + + // Running nikto and outputting to a file + try { + execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { + stdio: "inherit", + }); + } catch (e) { + console.error(e); + throw new Error( + "Something went wrong running the nikto command.\n" + e.message, + ); + } + + // Reading the file created by nikto + try { + var file_contents = fs.readFileSync("./output.json").toString(); + } catch (e) { + console.error(e); + throw new Error( + "Something went wrong reading the file from the nikto command.\n" + + e.message, + ); + } + console.log("File contents: " + file_contents); + return [[[], file_contents]]; +} diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js new file mode 100644 index 00000000000..a578bf88b3e --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -0,0 +1,78 @@ +import { execSync } from "node:child_process"; +import run from "./main.js"; + +/** + * @param {string} inp The string input to base64 encode + */ +function b64encode(inp) { + console.log(`Encoding: ${inp}`); + return Buffer.from(inp).toString("base64"); +} + +let out; +let output_url; + +async function main() { + const input_url = process.argv[process.argv.length - 1]; + + // Getting the boefje input + try { + var boefje_input = JSON.parse( + execSync(`curl --request GET --url ${input_url} -s`).toString(), + ); + } catch (error) { + console.error(`Getting boefje input went wrong with URL: ${input_url}`); + throw new Error(error); + } + + output_url = boefje_input.output_url; + const raws = run(boefje_input.boefje_meta); + console.log("RAWS: " + JSON.stringify(raws)); + return { + status: "COMPLETED", + files: raws.map((x) => { + return { + content: b64encode(x[1]), + tags: x[0], + }; + }), + }; +} + +main() + .then((value) => { + out = value; + }) + .catch((reason) => { + out = { + status: "FAILED", + files: [ + { + content: b64encode("main caught an error: " + reason), + tags: ["error/boefje"], + }, + ], + }; + }) + .finally(async () => { + console.log("Finishing with: " + out); + if (out == undefined) return console.error("Somehow `out` was not set."); + + try { + console.log("SENDING OUT WITH: " + JSON.stringify(out)); + const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( + out, + ).replaceAll('"', '\\"')}`; + console.log(cmd); + try { + execSync(cmd).toString(); + console.log("FINISHED"); + } catch (error) { + console.error( + "Something went wrong outputting to the boefje api: " + error.message, + ); + } + } catch (error) { + console.error("SECOND FETCH WENT WRONG: " + error); + } + }); diff --git a/boefjes/boefjes/plugins/kat_nikto/package-lock.json b/boefjes/boefjes/plugins/kat_nikto/package-lock.json index 5efc27623a6..daa0ba14207 100644 --- a/boefjes/boefjes/plugins/kat_nikto/package-lock.json +++ b/boefjes/boefjes/plugins/kat_nikto/package-lock.json @@ -7,138 +7,37 @@ "": { "name": "kat-nikto", "version": "1.0.0", - "license": "ISC", "dependencies": { - "node-fetch": "^3.3.2" + "@types/node": "^22.1.0" } }, - "node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", - "engines": { - "node": ">= 12" - } - }, - "node_modules/fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "paypal", - "url": "https://paypal.me/jimmywarting" - } - ], - "dependencies": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - }, - "engines": { - "node": "^12.20 || >= 14.13" - } - }, - "node_modules/formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "dependencies": { - "fetch-blob": "^3.1.2" - }, - "engines": { - "node": ">=12.20.0" - } - }, - "node_modules/node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/jimmywarting" - }, - { - "type": "github", - "url": "https://paypal.me/jimmywarting" - } - ], - "engines": { - "node": ">=10.5.0" - } - }, - "node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "node_modules/@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "undici-types": "~6.13.0" } }, - "node_modules/web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", - "engines": { - "node": ">= 8" - } + "node_modules/undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" } }, "dependencies": { - "data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==" - }, - "fetch-blob": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz", - "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==", - "requires": { - "node-domexception": "^1.0.0", - "web-streams-polyfill": "^3.0.3" - } - }, - "formdata-polyfill": { - "version": "4.0.10", - "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz", - "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==", - "requires": { - "fetch-blob": "^3.1.2" - } - }, - "node-domexception": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", - "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==" - }, - "node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "@types/node": { + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.1.0.tgz", + "integrity": "sha512-AOmuRF0R2/5j1knA3c6G3HOk523Ga+l+ZXltX8SF1+5oqcXijjfTd8fY3XRZqSihEu9XhtQnKYLmkFaoxgsJHw==", "requires": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "undici-types": "~6.13.0" } }, - "web-streams-polyfill": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", - "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==" + "undici-types": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.13.0.tgz", + "integrity": "sha512-xtFJHudx8S2DSoujjMd1WeWvn7KKWFRESZTMeL1RptAYERu29D6jphMjjY+vn96jvN3kVPDNxU/E13VTaXj6jg==" } } } diff --git a/boefjes/boefjes/plugins/kat_nikto/package.json b/boefjes/boefjes/plugins/kat_nikto/package.json index a922f16073b..890572426c1 100644 --- a/boefjes/boefjes/plugins/kat_nikto/package.json +++ b/boefjes/boefjes/plugins/kat_nikto/package.json @@ -1,15 +1,10 @@ { "name": "kat-nikto", "version": "1.0.0", - "description": "", "type": "module", - "main": "index.js", - "scripts": { - "run": "node index.js" - }, - "author": "", - "license": "ISC", + "main": "oci_adapter.js", + "author": "cynalytics", "dependencies": { - "node-fetch": "^3.3.2" + "@types/node": "^22.1.0" } } From d4f92b7a7919a14933053b952bbfa177fc0f45f5 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Thu, 22 Aug 2024 09:26:33 +0000 Subject: [PATCH 22/37] Cleaned up code --- boefjes/boefjes/plugins/kat_nikto/oci_adapter.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index a578bf88b3e..d1cd586f164 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -2,7 +2,8 @@ import { execSync } from "node:child_process"; import run from "./main.js"; /** - * @param {string} inp The string input to base64 encode + * @param {string} inp The string input to base64 + * @returns {string} */ function b64encode(inp) { console.log(`Encoding: ${inp}`); @@ -30,12 +31,10 @@ async function main() { console.log("RAWS: " + JSON.stringify(raws)); return { status: "COMPLETED", - files: raws.map((x) => { - return { - content: b64encode(x[1]), - tags: x[0], - }; - }), + files: raws.map((x) => ({ + content: b64encode(x[1]), + tags: x[0], + })), }; } @@ -56,7 +55,7 @@ main() }) .finally(async () => { console.log("Finishing with: " + out); - if (out == undefined) return console.error("Somehow `out` was not set."); + if (out == undefined) return console.error("`out` is undefined."); try { console.log("SENDING OUT WITH: " + JSON.stringify(out)); From 6d39582fae569777c145128c1a40c0faa776aa5c Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Thu, 22 Aug 2024 11:57:09 +0000 Subject: [PATCH 23/37] Added normalizer to kat_nikto boefje --- .../boefjes/plugins/kat_nikto/normalize.py | 28 +++++++++++++++++++ .../boefjes/plugins/kat_nikto/normalizer.json | 10 +++++++ 2 files changed, 38 insertions(+) create mode 100644 boefjes/boefjes/plugins/kat_nikto/normalize.py create mode 100644 boefjes/boefjes/plugins/kat_nikto/normalizer.json diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py new file mode 100644 index 00000000000..f16c571c895 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -0,0 +1,28 @@ +import json +import logging +from collections.abc import Iterable + +from boefjes.job_models import NormalizerOutput +from octopoes.models import Reference +from octopoes.models.ooi.software import Software, SoftwareInstance + + +def scan_outdated_software(data: dict, ooi_ref): + for scan in data: + for vulnerability in scan["vulnerabilities"]: + # If the scanned vulnerability has to do with outdated software + if vulnerability["id"].startswith("6"): + software_name, found_version = vulnerability["msg"].split()[0].split("/") + + software = Software(name=software_name, version=found_version) + yield software + yield SoftwareInstance(ooi=ooi_ref, software=software.reference) + + +def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: + logging.info(input_ooi) + data = json.loads(raw) + + ooi_ref = Reference.from_str(input_ooi["primary_key"]) + + yield from scan_outdated_software(data, ooi_ref) diff --git a/boefjes/boefjes/plugins/kat_nikto/normalizer.json b/boefjes/boefjes/plugins/kat_nikto/normalizer.json new file mode 100644 index 00000000000..7e9e2f5ae09 --- /dev/null +++ b/boefjes/boefjes/plugins/kat_nikto/normalizer.json @@ -0,0 +1,10 @@ +{ + "id": "kat_nikto_normalize", + "consumes": [ + "boefje/nikto" + ], + "produces": [ + "Software", + "SoftwareInstance" + ] +} From 723fd55e0f5a0e298d7c8b7c1a4ceb4570ba8652 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 09:38:32 +0000 Subject: [PATCH 24/37] Added new OOI that has information about outdated software --- boefjes/boefjes/plugins/kat_nikto/normalize.py | 17 +++++++++++++++-- octopoes/octopoes/models/ooi/software.py | 16 ++++++++++++++++ octopoes/octopoes/models/types.py | 4 ++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py index f16c571c895..49a06eb7d7d 100644 --- a/boefjes/boefjes/plugins/kat_nikto/normalize.py +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -1,10 +1,11 @@ import json import logging +import re from collections.abc import Iterable from boefjes.job_models import NormalizerOutput from octopoes.models import Reference -from octopoes.models.ooi.software import Software, SoftwareInstance +from octopoes.models.ooi.software import OutdatedSoftwareInstance, Software, SoftwareInstance def scan_outdated_software(data: dict, ooi_ref): @@ -14,9 +15,21 @@ def scan_outdated_software(data: dict, ooi_ref): if vulnerability["id"].startswith("6"): software_name, found_version = vulnerability["msg"].split()[0].split("/") + # REGEX: get the text between "least " and ")" to get the latest version + match = re.search(r"least (.*)\)", vulnerability["msg"]) + if match is None: + logging.error("No version number found on supposedly outdated software") + continue + newest_version = match.group(1) software = Software(name=software_name, version=found_version) + software_instance = SoftwareInstance(ooi=ooi_ref, software=software.reference) yield software - yield SoftwareInstance(ooi=ooi_ref, software=software.reference) + yield software_instance + yield OutdatedSoftwareInstance( + ooi=ooi_ref, + software_instance=software_instance.reference, + newest_version=newest_version, + ) def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: diff --git a/octopoes/octopoes/models/ooi/software.py b/octopoes/octopoes/models/ooi/software.py index 91a7fbddf47..cfc0357e2e7 100644 --- a/octopoes/octopoes/models/ooi/software.py +++ b/octopoes/octopoes/models/ooi/software.py @@ -43,3 +43,19 @@ def format_reference_human_readable(cls, reference: Reference) -> str: ooi_reference = Reference.from_str("|".join(parts[0:-4])) software_reference = Reference.from_str("|".join(parts[-4:])) return f"{software_reference.human_readable} @ {ooi_reference.human_readable}" + + +class OutdatedSoftwareInstance(OOI): + object_type: Literal["OutdatedSoftwareInstance"] = "OutdatedSoftwareInstance" + + _natural_key_attrs = ["ooi", "software", "newest_version"] + + ooi: Reference = ReferenceField(OOI, max_issue_scan_level=0, max_inherit_scan_level=1) + software_instance: Reference = ReferenceField(SoftwareInstance, max_issue_scan_level=1, max_inherit_scan_level=0) + newest_version: str | None = None + + @classmethod + def format_reference_human_readable(cls, reference: Reference) -> str: + return reference.human_readable + + # TODO: create `format_reference_human_readable` to include `newest_version` diff --git a/octopoes/octopoes/models/types.py b/octopoes/octopoes/models/types.py index 2bc1acc9af9..91d49d99df4 100644 --- a/octopoes/octopoes/models/types.py +++ b/octopoes/octopoes/models/types.py @@ -62,7 +62,7 @@ from octopoes.models.ooi.reports import Report, ReportData from octopoes.models.ooi.scans import ExternalScan from octopoes.models.ooi.service import IPService, Service, TLSCipher -from octopoes.models.ooi.software import Software, SoftwareInstance +from octopoes.models.ooi.software import OutdatedSoftwareInstance, Software, SoftwareInstance from octopoes.models.ooi.web import ( RESTAPI, URL, @@ -109,7 +109,7 @@ ConcreteNetworkType = Network | IPAddressV4 | IPAddressV6 | AutonomousSystem | IPV4NetBlock | IPV6NetBlock | IPPort NetworkType = ConcreteNetworkType | IPAddress ServiceType = Service | IPService | TLSCipher -SoftwareType = Software | SoftwareInstance +SoftwareType = Software | SoftwareInstance | OutdatedSoftwareInstance WebType = ( Website | URL From 13ca4de73fd4577e40807a2e4c44763808215634 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 11:17:30 +0000 Subject: [PATCH 25/37] Rewrote `oci_adapter.js` to work like `oci_adapter.py` does --- .../boefjes/plugins/kat_nikto/oci_adapter.js | 74 ++++++++----------- 1 file changed, 30 insertions(+), 44 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index d1cd586f164..18c7d8fb73f 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -10,10 +10,7 @@ function b64encode(inp) { return Buffer.from(inp).toString("base64"); } -let out; -let output_url; - -async function main() { +function main() { const input_url = process.argv[process.argv.length - 1]; // Getting the boefje input @@ -26,52 +23,41 @@ async function main() { throw new Error(error); } - output_url = boefje_input.output_url; - const raws = run(boefje_input.boefje_meta); - console.log("RAWS: " + JSON.stringify(raws)); - return { - status: "COMPLETED", - files: raws.map((x) => ({ - content: b64encode(x[1]), - tags: x[0], - })), - }; -} - -main() - .then((value) => { - out = value; - }) - .catch((reason) => { + let out = undefined; + let output_url = boefje_input.output_url; + try { + // Getting the raw files + const raws = run(boefje_input.boefje_meta); + out = { + status: "COMPLETED", + files: raws.map((x) => ({ + content: b64encode(x[1]), + tags: x[0], + })), + }; + } catch (error) { out = { status: "FAILED", files: [ { - content: b64encode("main caught an error: " + reason), + content: b64encode("Boefje caught an error: " + error.message), tags: ["error/boefje"], }, ], }; - }) - .finally(async () => { - console.log("Finishing with: " + out); - if (out == undefined) return console.error("`out` is undefined."); + } + + // Example command + /* + curl --request POST \ + --url http://boefje/api/v0/tasks/7342e8dd-b945-4185-aaec-787205b7b664 \ + --header 'Content-Type: application/json' \ + --data '{"status":"COMPLETED","files":[{"content":"BASE_64_ENCODED_CONTENT","tags":[]}]}' + */ + const out_json = JSON.stringify(out); + const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data '${out_json}'`; + + execSync(cmd); +} - try { - console.log("SENDING OUT WITH: " + JSON.stringify(out)); - const cmd = `curl --request POST --url ${output_url} --header "Content-Type: application/json" --data ${JSON.stringify( - out, - ).replaceAll('"', '\\"')}`; - console.log(cmd); - try { - execSync(cmd).toString(); - console.log("FINISHED"); - } catch (error) { - console.error( - "Something went wrong outputting to the boefje api: " + error.message, - ); - } - } catch (error) { - console.error("SECOND FETCH WENT WRONG: " + error); - } - }); +main(); From cb8d13627b0c2cfd210a5bac4a648178a7cf36e7 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 11:31:28 +0000 Subject: [PATCH 26/37] Fixed example url --- boefjes/boefjes/plugins/kat_nikto/oci_adapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index 18c7d8fb73f..2ab82c478f1 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -50,7 +50,7 @@ function main() { // Example command /* curl --request POST \ - --url http://boefje/api/v0/tasks/7342e8dd-b945-4185-aaec-787205b7b664 \ + --url http://boefje:8000/api/v0/tasks/7342e8dd-b945-4185-aaec-787205b7b664 \ --header 'Content-Type: application/json' \ --data '{"status":"COMPLETED","files":[{"content":"BASE_64_ENCODED_CONTENT","tags":[]}]}' */ From 2d96eff610f3bae402aeffc32858fc2a8a8ac918 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 23 Aug 2024 13:48:00 +0000 Subject: [PATCH 27/37] cleaned up dockerfiles to remove comments --- boefjes/boefjes/plugins/kat_nikto/.dockerignore | 1 - boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile | 1 - 2 files changed, 2 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/.dockerignore b/boefjes/boefjes/plugins/kat_nikto/.dockerignore index 476b7d85f6a..e0da5c735a0 100644 --- a/boefjes/boefjes/plugins/kat_nikto/.dockerignore +++ b/boefjes/boefjes/plugins/kat_nikto/.dockerignore @@ -1,4 +1,3 @@ .git *Dockerfile* *docker-compose* -node_modules diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile index ed9308c735e..feac3fd7a6b 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -13,4 +13,3 @@ COPY $BOEFJE_PATH ./ RUN npm ci ENTRYPOINT [ "node", "./" ] -# node ./ "http://localhost:8006/api/v0/tasks/ff208697-c332-4b04-919d-755b014e881d" From b050735d85c9aa0cb933e7385997779b2174c587 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Tue, 27 Aug 2024 10:20:27 +0000 Subject: [PATCH 28/37] Removed new OOI type and sent the nikto message straight to the finding --- .../boefjes/plugins/kat_nikto/normalize.py | 23 +++++++++---------- octopoes/octopoes/models/ooi/software.py | 16 ------------- 2 files changed, 11 insertions(+), 28 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py index 49a06eb7d7d..5bc3eb95420 100644 --- a/boefjes/boefjes/plugins/kat_nikto/normalize.py +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -1,11 +1,11 @@ import json import logging -import re from collections.abc import Iterable from boefjes.job_models import NormalizerOutput from octopoes.models import Reference -from octopoes.models.ooi.software import OutdatedSoftwareInstance, Software, SoftwareInstance +from octopoes.models.ooi.findings import Finding, KATFindingType +from octopoes.models.ooi.software import Software, SoftwareInstance def scan_outdated_software(data: dict, ooi_ref): @@ -13,22 +13,21 @@ def scan_outdated_software(data: dict, ooi_ref): for vulnerability in scan["vulnerabilities"]: # If the scanned vulnerability has to do with outdated software if vulnerability["id"].startswith("6"): + # Example of `vulnerability["msg"]` + # @SOFTWARE/@RUNNING_VER appears to be outdated (current is at least @CURRENT_VER) software_name, found_version = vulnerability["msg"].split()[0].split("/") - # REGEX: get the text between "least " and ")" to get the latest version - match = re.search(r"least (.*)\)", vulnerability["msg"]) - if match is None: - logging.error("No version number found on supposedly outdated software") - continue - newest_version = match.group(1) software = Software(name=software_name, version=found_version) software_instance = SoftwareInstance(ooi=ooi_ref, software=software.reference) yield software yield software_instance - yield OutdatedSoftwareInstance( - ooi=ooi_ref, - software_instance=software_instance.reference, - newest_version=newest_version, + + finding_type = KATFindingType(id="KAT-VERIFIED-VULNERABILITY") + yield finding_type + yield Finding( + finding_type=finding_type.reference, + ooi=software_instance.reference, + description=vulnerability["msg"], ) diff --git a/octopoes/octopoes/models/ooi/software.py b/octopoes/octopoes/models/ooi/software.py index cfc0357e2e7..91a7fbddf47 100644 --- a/octopoes/octopoes/models/ooi/software.py +++ b/octopoes/octopoes/models/ooi/software.py @@ -43,19 +43,3 @@ def format_reference_human_readable(cls, reference: Reference) -> str: ooi_reference = Reference.from_str("|".join(parts[0:-4])) software_reference = Reference.from_str("|".join(parts[-4:])) return f"{software_reference.human_readable} @ {ooi_reference.human_readable}" - - -class OutdatedSoftwareInstance(OOI): - object_type: Literal["OutdatedSoftwareInstance"] = "OutdatedSoftwareInstance" - - _natural_key_attrs = ["ooi", "software", "newest_version"] - - ooi: Reference = ReferenceField(OOI, max_issue_scan_level=0, max_inherit_scan_level=1) - software_instance: Reference = ReferenceField(SoftwareInstance, max_issue_scan_level=1, max_inherit_scan_level=0) - newest_version: str | None = None - - @classmethod - def format_reference_human_readable(cls, reference: Reference) -> str: - return reference.human_readable - - # TODO: create `format_reference_human_readable` to include `newest_version` From 9954e6284a74bc4aaff917506011b5ced96dbcbf Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Tue, 27 Aug 2024 11:24:29 +0000 Subject: [PATCH 29/37] Removed unused variable --- octopoes/octopoes/models/types.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/octopoes/octopoes/models/types.py b/octopoes/octopoes/models/types.py index 91d49d99df4..2bc1acc9af9 100644 --- a/octopoes/octopoes/models/types.py +++ b/octopoes/octopoes/models/types.py @@ -62,7 +62,7 @@ from octopoes.models.ooi.reports import Report, ReportData from octopoes.models.ooi.scans import ExternalScan from octopoes.models.ooi.service import IPService, Service, TLSCipher -from octopoes.models.ooi.software import OutdatedSoftwareInstance, Software, SoftwareInstance +from octopoes.models.ooi.software import Software, SoftwareInstance from octopoes.models.ooi.web import ( RESTAPI, URL, @@ -109,7 +109,7 @@ ConcreteNetworkType = Network | IPAddressV4 | IPAddressV6 | AutonomousSystem | IPV4NetBlock | IPV6NetBlock | IPPort NetworkType = ConcreteNetworkType | IPAddress ServiceType = Service | IPService | TLSCipher -SoftwareType = Software | SoftwareInstance | OutdatedSoftwareInstance +SoftwareType = Software | SoftwareInstance WebType = ( Website | URL From 0ace647633fffbcf5f763e82d9281202a956c62c Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Tue, 27 Aug 2024 13:22:29 +0000 Subject: [PATCH 30/37] Added new finding type and use this one instead for nikto boefje --- .../kat_finding_types.json | 6 ++++++ boefjes/boefjes/plugins/kat_nikto/main.js | 18 ++++++++++++++++-- boefjes/boefjes/plugins/kat_nikto/normalize.py | 2 +- .../boefjes/plugins/kat_nikto/normalizer.json | 2 +- 4 files changed, 24 insertions(+), 4 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json index 31ff5bed15b..35773f19567 100644 --- a/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json +++ b/boefjes/boefjes/plugins/kat_kat_finding_types/kat_finding_types.json @@ -486,5 +486,11 @@ "source": "https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers", "impact": "Nonstandard headers may not be supported by all browsers and may not provide the security that is expected.", "recommendation": "Remove the nonstandard headers from the response." + }, + "KAT-OUTDATED-SOFTWARE": { + "description": "A newer version of existing software has been found.", + "risk": "recommendation", + "impact": "Depending on what software is outdated this can be critical.", + "recommendation": "Inspect the software version, determine if additional measures need to be taken and install updates to reduce the attack surface." } } diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js index 729d4798914..f714aaf4acd 100644 --- a/boefjes/boefjes/plugins/kat_nikto/main.js +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -28,16 +28,30 @@ export default function (boefje_meta) { ); } + const raws = []; + // Reading the file created by nikto try { var file_contents = fs.readFileSync("./output.json").toString(); + raws.push([["boefje/nikto-output"], file_contents]); } catch (e) { - console.error(e); + console.error(e.message); throw new Error( "Something went wrong reading the file from the nikto command.\n" + e.message, ); } + + // Looking if outdated software has been found + try { + const data = JSON.parse(file_contents); + for (const vulnerability of data["vulnerabilities"]) + if (vulnerability["id"].startsWith("6")) + raws.push([["openkat/finding"], "KAT-OUTDATED-SOFTWARE"]); + } catch (e) { + console.error(e.message); + } + console.log("File contents: " + file_contents); - return [[[], file_contents]]; + return raws; } diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py index 5bc3eb95420..7e9a3e9f82f 100644 --- a/boefjes/boefjes/plugins/kat_nikto/normalize.py +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -22,7 +22,7 @@ def scan_outdated_software(data: dict, ooi_ref): yield software yield software_instance - finding_type = KATFindingType(id="KAT-VERIFIED-VULNERABILITY") + finding_type = KATFindingType(id="KAT-OUTDATED-SOFTWARE") yield finding_type yield Finding( finding_type=finding_type.reference, diff --git a/boefjes/boefjes/plugins/kat_nikto/normalizer.json b/boefjes/boefjes/plugins/kat_nikto/normalizer.json index 7e9e2f5ae09..d6e8ca4fe87 100644 --- a/boefjes/boefjes/plugins/kat_nikto/normalizer.json +++ b/boefjes/boefjes/plugins/kat_nikto/normalizer.json @@ -1,7 +1,7 @@ { "id": "kat_nikto_normalize", "consumes": [ - "boefje/nikto" + "boefje/nikto-output" ], "produces": [ "Software", From 491247da4d3a0f20d2de0ad14f7dec85cfee2d99 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 28 Aug 2024 08:30:02 +0000 Subject: [PATCH 31/37] Fixed merging mistake --- .../plugins/kat_cve_normalizer/__init__.py | 0 .../plugins/kat_cve_normalizer/normalize.py | 38 ------------------- .../kat_cve_normalizer/normalizer.json | 10 ----- 3 files changed, 48 deletions(-) delete mode 100644 boefjes/boefjes/plugins/kat_cve_normalizer/__init__.py delete mode 100644 boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py delete mode 100644 boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/__init__.py b/boefjes/boefjes/plugins/kat_cve_normalizer/__init__.py deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py b/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py deleted file mode 100644 index 0cc68c03f71..00000000000 --- a/boefjes/boefjes/plugins/kat_cve_normalizer/normalize.py +++ /dev/null @@ -1,38 +0,0 @@ -import re -from collections.abc import Iterable - -from boefjes.job_models import NormalizerOutput -from octopoes.models import Reference -from octopoes.models.ooi.findings import CVEFindingType, Finding, KATFindingType, RetireJSFindingType, SnykFindingType - -CVE_PATTERN = re.compile(r"CVE-\d{4}-\d{4,7}") - - -def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: - ooi = Reference.from_str(input_ooi["primary_key"]) - finding_ids_str = raw.decode() - finding_ids_list = [fid.strip().upper() for fid in finding_ids_str.split(",")] - - finding_type_mapping = { - "CVE": CVEFindingType, - "KAT": KATFindingType, - "SNYK": SnykFindingType, - "RETIREJS": RetireJSFindingType, - } - - for finding_id in finding_ids_list: - parts = finding_id.split("-") - prefix = parts[0] - - if prefix in finding_type_mapping: - if prefix == "CVE" and not CVE_PATTERN.match(finding_id): - continue # skip incorrect cves - - finding_type = finding_type_mapping[prefix](id=finding_id) - finding = Finding( - finding_type=finding_type.reference, - ooi=ooi, - description=f"{finding_id} is found on this OOI", - ) - yield finding_type - yield finding diff --git a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json b/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json deleted file mode 100644 index ec7e54b209c..00000000000 --- a/boefjes/boefjes/plugins/kat_cve_normalizer/normalizer.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "id": "kat_generic_finding_normalize", - "consumes": [ - "openkat/finding" - ], - "produces": [ - "Finding", - "CVEFindingType" - ] -} From ef25331df433f2a1d6ddaba5769b5122e1c4d56f Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 28 Aug 2024 08:45:50 +0000 Subject: [PATCH 32/37] =?UTF-8?q?Updated=20dev's=20cat'=20=F0=9F=98=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- boefjes/boefjes/plugins/kat_nikto/cover.jpg | Bin 62267 -> 49649 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/cover.jpg b/boefjes/boefjes/plugins/kat_nikto/cover.jpg index d509564388d68d3189bab55cc28aa5073cc53248..02d906baa8329b40800bb10685c94e11eee14eb4 100644 GIT binary patch literal 49649 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 Date: Wed, 28 Aug 2024 09:53:49 +0000 Subject: [PATCH 33/37] Added tests for nikto normalizer --- .../tests/examples/raw/nikto-example.com.json | 23 +++++++++++ .../examples/raw/nikto-non-existing.com.json | 16 ++++++++ boefjes/tests/test_nikto_normalizer.py | 41 +++++++++++++++++++ 3 files changed, 80 insertions(+) create mode 100644 boefjes/tests/examples/raw/nikto-example.com.json create mode 100644 boefjes/tests/examples/raw/nikto-non-existing.com.json create mode 100644 boefjes/tests/test_nikto_normalizer.py diff --git a/boefjes/tests/examples/raw/nikto-example.com.json b/boefjes/tests/examples/raw/nikto-example.com.json new file mode 100644 index 00000000000..264320b0cb8 --- /dev/null +++ b/boefjes/tests/examples/raw/nikto-example.com.json @@ -0,0 +1,23 @@ +[ + { + "host": "example.com", + "ip": "178.128.108.228", + "port": "80", + "banner": "", + "vulnerabilities": [ + { + "id": "600575", + "method": "HEAD", + "url": "/", + "msg": "nginx/1.18.0 appears to be outdated (current is at least 1.25.3)." + }, + { + "id": "999103", + "references": "https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/", + "method": "GET", + "url": "/", + "msg": "The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type." + } + ] + } +] diff --git a/boefjes/tests/examples/raw/nikto-non-existing.com.json b/boefjes/tests/examples/raw/nikto-non-existing.com.json new file mode 100644 index 00000000000..ce45231ff33 --- /dev/null +++ b/boefjes/tests/examples/raw/nikto-non-existing.com.json @@ -0,0 +1,16 @@ +[ + { + "host": "non-existing.com", + "ip": "2.1.3.5", + "port": "6667", + "banner": "", + "vulnerabilities": [ + { + "id": "0", + "method": "GET", + "url": "/", + "msg": "Unable to connect to non-existing.com." + } + ] + } +] diff --git a/boefjes/tests/test_nikto_normalizer.py b/boefjes/tests/test_nikto_normalizer.py new file mode 100644 index 00000000000..e2a3fa1ce11 --- /dev/null +++ b/boefjes/tests/test_nikto_normalizer.py @@ -0,0 +1,41 @@ +from unittest import TestCase + +from boefjes.plugins.kat_nikto.normalize import run +from octopoes.models import Reference +from octopoes.models.ooi.findings import KATFindingType +from octopoes.models.ooi.software import Software, SoftwareInstance +from octopoes.models.types import Finding +from tests.loading import get_dummy_data + + +class CVETest(TestCase): + def test_outdated_found(self): + input_ooi = {"primary_key": "Hostname|internet|example.com"} + ooi_ref = Reference.from_str(input_ooi["primary_key"]) + + oois = list(run(input_ooi, get_dummy_data("raw/nikto-example.com.json"))) + + software = Software(name="nginx", version="1.18.0") + finding_type = KATFindingType(id="KAT-OUTDATED-SOFTWARE") + software_instance = SoftwareInstance(ooi=ooi_ref, software=software.reference) + finding = Finding( + finding_type=finding_type.reference, + ooi=software_instance.reference, + description="nginx/1.18.0 appears to be outdated (current is at least 1.25.3).", + ) + + expected = [ + software, + software_instance, + finding_type, + finding, + ] + + self.assertEqual(expected, oois) + + def test_nothing_found(self): + input_ooi = {"primary_key": "Hostname|internet|non-existing.com"} + + oois = list(run(input_ooi, get_dummy_data("raw/nikto-non-existing.com.json"))) + + self.assertEqual([], oois) From c6647da60354fe61d29bc528d6d98989076b9394 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 28 Aug 2024 10:07:59 +0000 Subject: [PATCH 34/37] Refactored code --- boefjes/boefjes/plugins/kat_nikto/.dockerignore | 3 --- boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile | 1 - boefjes/boefjes/plugins/kat_nikto/description.md | 10 +--------- boefjes/boefjes/plugins/kat_nikto/main.js | 3 --- boefjes/boefjes/plugins/kat_nikto/normalize.py | 4 +--- boefjes/boefjes/plugins/kat_nikto/oci_adapter.js | 3 +-- 6 files changed, 3 insertions(+), 21 deletions(-) delete mode 100644 boefjes/boefjes/plugins/kat_nikto/.dockerignore diff --git a/boefjes/boefjes/plugins/kat_nikto/.dockerignore b/boefjes/boefjes/plugins/kat_nikto/.dockerignore deleted file mode 100644 index e0da5c735a0..00000000000 --- a/boefjes/boefjes/plugins/kat_nikto/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -.git -*Dockerfile* -*docker-compose* diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile index feac3fd7a6b..f852b54f71a 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -4,7 +4,6 @@ WORKDIR /app RUN apt update RUN apt install -y git - RUN git clone https://github.com/sullo/nikto ARG BOEFJE_PATH=./boefjes/plugins/kat_nikto diff --git a/boefjes/boefjes/plugins/kat_nikto/description.md b/boefjes/boefjes/plugins/kat_nikto/description.md index 30000258ee6..e2e1d3c27e0 100644 --- a/boefjes/boefjes/plugins/kat_nikto/description.md +++ b/boefjes/boefjes/plugins/kat_nikto/description.md @@ -10,14 +10,6 @@ Nikto expects an IpAddress or a Hostname OOI. ### Output OOIs -Nikto outputs the following OOIs: - -| OOI type | Description | -| -------- | ----------- | -| | | -| | | -| | | -| | | -| | | +Nikto outputs the following the found outdated software and a finding explaining that the software is outdated. **Cat name**: Kitty diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js index f714aaf4acd..9916ef54246 100644 --- a/boefjes/boefjes/plugins/kat_nikto/main.js +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -14,8 +14,6 @@ export default function (boefje_meta) { else if (object_type == "Hostname") ooi = boefje_meta.arguments.input.name; else throw new Error("Unexpected boefje_meta"); - console.log(`Found boefje input with ooi: ${ooi}`); - // Running nikto and outputting to a file try { execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { @@ -52,6 +50,5 @@ export default function (boefje_meta) { console.error(e.message); } - console.log("File contents: " + file_contents); return raws; } diff --git a/boefjes/boefjes/plugins/kat_nikto/normalize.py b/boefjes/boefjes/plugins/kat_nikto/normalize.py index 7e9a3e9f82f..f5153f026e5 100644 --- a/boefjes/boefjes/plugins/kat_nikto/normalize.py +++ b/boefjes/boefjes/plugins/kat_nikto/normalize.py @@ -1,5 +1,4 @@ import json -import logging from collections.abc import Iterable from boefjes.job_models import NormalizerOutput @@ -8,7 +7,7 @@ from octopoes.models.ooi.software import Software, SoftwareInstance -def scan_outdated_software(data: dict, ooi_ref): +def scan_outdated_software(data: dict, ooi_ref: Reference) -> Iterable[NormalizerOutput]: for scan in data: for vulnerability in scan["vulnerabilities"]: # If the scanned vulnerability has to do with outdated software @@ -32,7 +31,6 @@ def scan_outdated_software(data: dict, ooi_ref): def run(input_ooi: dict, raw: bytes) -> Iterable[NormalizerOutput]: - logging.info(input_ooi) data = json.loads(raw) ooi_ref = Reference.from_str(input_ooi["primary_key"]) diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index 2ab82c478f1..1d98e515055 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -6,7 +6,6 @@ import run from "./main.js"; * @returns {string} */ function b64encode(inp) { - console.log(`Encoding: ${inp}`); return Buffer.from(inp).toString("base64"); } @@ -20,7 +19,7 @@ function main() { ); } catch (error) { console.error(`Getting boefje input went wrong with URL: ${input_url}`); - throw new Error(error); + throw new Error(error.message); } let out = undefined; From 0c169ba1ecae06fe6c3a30ddee6b2dc406f1955e Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Fri, 30 Aug 2024 09:03:44 +0000 Subject: [PATCH 35/37] Made nikto boefje run on `HostnameHTTPURL` Nikto boefje now consumes `HostnameHTTPURL` Fixed issue of perl not being able to handle https requests --- .../plugins/kat_nikto/boefje.Dockerfile | 5 ++-- boefjes/boefjes/plugins/kat_nikto/boefje.json | 4 +-- boefjes/boefjes/plugins/kat_nikto/main.js | 27 ++++++++++--------- .../boefjes/plugins/kat_nikto/oci_adapter.js | 4 +-- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile index f852b54f71a..ea75a179336 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.Dockerfile @@ -1,14 +1,13 @@ -FROM node:19-bullseye +FROM perl:5.40 WORKDIR /app RUN apt update RUN apt install -y git +RUN apt install -y nodejs RUN git clone https://github.com/sullo/nikto ARG BOEFJE_PATH=./boefjes/plugins/kat_nikto COPY $BOEFJE_PATH ./ -RUN npm ci - ENTRYPOINT [ "node", "./" ] diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.json b/boefjes/boefjes/plugins/kat_nikto/boefje.json index f10f492bb60..406ac61f34a 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.json +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.json @@ -3,9 +3,7 @@ "name": "Nikto", "description": "Uses Nikto", "consumes": [ - "IPAddressV4", - "IPAddressV6", - "Hostname" + "HostnameHTTPURL" ], "environment_keys": [], "scan_level": 3, diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js index 9916ef54246..3cf6f397843 100644 --- a/boefjes/boefjes/plugins/kat_nikto/main.js +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -1,29 +1,32 @@ import fs from "node:fs"; import { execSync } from "node:child_process"; - /** - * @param {{}} boefje_meta The string input to base64 encode + * @param {Object} boefje_meta Information about the task + * @param {Object} boefje_meta.arguments + * @param {Object} boefje_meta.arguments.input + * @param {string} boefje_meta.arguments.input.object_type + * @param {"http" | "https"} boefje_meta.arguments.input.scheme + * @param {number} boefje_meta.arguments.input.port + * @param {Object} boefje_meta.arguments.input.netloc + * @param {string} boefje_meta.arguments.input.netloc.name * @returns {(string | string[])[][]} */ export default function (boefje_meta) { // Depending on what OOI triggered this task, the hostname / address will be in a different location - const object_type = boefje_meta.arguments.input.object_type; - let ooi = ""; - if (["IPAddressV4", "IPAddressV6"].includes(object_type)) - ooi = boefje_meta.arguments.input.address; - else if (object_type == "Hostname") ooi = boefje_meta.arguments.input.name; - else throw new Error("Unexpected boefje_meta"); + const hostname = boefje_meta.arguments.input.netloc.name; + const scheme = boefje_meta.arguments.input.scheme; + + let command = `./nikto/program/nikto.pl -h ${hostname} -o ./output.json -404code=301,302,307,308`; + if (scheme == "https") command += " -ssl"; // Running nikto and outputting to a file try { - execSync(`./nikto/program/nikto.pl -h ${ooi} -o ./output.json`, { + execSync(command, { stdio: "inherit", }); } catch (e) { console.error(e); - throw new Error( - "Something went wrong running the nikto command.\n" + e.message, - ); + throw new Error("Something went wrong running the nikto command.\n"); } const raws = []; diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index 1d98e515055..5b585db510b 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -15,11 +15,11 @@ function main() { // Getting the boefje input try { var boefje_input = JSON.parse( - execSync(`curl --request GET --url ${input_url} -s`).toString(), + execSync(`curl --request GET --url ${input_url}`).toString(), ); } catch (error) { console.error(`Getting boefje input went wrong with URL: ${input_url}`); - throw new Error(error.message); + throw new Error(error); } let out = undefined; From 346e170f3b136e2bc9df664e782ef7bab1058c03 Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 4 Sep 2024 08:52:57 +0000 Subject: [PATCH 36/37] Added env variables to nikto boefje --- boefjes/boefjes/plugins/kat_nikto/boefje.json | 8 +++- boefjes/boefjes/plugins/kat_nikto/main.js | 44 +++++++++++++++---- .../boefjes/plugins/kat_nikto/oci_adapter.js | 2 + boefjes/boefjes/plugins/kat_nikto/schema.json | 28 +++++++++++- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/boefje.json b/boefjes/boefjes/plugins/kat_nikto/boefje.json index 406ac61f34a..e4cd50cf81a 100644 --- a/boefjes/boefjes/plugins/kat_nikto/boefje.json +++ b/boefjes/boefjes/plugins/kat_nikto/boefje.json @@ -5,7 +5,13 @@ "consumes": [ "HostnameHTTPURL" ], - "environment_keys": [], + "environment_keys": [ + "PROXYHOST", + "PROXYPORT", + "PROXYUSER", + "PROXYPASS", + "USERAGENT" + ], "scan_level": 3, "oci_image": "openkat/nikto", "oci_arguments": [] diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js index 3cf6f397843..414cf7401e7 100644 --- a/boefjes/boefjes/plugins/kat_nikto/main.js +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -1,5 +1,6 @@ import fs from "node:fs"; import { execSync } from "node:child_process"; + /** * @param {Object} boefje_meta Information about the task * @param {Object} boefje_meta.arguments @@ -15,18 +16,45 @@ export default function (boefje_meta) { // Depending on what OOI triggered this task, the hostname / address will be in a different location const hostname = boefje_meta.arguments.input.netloc.name; const scheme = boefje_meta.arguments.input.scheme; + const IS_USING_PROXY = !!process.env.PROXYHOST; + + // Setup config file + try { + let config_contents = + "PROMPTS=no\nUPDATES=no\nCLIOPTS=-404code=301,302,307,308 -o ./output.json"; + + // CLI OPTIONS + if (scheme == "https") config_contents += " -ssl"; + if (IS_USING_PROXY) config_contents += " -useproxy"; + config_contents += "\n"; + + if (IS_USING_PROXY) { + const PROXY_HOST = process.env.PROXYHOST; + const PROXY_PORT = process.env.PROXYPORT || "8080"; + const PROXY_USER = process.env.PROXYUSER || ""; + const PROXY_PASS = process.env.PROXYPASS || ""; + + config_contents += `PROXYHOST=${PROXY_HOST}\n`; + config_contents += `PROXYPORT=${PROXY_PORT}\n`; + config_contents += `PROXYUSER=${PROXY_USER}\n`; + config_contents += `PROXYPASS=${PROXY_PASS}\n`; + } - let command = `./nikto/program/nikto.pl -h ${hostname} -o ./output.json -404code=301,302,307,308`; - if (scheme == "https") command += " -ssl"; + if (process.env.USERAGENT) + config_contents += `USERAGENT=${process.env.USERAGENT}\n`; + + fs.writeFileSync("./nikto.conf", config_contents); + } catch (e) { + console.error("Something went wrong writing to the config file.\n" + e); + } // Running nikto and outputting to a file try { - execSync(command, { + execSync(`./nikto/program/nikto.pl -h ${hostname} -config ./nikto.conf`, { stdio: "inherit", }); } catch (e) { - console.error(e); - throw new Error("Something went wrong running the nikto command.\n"); + throw new Error("Something went wrong running the nikto command.\n" + e); } const raws = []; @@ -36,10 +64,8 @@ export default function (boefje_meta) { var file_contents = fs.readFileSync("./output.json").toString(); raws.push([["boefje/nikto-output"], file_contents]); } catch (e) { - console.error(e.message); throw new Error( - "Something went wrong reading the file from the nikto command.\n" + - e.message, + "Something went wrong reading the file from the nikto command.\n" + e, ); } @@ -50,7 +76,7 @@ export default function (boefje_meta) { if (vulnerability["id"].startsWith("6")) raws.push([["openkat/finding"], "KAT-OUTDATED-SOFTWARE"]); } catch (e) { - console.error(e.message); + console.error(e); } return raws; diff --git a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js index 5b585db510b..83ae47927f1 100644 --- a/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js +++ b/boefjes/boefjes/plugins/kat_nikto/oci_adapter.js @@ -22,6 +22,8 @@ function main() { throw new Error(error); } + Object.assign(process.env, boefje_input["boefje_meta"]["environment"]); + let out = undefined; let output_url = boefje_input.output_url; try { diff --git a/boefjes/boefjes/plugins/kat_nikto/schema.json b/boefjes/boefjes/plugins/kat_nikto/schema.json index defe43d5eb9..9286d2e6ac5 100644 --- a/boefjes/boefjes/plugins/kat_nikto/schema.json +++ b/boefjes/boefjes/plugins/kat_nikto/schema.json @@ -1,6 +1,32 @@ { "title": "Arguments", "type": "object", - "properties": {}, + "properties": { + "PROXYHOST": { + "title": "PROXYHOST", + "maxLength": 256, + "type": "string" + }, + "PROXYPORT": { + "title": "PROXYPORT", + "maxLength": 256, + "type": "string" + }, + "PROXYUSER": { + "title": "PROXYUSER", + "maxLength": 256, + "type": "string" + }, + "PROXYPASS": { + "title": "PROXYPASS", + "maxLength": 256, + "type": "string" + }, + "USERAGENT": { + "title": "USERAGENT", + "maxLength": 256, + "type": "string" + } + }, "required": [] } From 8d5cba0fd39283aa7cc4175d21453d10a69c1b9c Mon Sep 17 00:00:00 2001 From: Soufyan Abdellati Date: Wed, 4 Sep 2024 10:58:09 +0000 Subject: [PATCH 37/37] Moved config file creation to a seperate function --- boefjes/boefjes/plugins/kat_nikto/main.js | 49 +++++++++++++++-------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/boefjes/boefjes/plugins/kat_nikto/main.js b/boefjes/boefjes/plugins/kat_nikto/main.js index 414cf7401e7..e9bf0da4484 100644 --- a/boefjes/boefjes/plugins/kat_nikto/main.js +++ b/boefjes/boefjes/plugins/kat_nikto/main.js @@ -2,20 +2,10 @@ import fs from "node:fs"; import { execSync } from "node:child_process"; /** - * @param {Object} boefje_meta Information about the task - * @param {Object} boefje_meta.arguments - * @param {Object} boefje_meta.arguments.input - * @param {string} boefje_meta.arguments.input.object_type - * @param {"http" | "https"} boefje_meta.arguments.input.scheme - * @param {number} boefje_meta.arguments.input.port - * @param {Object} boefje_meta.arguments.input.netloc - * @param {string} boefje_meta.arguments.input.netloc.name - * @returns {(string | string[])[][]} + * @param {string} scheme + * @returns {string} */ -export default function (boefje_meta) { - // Depending on what OOI triggered this task, the hostname / address will be in a different location - const hostname = boefje_meta.arguments.input.netloc.name; - const scheme = boefje_meta.arguments.input.scheme; +function get_config_content(scheme) { const IS_USING_PROXY = !!process.env.PROXYHOST; // Setup config file @@ -23,7 +13,6 @@ export default function (boefje_meta) { let config_contents = "PROMPTS=no\nUPDATES=no\nCLIOPTS=-404code=301,302,307,308 -o ./output.json"; - // CLI OPTIONS if (scheme == "https") config_contents += " -ssl"; if (IS_USING_PROXY) config_contents += " -useproxy"; config_contents += "\n"; @@ -43,10 +32,31 @@ export default function (boefje_meta) { if (process.env.USERAGENT) config_contents += `USERAGENT=${process.env.USERAGENT}\n`; - fs.writeFileSync("./nikto.conf", config_contents); + return config_contents; } catch (e) { - console.error("Something went wrong writing to the config file.\n" + e); + throw new Error("Something went wrong writing to the config file.\n" + e); } +} + +/** + * @param {Object} boefje_meta Information about the task + * @param {Object} boefje_meta.arguments + * @param {Object} boefje_meta.arguments.input + * @param {string} boefje_meta.arguments.input.object_type + * @param {"http" | "https"} boefje_meta.arguments.input.scheme + * @param {number} boefje_meta.arguments.input.port + * @param {Object} boefje_meta.arguments.input.netloc + * @param {string} boefje_meta.arguments.input.netloc.name + * @returns {(string | string[])[][]} + */ +export default function (boefje_meta) { + // Depending on what OOI triggered this task, the hostname / address will be in a different location + const hostname = boefje_meta.arguments.input.netloc.name; + + const config_contents = get_config_content( + boefje_meta.arguments.input.scheme, + ); + fs.writeFileSync("./nikto.conf", config_contents); // Running nikto and outputting to a file try { @@ -54,7 +64,12 @@ export default function (boefje_meta) { stdio: "inherit", }); } catch (e) { - throw new Error("Something went wrong running the nikto command.\n" + e); + throw new Error( + "Something went wrong running the nikto command.\n" + + e + + "\n" + + config_contents, + ); } const raws = [];