{"uuid": "6695e9fb-a165-49cc-a6cb-1c36363eb492", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2018-12613", "type": "seen", "source": "https://gist.github.com/R1sh0bh-1/e3c5cc26bd86f8855b7f134907987c2a", "content": "# OWASP Web Application Honeypot: GSoC 2026 Final Report\n\n**Organization:** OWASP Foundation\n**Contributor:** Rishabh Shukla\n**Mentor:** Adrian Winckles\n**GSoC 2026 Contributor, OWASP Foundation**\n\n---\n\n## Project Overview\n\nWhen I first ran the OWASP Honeypot Project locally, the picture was pretty clear: it worked, but it\nwas a sensor with nowhere to send data. ModSecurity was capturing attacks, the logs were going into\na legacy mlogc format that nothing downstream could easily consume, there was no enrichment pipeline,\nno way to detect when the honeypot had been fingerprinted and burned, and no path for getting\nanything useful into MISP or a STIX feed. Adrian's vision, which he was very direct about in our\nearly conversations, was a honeypot that adapts to its environment, generates community-ready threat\nintelligence automatically, and can be deployed across AWS regions without manual intervention for\neach one.\n\nThat was the scope. Eight interconnected deliverables, each one building on the last.\n\n---\n\n## Goals\n\n- Replace the legacy mlogc logging format with a versioned JSON schema and rewrite the Logstash\n  pipeline to enrich events with GeoIP2 and MITRE ATT&amp;CK mappings\n- Automate CRS version management so the WAF never silently falls behind on rule updates\n- Build a CRS 4.x honeytrap plugin with a hot-reload daemon so new rules take effect without\n  touching any running container\n- Build a Chameleon Persona Engine that polls Shodan and rotates the honeypot's identity on trigger\n  with zero downtime\n- Deliver a library of four realistic vulnerable application personas, each tied to specific CVEs\n- Provide a Terraform-based multi-region AWS deployment framework with centralised Kibana\n  aggregation\n- Build MISP and STIX 2.1 exporters that read directly from the versioned JSON schema\n- Ship three industry segment profiles (education/research, financial, general) switchable via a\n  single environment variable, with configurable severity thresholds for each\n\n---\n\n## What I Did\n\n### Structured JSON Logging Schema (v1.1)\n\nThe first thing I did was design the schema and get it right before writing any other code. The\nfinal v1.1 schema captures the full picture for both operational use and academic research: an event\nenvelope with `node_id` and `aws_region` for multi-region correlation, persona context, attack\nclassification with a `honeytrap_triggered` boolean, MITRE ATT&amp;CK technique IDs as an array\n(not a single string, which the old format was using), GeoIP2 enrichment with ASN and ISP fields,\nthe full HTTP transaction, and feed metadata for batch correlation. The Logstash pipeline went from\na bare pass-through to a proper filter stage. Getting this right upfront genuinely made every\nsubsequent deliverable easier than it would have been otherwise.\n\n### Automated CRS Version Management\n\nA nightly GitHub Actions workflow polls for new CRS releases, builds the Docker image against the\nnew tag, runs the test suite, and opens a version-bump PR automatically. The Dockerfile was\nrefactored to take `CRS_VERSION` as an explicit build argument so the version is always auditable\nand a failed update never silently affects a running deployment. A later PR added LTS auto-merge,\nsmoke tests, and per-stack CRS version tracking across the mds_elk, mlogc_elk, and honeytraps\nstacks.\n\n### CRS 4.x Honeytrap Plugin with Hot-Reload\n\nBuilt a dedicated plugin in the reserved rule ID range 9,500,000 to 9,999,999. The plugin covers\nfake high-value endpoints, scanner fingerprint detection, rapid probing detection, and credential\ncanaries. Alongside the plugin came `rule_watcher.py`, a daemon that watches the rule files for\nchanges and calls `apachectl graceful` so updates load without restarting anything. It falls back\nto a full container restart if graceful fails three times in a row.\n\n### Chameleon Persona Engine\n\n`persona_watchdog.py` polls the Shodan API for the honeypot's public IP on a configurable interval.\nWhen the Honeyscore crosses the configurable threshold (anywhere from 0.4 to 0.7 depending on how\naggressively you want to rotate) or Shodan tags the host directly as a honeypot, it rewrites\n`docker-compose.override.yml` to point the persona backend at the next pre-built image, then runs\n`docker compose up -d` which only recreates the persona_backend container. The WAF container is\nnot touched on subsequent rotations. Only the very first rotation causes a one-time WAF restart so\nit picks up the initial BACKEND environment variable. After that, apachectl graceful inside the WAF\nflushes the proxy cache and the WAF stays up for every rotation that follows. Every rotation gets a\nline in `rotation_log.jsonl`. Exponential backoff handles Shodan rate limits and a local score cache\nmakes sure a temporary API outage never triggers a false rotation.\n\n### Vulnerable Application Persona Library\n\nFour self-contained personas, each simulating a specific application version with known CVEs as\nattacker lures:\n\n- `wordpress-5.0`: WordPress 5.0, CVE-2019-8942 and CVE-2019-8943 (chained image upload plus\n  path traversal to RCE, exploitable at author privilege level)\n- `phpmyadmin-4.8.1`: phpMyAdmin 4.8.1, CVE-2018-12613 (LFI via the file parameter,\n  unauthenticated when AllowArbitraryServer is enabled)\n- `iis-7.5-fastcgi`: IIS 7.5 with FastCGI, CVE-2010-2730 (FastCGI request header buffer overflow\n  enabling RCE, targets Windows-focused attackers)\n- `apache-2.2-php5`: Apache 2.2 with PHP-CGI, CVE-2012-1823 (PHP-CGI argument injection,\n  closest to the existing project base so easiest to validate against)\n\nEach persona is a self-contained directory. Adding a new one requires zero changes to the engine code.\n\n### Multi-Region AWS Deployment Framework\n\nA Terraform module provisioning EC2 nodes across multiple regions with Elastic IP assignment and\nFilebeat log shipping. The module is additive, so each new region is a new module call rather than\na rewrite. This PR is currently in review.\n\n### MISP and STIX 2.1 Exporters\n\nTwo standalone exporters that read the v1.1 schema directly with no format translation in between.\n\nThe MISP exporter has two modes. Batch reads a JSON file and pushes all events to MISP in one shot.\nReal-time tails a Logstash output file and forwards events as they arrive. Each event maps to one\nMISP event with the source IP, request line, GeoIP2 data, CVE as a vulnerability attribute, MITRE\ntechnique tags, and the full raw JSON blob so nothing gets dropped.\n\nThe STIX 2.1 exporter builds bundles containing `AttackPattern` objects per MITRE technique ID\n(with external references back to attack.mitre.org), an `Indicator` for the source IP, and an\n`ObservedData` object. Output goes to a local file, a TAXII 2.1 endpoint, or both. Every bundle is\nvalidated by the stix2 library before anything is written or pushed.\n\nBoth exporters support a `--min-severity` flag so analysts can pick any level from CRITICAL down\nto LOW. This came directly from Adrian's feedback after the exporters merged. Setting LOW captures\neverything including low-severity noise. The default stays HIGH in real-time mode so existing\nsetups are unaffected. The test suite covers all four graded levels end-to-end, building actual\nSTIX bundles and MISP events from a mixed-severity event set and confirming the right events make\nit through at each threshold.\n\n### Industry Segment Profiles\n\nThree YAML profiles controlling detection thresholds, rotation sensitivity, and export settings\nfor different deployment contexts. `education_research.yaml` runs with a 0.55 Honeyscore threshold\nand captures everything down to LOW severity so research datasets are as complete as possible.\n`financial.yaml` rotates more aggressively at 0.40 and pushes only HIGH and above to MISP in\nreal-time to keep the feed high-signal. `general.yaml` uses balanced defaults at 0.6 and is the\nfallback when `HONEYPOT_PROFILE` is not set.\n\n`profile_loader.py` reads the env var, loads the YAML, validates all required keys and value ranges\nat startup, and fails loudly with a specific error if anything is wrong. A broken profile never\nsilently applies wrong settings.\n\n---\n\n## Current State\n\nMost of the project is built, tested, and merged. The JSON schema migration, CRS automation,\nhoneytrap plugin, chameleon engine, persona library, and MISP/STIX exporters are all in master.\nThe industry segment profiles PR (which also includes the `--min-severity` exporter update) and\nthe Terraform multi-region PR are both currently in review.\n\nThe exporters are the most immediately usable piece right now. They run standalone against any\ndeployment and do not depend on any of the pending PRs.\n\n---\n\n## What's Left to Do\n\n- Merge of the industry segment profiles PR (#99, currently in review), which also includes the\n  `--min-severity` flag for both exporters\n- Merge of the Terraform multi-region PR (#97, currently in review)\n- Build `deploy_fleet.py` on top of the merged Terraform outputs. The script is designed but\n  depends on the Terraform outputs being finalised first, so I parked it rather than build on a\n  moving target\n- Final end-to-end integration test with all deliverables running together\n\n---\n\n## Code Contributions\n\n**Infrastructure and Docker**\n\n- Merged: [#73 fix: modernize Docker stack across mds_elk, honeytraps and mlogc_elk](https://github.com/OWASP/Honeypot-Project/pull/73)\n- Merged: [#75 ci: add Docker stack integration tests for mds_elk, mlogc_elk and honeytraps](https://github.com/OWASP/Honeypot-Project/pull/75)\n- Merged: [#95 fix: use multi-arch apache tag in waf_modsec Dockerfiles to fix AMD64 CI failures](https://github.com/OWASP/Honeypot-Project/pull/95)\n\n**JSON Schema and Logging**\n\n- Merged: [#76 feat: v1.1 JSON Schema Migration and Pipeline Enrichment](https://github.com/OWASP/Honeypot-Project/pull/76)\n- Merged: [#90 feat: finalize v1.1 schema migration, logstash routing, and kibana dashboards](https://github.com/OWASP/Honeypot-Project/pull/90)\n\n**CRS Automation and WAF**\n\n- Merged: [#74 feat: implement automated CRS version update workflow](https://github.com/OWASP/Honeypot-Project/pull/74)\n- Merged: [#87 feat: add LTS auto-merge, smoke test, and multi-stack CRS version tracking](https://github.com/OWASP/Honeypot-Project/pull/87)\n- Merged: [#91 chore: upgrade base WAF to CRS v4.25 LTS and wire plugin architecture](https://github.com/OWASP/Honeypot-Project/pull/91)\n- Merged: [#92 feat: implement CRS 4.x active deception plugins, hot-reload watchdog, and v1.1 telemetry schema](https://github.com/OWASP/Honeypot-Project/pull/92)\n\n**Chameleon Engine and Personas**\n\n- Merged: [#93 feat: add 4 vulnerable application personas for the chameleon engine](https://github.com/OWASP/Honeypot-Project/pull/93)\n- Merged: [#96 feat: add chameleon engine daemon for dynamic persona rotation](https://github.com/OWASP/Honeypot-Project/pull/96)\n\n**Threat Intelligence**\n\n- Merged: [#98 feat: add MISP and STIX 2.1 threat intelligence exporters](https://github.com/OWASP/Honeypot-Project/pull/98)\n- Open (in review): [#99 feat: add industry segment profiles and --min-severity exporter flag](https://github.com/OWASP/Honeypot-Project/pull/99)\n\n**Infrastructure as Code**\n\n- Open (in review): [#97 feat: add multi-region terraform module for honeypot deployment](https://github.com/OWASP/Honeypot-Project/pull/97)\n\n---\n\n## Challenges and Learnings\n\nThe stickiest technical problem was in the STIX exporter. The `stix2` Python library's `Indicator`\nconstructor silently rejects an `indicates` keyword argument in strict mode but does not raise a\nclear error about it. I spent more time on this than I want to admit before realising the\nrelationship between the Indicator and the AttackPattern is implicit in the bundle structure and\nthe field was unnecessary in the first place. The fix was simple once I understood it, but getting\nthere meant reading the library source rather than the docs. I now run the stix2 validator locally\nbefore assuming anything about a bundle.\n\nThe other thing that took real thought was `deploy_fleet.py`. It needs Terraform outputs to be\nfinalised before it can be built properly, and the Terraform PR is still in review. The tempting\nmove was to write it speculatively against a draft of those outputs and patch it after the merge,\nbut that felt like the kind of shortcut that causes rework and messier history. So I have not\nstarted it yet. I'll build it the moment the Terraform PR lands. Keeping it unstarted rather than\nhalf-built was an active decision, and I think it was the right one.\n\nOne thing I underestimated at the start was how much the schema decision in week one would matter\nfor everything else. Because the exporters read v1.1 directly, there was no translation layer to\nwrite, debug, or maintain. The Kibana dashboards, the MISP attributes, the STIX objects, all of\nit follows the same field paths. Getting the schema right before writing any consumer code saved\na significant amount of rework.\n\n---\n\n## Links and Resources\n\n- Repository: https://github.com/OWASP/Honeypot-Project\n- OWASP Honeypot Project: https://owasp.org/www-project-honeypot/\n- MITRE ATT&amp;CK: https://attack.mitre.org\n- stix2 Python library: https://github.com/oasis-open/cti-python-stix2\n- PyMISP: https://github.com/MISP/PyMISP\n- OWASP CRS: https://coreruleset.org\n\n---\n\n## Acknowledgements\n\nBefore I was even selected, Adrian took the time to walk me through exactly what he wanted the\nproject to become. That initial Slack conversation covered the JSON schema direction, the\napplication-first persona approach with CVE lures, the Shodan rotation trigger, industry segment\nprofiles, the MISP and STIX exporters, and the multi-region AWS framework. Basically the entire\nscope of this project came from that conversation. Most proposals are written in a vacuum and then\nreconciled with the mentor after acceptance. Mine was not, and that made a real difference to how\nthe summer went.\n\nDuring the programme he was equally direct. Quick PR reviews, clear feedback, and when he suggested\nadding graded severity levels to the exporters after they merged, it was the kind of note that only\ncomes from someone thinking about how the tool actually gets used rather than just whether the code\npasses review. I am planning to stay involved as a contributor after the programme ends, and that\nis in no small part because of how the mentorship shaped the project into something worth\ncontinuing.\n", "creation_timestamp": "2026-08-16T10:54:36.394382Z"}