Simple Python helper to probe Fortinet/FortiWeb targets for the fwbcgi authentication bypass pattern reported by watchTowr Labs. Intelligence and request details came from: https://labs.watchtowr.com/when-the-impersonation-function-gets-used-to-impersonate-users-fortinet-fortiweb-auth-bypass/
python3 scanner.py http://192.168.9.1:80
python3 scanner.py -f targets.txt --find-forti --follow-redirects
Targets must include their scheme explicitly (http:// or https://). If the port is omitted, the scanner assumes 80 for HTTP or 443 for HTTPS. Outputs one line per target with [+] VULNERABLE, [+] MAY BE VULNERABLE, [+] PATCHED, [+] POSSIBLY PATCHED, or [-] INDETERMINATE; optionally highlights words containing “forti”.
targets: one or more<scheme>://<host>[:<port>]entries on the command line (ports default to80for HTTP or443for HTTPS).-f/--targets-file: read additional targets from file(s); same<scheme>://<host>[:<port>]format.--timeout: socket timeout in seconds (default5).--find-forti: print unique tokens containing “forti” that appeared in the response body.--follow-redirects: opt-in redirect handling for targets that issue 30x responses.--max-redirects: limit for redirect hops when--follow-redirectsis active (default3,0disables following even if the flag is present).--validate-tls: force certificate validation for HTTPS targets and redirects (default behavior skips validation to avoid blocking on self-signed certs).--workers: number of concurrent scans to run via asyncio (default10).--user-agent: custom HTTP User-Agent header (defaultfwbcgi-scanner/1.0).--csv-output: write<target>,<classification>rows to the given CSV file in addition to console output.
Due to a lack of decent testing infra, here's the naive test suite I used.
PYTHONPYCACHEPREFIX=./.pycache python3 -m unittest discover -s tests
The scanner relies on TLS 1.2+ support to talk to modern Fortinet or Cloudflare-fronted sites. Make sure the python3 you run is linked against a recent OpenSSL build:
- macOS: The system Python (
/usr/bin/python3) is tied to LibreSSL 2.8 and cannot negotiate TLS 1.3, causingTLSV1_ALERT_PROTOCOL_VERSIONerrors. Install a modern interpreter via Homebrew (brew install python) or pyenv and run the scanner with that binary (e.g.,/opt/homebrew/bin/python3). - Linux: Most distro-supplied Pythons are already linked to OpenSSL ≥ 1.1.1. Verify with
python3 - <<'PY'\nimport ssl; print(ssl.OPENSSL_VERSION)\nPY. If it reports something older, install an updated python (pyenv, distro backports, etc.). - Windows: Use the official python.org downloads (3.11+) which bundle OpenSSL 3.x. Double-check via the same
ssl.OPENSSL_VERSIONsnippet if you’re running inside WSL or an older virtual environment.
If you must run on an older interpreter, expect HTTPS targets that require TLS 1.3 to fail; HTTP targets continue to work regardless.