
A read-only, passive scanner that checks a REDCap host for exposure to and compromise by **CVE-2026-90817** — the unauthenticated survey-endpoint remote-code-execution flaw abused by the XMRig cryptomining campaign documented by Palo Alto Unit 42
redcap_cve_2026_90817_scan.py is a read-only, passive scanner that checks a
REDCap host for exposure to and compromise by CVE-2026-90817 — the
unauthenticated survey-endpoint remote-code-execution flaw abused by the XMRig
cryptomining campaign documented by Palo Alto Unit 42
(2026-10-07-XMRig-campaign-through-CVE-2026-90817).
It answers two questions about the host it runs on:
This tool is detection only. It:
It is intended for an administrator running it against their own REDCap server.
pip installs. A single file; copy
it to the host and run./var/log/apache2 (Debian) or /var/log/httpd
(RHEL/CentOS/Rocky/Alma), and nginx at /var/log/nginx. On RHEL 8 the system
python3 is 3.6, so invoke python3.9 (or newer) there; RHEL/Rocky/Alma 9
ship 3.9+. Run as root for a complete scan (per-user crontabs, other users'
authorized_keys and /proc/<pid>/exe, and some logs are otherwise
unreadable). Without root it still runs and clearly marks the result as a
partial scan.# Simplest: defaults to /var/www/html/redcap, auto-detects the mitigation date
sudo python3 -I redcap_cve_2026_90817_scan.py
# Point at a non-default install, pin the mitigation date, list every attack entry
sudo python3 -I redcap_cve_2026_90817_scan.py \
--redcap-root /var/https/redcap \
--mitigation-date 2026-09-21 \
--max-log-matches all
# Machine-readable output for monitoring / ticketing
sudo python3 -I redcap_cve_2026_90817_scan.py --json
On Windows, run from an elevated prompt and point --redcap-root at the
install (platform and default log dirs are auto-detected):
# IIS or Apache/XAMPP; logs under C:\inetpub\logs\LogFiles or the Apache logs dir
python -I redcap_cve_2026_90817_scan.py --redcap-root C:\redcap --json
-I runs Python in isolated mode (ignores $PYTHONPATH and the CWD) — good hygiene
when scanning a possibly-tampered host.
| Flag | Default | Purpose |
|---|---|---|
--redcap-root PATH | /var/www/html/redcap | REDCap install root. |
--log-dir DIR (repeatable) | platform-specific (Apache/nginx on Linux; IIS LogFiles + Apache on Windows) | Web-server log directories to scan (handles rotated .gz and IIS W3C logs). |
--home-dir DIR (repeatable) | /root + each /home/* (Linux); each C:\Users\* (Windows) | Extra home dirs to scan for SSH keys / shell/profile files. |
--platform auto|linux|windows | auto | Host platform to assume. Auto-detects from the OS; force it to select a provider (OS-specific host probes still run only on the matching live OS). |
--mitigation-date YYYY-MM-DD | auto-detected | Date the vulnerability was closed by upgrading. See Attack timing. |
--since YYYY-MM-DD | — | Only examine web-log entries on or after this date (inclusive). Log files last modified earlier are not opened. Applies to both log passes; host-state checks are unaffected. See Attack timing. |
--until YYYY-MM-DD | — | Only examine web-log entries on or before this date (inclusive). |
--full-hash-scan | off | Recursively hash files under temp/cache and staging dirs (slower). |
--max-log-matches N | all | 100 | How many attack log entries to list per category, kept verbatim. |
--attacker-ip IP (repeatable) | — | Extra known attacker IP (e.g. from another host's scan). Treated like the documented IOC IP. See Second pass. |
--json | off | Emit JSON instead of the text report. |
--quiet | off | Suppress OK/INFO lines in text output. |
| Code | Meaning |
|---|---|
0 | Clean and patched, and the scan completed fully. |
1 | One or more findings (vulnerable version and/or IOC/attack) — investigate. |
2 | Scan could not be completed fully (errors, or unprivileged and otherwise clean — a clean result could not be fully asserted). |
Each documented IOC maps to a passive local check:
redcap_vX.Y.Z
directory names and compares against the patched releases
(16.0.49 LTS / 17.3.10 LTS / 17.4.4 Standard; affected floor 13.3.0).temp/cache — every file there (and in the staging
dirs) is hashed against the Unit 42 dropper SHA-256. Note: the tool does not
flag files by the .bladec extension. REDCap core uses the BladeOne template
engine, which writes hash-named .bladec compiled templates to temp/cache as
normal output, so the extension is not an indicator of compromise; a genuinely
malicious dropped file is caught by its content hash, regardless of extension..syslog-* dirs, xmrig* archives, and the competitor
directories (/dev/shm/duet, /var/tmp/.bin) the campaign locks to perms 000./var/tmp, /dev/shm, /tmp, and syslog-ng-* masquerading processes.127.0.0.1:50001, and live
connections to the attacker source IP(s) — the documented one, the
observed ones, any --attacker-ip, and every IP the web-log check discovered.authorized_keys — keys matching the attacker's backdoor fingerprint.
(It deliberately does not list unrelated keys for "review" — on a normal host
those belong to real accounts and aren't independently verifiable.)~/.profile — injected startup code and HISTFILE anti-forensics.__passthru and route= on their own are legitimate REDCap parameters —
External Modules route through __passthru, and normal survey traffic uses a plain
__passthru=index.php to reach benign controllers like PdfController and
SendItController. The scanner therefore never matches on those alone. A log line
is treated as exploit-shaped only when it shows:
__passthru reaching DataImportController (the report's
documented sink), at any encoding; or__passthru reaching any internal …Controller — e.g.
__passthru=%2569ndex.php&route=ParcelController:show. This is the campaign's
generalizable signature: legitimate clients send a plain, literal index.php,
never a double-encoded one, so the obfuscation (not the controller name, not
the HTTP status) is what distinguishes the attack. This is what catches attacker
hosts other than the one documented IOC IP; or