Skip to content

5) CVE Module

Mastau edited this page Dec 4, 2025 · 1 revision

CVE Module

Module structure

A CVE module is a standalone Python file (in modules/) that defines metadata and checking functions.

Mandatory variables

Each module must define the following global variables:

Variable Type Description
CVE_ID str The CVE identifier (e.g., "CVE-2018-20979").
DESCRIPTION str A short description of the vulnerability.
PLUGIN_SLUG str The slug of the affected plugin (e.g., "contact-form-7").
VULN_MAX_VERSION str The maximum vulnerable version (inclusive, e.g., "5.0.3").

Mandatory methods

The module must expose the check function for passive version analysis.

Method Argument Role
check enum_data(dict) Performs a passive check (based on version). Must return a result dictionary if vulnerable, otherwise None.

Optional methods

Method Argument Role
run target_url, enum_data Contains the Active Exploitation logic (Proof of Concept) if the vulnerability is confirmed.

How a module is loaded (automatic)

The CVE Engine (in core/cve_engine.py) uses Python introspection:

  1. It scans the modules/ directory.
  2. For every .py file, it dynamically imports the module.
  3. It checks for the presence of the mandatory variables (CVE_ID, PLUGIN_SLUG, etc.) and the check() function.
  4. All valid modules are loaded and stored in a list for execution. Adding a new .py file to modules/ makes it immediately available.

Creating a CVE module

Step-by-Step Tutorial (Example: modules/cve_cf7_2018_20979.py)

Step 1: Create the File

Create a new file in the modules/ directory with a descriptive name, e.g., cve_myplugin_id.py.

Step 2: Add Variables & IDs

Define the mandatory variables and helper functions for version comparison.

CVE_ID = "CVE-YYYY-XXXXX"
DESCRIPTION = "Description of the vulnerability"
PLUGIN_SLUG = "my-plugin"
VULN_MAX_VERSION = "1.2.3"

# ... include the _parse_version and _is_vulnerable_version helpers
def _parse_version(v: str):
    if not v:
        return None
    result = []
    for part in v.split("."):
        try:
            result.append(int(part))
        except ValueError:
            break
    while len(result) < 3:
        result.append(0)
    return tuple(result[:3])


def _is_vulnerable_version(v):
    pv = _parse_version(v)
    vmax = _parse_version(VULN_MAX_VERSION)
    if not pv or not vmax:
        return False
    return pv <= vmax

Step 3: Write the check(enum_data) function

This function implements the passive verification logic.

  1. Check if the PLUGIN_SLUG is present in enum_data["plugins"].
  2. Use _is_vulnerable_version(installed_version) for comparison.
  3. Return the result dictionary if vulnerable.
def check(enum_data):
    plugins = enum_data.get("plugins", {})
    if PLUGIN_SLUG not in plugins:
        return None

    installed = plugins.get(PLUGIN_SLUG)

    if installed is None:
        return {
            "cve": CVE_ID,
            "plugin": PLUGIN_SLUG,
            "version": None,
            "vulnerable": None,
            "details": "Version unknown; manual investigation required."
        }

    if _is_vulnerable_version(installed):
        return {
            "cve": CVE_ID,
            "plugin": PLUGIN_SLUG,
            "version": installed,
            "vulnerable": True,
            "details": f"{installed} <= {VULN_MAX_VERSION}"
        }

    return None

Step 4: Testing the Integration

  • Run WPBurst against your Docker Lab (where the vulnerable plugin is installed).
  • Verify that the module loads and the result is displayed.

Checklist (BONUS)

  • Naming: Name the file cve_{plugin_slug}_{short_id}.py.
  • Comparison: Always use a robust function for version comparison (e.g., _is_vulnerable_version).
  • Documentation: Add clear comments for the run() function, especially if no active PoC is provided.

Clone this wiki locally