
Python checker and exploit hook for CVE-2026-90817, a critical unauthenticated REDCap RCE via survey __passthru routing, with mass scanning and FOFA target import.
Python 3 checker (and configurable exploit hook) for CVE-2026-90817 (Securifera / Ryan Wincey).
| Product | REDCap (Vanderbilt) |
| Affected | ≥ 13.3.0 (until branch patch) |
| Fixed | 16.0.49 LTS, 17.3.10 LTS, 17.4.4 Standard+ |
| CVSS 3.1 | 9.8 Critical |
| Auth | None — valid public survey hash (s=) required for full chain |
| CWE | CWE-73, CWE-94 |
From a public survey context, attackers can abuse __passthru (survey passthrough) routing to reach unintended controllers (e.g. Data Import), then trigger unsafe file-path / stream handling → RCE.
Securifera has not published the full HTTP chain yet (no public PoC on GitHub / Exploit-DB at repo publish time).
| Mode | What it does |
|---|---|
check | REDCap fingerprint, version heuristics, valid s= survey (if hash given), __passthru → DataImport probes |
exploit | Runs only with a verified exploit_chain.json (not the placeholder example) |
exploit_chain.example.json is placeholder only (guessed routes/params). It will not RCE.
Research dry run: --allow-placeholder-chain (sends requests; expect failure).
pip install -r requirements.txtpip install -r requirements.txt
# Single target (survey hash required for survey + passthru tests)
python poc.py -u https://redcap.example.edu/redcap --hash Ab12Xy34Zq --mode check
# Shorthand: base|hash
python poc.py -u "https://redcap.example.edu/redcap|Ab12Xy34Zq" --mode check
# Mass check (one URL per line, optional |hash)
python poc.py --list targets.example.txt --mode check -j 20 -q
# Live stream: every host + test summary (recommended for long lists)
python poc.py --list targets.example.txt --mode check -j 20 -q --flow
# Exploit (after advisory → real exploit_chain.json)
cp exploit_chain.example.json exploit_chain.json # edit with real values
python poc.py -u https://redcap.example.edu/redcap --hash XXX --mode exploit -c id \
--chain exploit_chain.json
# Place export as fofa_csv_7561.csv (or any fofa*.csv), then:
python fofa_to_list.py
# Writes list.txt (gitignored) and normalizes the CSV with a url column
python poc.py --list list.txt --mode check -j 20 -q --flow
https://uni.edu/redcap|SurveyHash10
https://uni.edu/redcap?s=SurveyHash10
https://uni.edu/redcap
Without a hash, check can still fingerprint REDCap and flag version windows, but cannot validate survey or run passthru probes.
--flow mass check)
| Option | Description |
|---|---|
-u, --url | Single base URL (or URL|hash) |
--hash | Public survey hash (s= value) |
--list | Target file (one URL or URL|hash per line) |
--mode | check or exploit |
--chain | JSON chain for exploit mode (default exploit_chain.json) |
--allow-placeholder-chain | Allow example JSON in exploit mode (no real RCE) |
-c, --command | Shell command (exploit mode; needs working chain) |
--threads, -j | Mass concurrency (default 15) |
--timeout | HTTP timeout seconds (default 25) |
--proxy | HTTP(S) proxy URL |
--output | JSONL results (default cve_2026_90817_results.jsonl) |
--vuln-list | Check → hits.txt; exploit → exploited.txt |
--quiet, -q | Suppress periodic progress ticks |
--flow, -f | One line per completed target (site + test summary) |
| File | Content |
|---|---|
cve_2026_90817_results.jsonl | Per-target JSON |
hits.txt | Candidates (exploitable_candidate) |
status values (check)| Status | Meaning |
|---|---|
passthru_dataimport_reachable | Valid survey + passthru route looks like Data Import |
passthru_probe_reachable | Passthru returned non-blocked HTTP |
likely_vulnerable_version | Version in affected window (survey OK, probes inconclusive) |
redcap_version_hot_no_hash | Affected version heuristics, no survey hash supplied |
redcap_no_survey_hash | REDCap OK, no hash, version unknown |
patched / patched_no_survey | At or above fixed version for branch |
no_valid_survey | Hash invalid or survey not public |
no_redcap | Host does not look like REDCap |
survey_ok_version_unknown | Survey OK, version string not found |
__passthru route and parameter names from Securifera/vendor; defaults are placeholders.vulnerable_version may be null.title="REDCap" rows often lack survey hashes — CVE preconditions need s= from public links.title="REDCap"
body="redcap_version"
body="/surveys/?s="
.
├── poc.py
├── fofa_to_list.py
├── exploit_chain.example.json
├── poc.png # example --flow terminal output
├── requirements.txt
├── targets.example.txt
├── README.md
├── LICENSE
└── .gitignore
For authorized security testing only. You are responsible for compliance with applicable laws and program rules.