Skip to content

Add fortiweb CVE 2025 64446 - #1490

Closed
Raavi29 wants to merge 11 commits into
OWASP:masterfrom
Raavi29:add-fortiweb-cve-2025-64446
Closed

Add fortiweb CVE 2025 64446#1490
Raavi29 wants to merge 11 commits into
OWASP:masterfrom
Raavi29:add-fortiweb-cve-2025-64446

Conversation

@Raavi29

@Raavi29 Raavi29 commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Proposed change

Summary

Adds a new vulnerability detection module for CVE-2025-64446, a critical path traversal vulnerability in Fortinet FortiWeb WAF.

Vulnerability Details

  • CVE: CVE-2025-64446
  • CVSS: 9.8 (Critical)
  • Affected versions: Fortiweb 8.0.1 and earlier
  • **Fixed in: ** Fortiweb 8.0.2
  • Type: Relative path traversal -> authentication bypass
  • Impact: Unauthenticated admin account creation, full device compromise
  • Status: Actively exploited, added to the CISA KEV catalog November 14, 2025

How it works

FortiWeb's API handler forwards requests beginning with /api/v2.0 to a backend CGI handler before resolving path traversal sequences. An attacker sends a GET request to: /api/v2.0/cmdb/system/admin?/../../../../../cgi-bi/fwbcgi
This bypasses authentication entirely and reaches the internal fwbcgi administrative component.

Detection

The module sends a GET request to the traversal path on ports 443, 8443, and 80 over both HTTP ad HTTPS. A vulnerability system returns HTTP 200 with FortiWeb-specific content. Patched systems (8.0.2+) return 403.

Refrences

Type of change

  • New core framework functionality
  • Bugfix (non-breaking change which fixes an issue)
  • Code refactoring without any functionality changes
  • New or existing module/payload change
  • Documentation/localization improvement
  • Test coverage improvement
  • Dependency upgrade
  • Other improvement (best practice, cleanup, optimization, etc)

Checklist

  • I've followed the contributing guidelines
  • I have digitally signed all my commits in this PR
  • I've run make pre-commit and confirm it didn't generate any warnings/changes
  • I've run make test, I confirm all tests passed locally
  • I've added/updated any relevant documentation in the docs/ folder
  • I've linked this PR with an open issue
  • I've tested and verified that my code works as intended and resolves the issue as described
  • I have attached screenshots demonstrating my code works as intended
  • I've checked all other open PRs to avoid submitting duplicate work
  • I confirm that the code and comments in this PR are not direct unreviewed outputs of AI
  • I confirm that I am the Sole Responsible Author for every line of code, comment, and design decision

Raavi29 added 6 commits March 25, 2026 08:21
- Tests weak algorithms: sha1, md5, md2, md4
- Tests case insensitivity (uppercase input)
- Tests safe algorithms: sha256, sha512, sha384
- Tests edge cases: empty string, random string
- All 11 tests passing

Part of improving test coverage for GSoC 2026
- TestIsSingleIPv4: 12 tests for IPv4 address validation
- TestIsSingleIPv6: 10 tests including None bug documentation
- TestIsIPv4Range: 8 tests (documents naming swap with is_ipv4_cidr)
- TestIsIPv4CIDR: 7 tests (documents naming swap with is_ipv4_range)
- TestIsIPv6Range: 6 tests for IPv6 dash-range detection
- TestIsIPv6CIDR: 8 tests for IPv6 CIDR detection
- TestGenerateIPRange: 7 tests covering both code branches
- TestGetIPRange: 4 tests using unittest.mock for HTTP isolation

Coverage: nettacker/core/ip.py 0% -> 83%
Note: is_ipv4_range/is_ipv4_cidr and is_ipv6_range/is_ipv6_cidr
appear to have swapped names - documented in test docstrings
CVE-2025-64446 is a critical (CVSS 9.8) relative path traversal in
Fortinet FortiWeb WAF versions 8.0.1 and earlier. Unauthenticated
attackers can traverse from /api/v2.0/ into the internal CGI handler
to create admin accounts without credentials.

Actively exploited since October 2025, added to CISA KEV catalog
November 14 2025, fixed in FortiWeb 8.0.2.

Detection sends a GET request to the traversal path and checks for
200 response or FortiWeb-specific content in the response body.
@coderabbitai

coderabbitai Bot commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 24761304-2158-4916-9dfa-50cae38c3254

📥 Commits

Reviewing files that changed from the base of the PR and between 35cf8ef and 77431d7.

📒 Files selected for processing (1)
  • docs/Modules.md
✅ Files skipped from review due to trivial changes (1)
  • docs/Modules.md

Summary by CodeRabbit

  • New Features

    • Added detection module for Fortinet FortiWeb CVE-2025-64446, a critical path traversal and unauthenticated admin bypass vulnerability (CVSS 9.8).
  • Documentation

    • Updated documentation to include the new vulnerability detection module.

Walkthrough

A new vulnerability module for FortiWeb CVE-2025-64446 is introduced alongside documentation updates. The module detects a path traversal authentication bypass via HTTP requests across multiple ports and protocols.

Changes

Cohort / File(s) Summary
New Vulnerability Module
nettacker/modules/vuln/fortiweb_cve_2025_64446.yaml
Introduces FortiWeb CVE-2025-64446 vulnerability check. Defines HTTP payload with path traversal (../../../..) targeting /cgi-bin/fwbcgi endpoint. Tests against ports 80, 443, 8443 across http/https. Validates exploitation via HTTP 200 status and response content matching super_admin|privilege|fwbcgi.
Documentation Update
docs/Modules.md
Added entry for new fortiweb_cve_2025_64446_vuln module describing the CVE with CVSS 9.8 severity and unauthenticated admin bypass context.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested labels

new module, documentation

Suggested reviewers

  • arkid15r
  • securestep9
🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: adding a new FortiWeb CVE-2025-64446 vulnerability module.
Description check ✅ Passed The description comprehensively details the CVE, its impact, how detection works, and provides relevant references—all directly related to the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
tests/core/lib/test_ssl.py (1)

10-58: Please restore targeted tests for get_cert_info to avoid SSL coverage regression.

This file now validates only is_weak_hash_algo, while nettacker/core/lib/ssl.py (Line 130-152) still contains non-trivial cert parsing/date computations (activation_date, expiring_soon, not_activated) that should remain tested.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/core/lib/test_ssl.py` around lines 10 - 58, Restore unit tests that
target get_cert_info in nettacker/core/lib/ssl.py: add focused tests for the
function get_cert_info that validate certificate parsing and the date-based
flags activation_date, expiring_soon, and not_activated; create minimal
certificate fixtures (or mock the parsed cert structure) for the following cases
— already expired, not yet active, expiring within the threshold, and valid
long-lived — and assert the returned activation_date, expiry date parsing and
boolean flags match expectations; ensure tests reference get_cert_info and
exercise the code paths around activation_date, expiring_soon, and not_activated
so SSL-related coverage is preserved.
tests/test_ip.py (1)

261-296: get_ip_range success path is documented but not tested.

The docstring (Lines 264-266) says successful API behavior should be validated, but current tests only assert fallback/error paths. Please add one happy-path test with mocked RIPE response to lock in expected parsing behavior.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/test_ip.py` around lines 261 - 296, Add a happy-path unit test for
get_ip_range that mocks nettacker.core.ip.requests.get to return a successful
RIPE-style JSON payload and asserts the parsed result matches the expected list;
specifically, patch requests.get to return an object whose .content is the RIPE
API JSON string (matching the structure your production code parses), call
get_ip_range("x.x.x.x") and compare the return to the expected output (either by
calling generate_ip_range("x.x.x.x") or a hard-coded list), and ensure the test
imports/uses the same get_ip_range and generate_ip_range symbols so it validates
the success parsing path rather than only fallback behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@nettacker/modules/vuln/fortiweb_cve_2025_64446.yaml`:
- Around line 48-55: The rule currently uses condition_type: or so a match is
true if either status_code or content matches, which causes false positives due
to the broad "FortiWeb" token; change the logic to require both a valid HTTP
response and a fingerprint by setting condition_type to and and/or tighten the
content regex to require stronger indicators (e.g., combine tokens with
lookahead or require "fwbcgi" or "admin.*privilege" together with "FortiWeb") so
the rule only fires when status_code and content both match; update the YAML
fields condition_type, conditions -> status_code.regex, and conditions ->
content.regex accordingly.

In `@tests/test_ip.py`:
- Around line 1-296: The test file is placed at tests/test_ip.py but should
mirror the package layout; move this file to tests/core/test_ip.py so it aligns
with the module under test (nettacker.core.ip) and the project's test layout;
ensure the file name and imports (e.g., references to generate_ip_range,
get_ip_range, is_single_ipv4, etc.) remain unchanged after moving so pytest
discovery still runs the same tests.
- Around line 93-97: The test test_none_raises is too broad by catching
(TypeError, Exception); update the pytest.raises call in the test_none_raises
function to only expect TypeError so that only the documented failure from
is_single_ipv6(None) is accepted (replace the tuple with the single TypeError
exception).

---

Nitpick comments:
In `@tests/core/lib/test_ssl.py`:
- Around line 10-58: Restore unit tests that target get_cert_info in
nettacker/core/lib/ssl.py: add focused tests for the function get_cert_info that
validate certificate parsing and the date-based flags activation_date,
expiring_soon, and not_activated; create minimal certificate fixtures (or mock
the parsed cert structure) for the following cases — already expired, not yet
active, expiring within the threshold, and valid long-lived — and assert the
returned activation_date, expiry date parsing and boolean flags match
expectations; ensure tests reference get_cert_info and exercise the code paths
around activation_date, expiring_soon, and not_activated so SSL-related coverage
is preserved.

In `@tests/test_ip.py`:
- Around line 261-296: Add a happy-path unit test for get_ip_range that mocks
nettacker.core.ip.requests.get to return a successful RIPE-style JSON payload
and asserts the parsed result matches the expected list; specifically, patch
requests.get to return an object whose .content is the RIPE API JSON string
(matching the structure your production code parses), call
get_ip_range("x.x.x.x") and compare the return to the expected output (either by
calling generate_ip_range("x.x.x.x") or a hard-coded list), and ensure the test
imports/uses the same get_ip_range and generate_ip_range symbols so it validates
the success parsing path rather than only fallback behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e8722bb8-3d40-412a-959a-9af1df0dfdf2

📥 Commits

Reviewing files that changed from the base of the PR and between f4c1bbf and 56f92f6.

📒 Files selected for processing (3)
  • nettacker/modules/vuln/fortiweb_cve_2025_64446.yaml
  • tests/core/lib/test_ssl.py
  • tests/test_ip.py

Comment thread nettacker/modules/vuln/fortiweb_cve_2025_64446.yaml Outdated
Comment thread tests/test_ip.py Outdated
Comment thread tests/test_ip.py Outdated
Raavi29 added 3 commits April 2, 2026 16:20
…egex

Addresses CodeRabbit feedback - using OR with broad FortiWeb token
could cause false positives on any FortiWeb response regardless of
vulnerability. Changed to AND requiring both HTTP 200 and specific
content (super_admin, privilege, fwbcgi) to confirm vulnerable endpoint.
- tests/test_ip.py already exists at tests/core/test_ip.py, removed duplicate
- tests/core/lib/test_ssl.py was accidentally stripped, restored 574-line original
@Raavi29

Raavi29 commented Apr 2, 2026

Copy link
Copy Markdown
Contributor Author

Latest commits: tightened response matching to condition_type: and with stricter regex, removed tests/test_ip.py duplicate, restored SSL test suite.

@securestep9

Copy link
Copy Markdown
Collaborator

@Raavi29 you have failed to follow the guidelines and PR checks - there is no screenshot evidence proving the module works, documentation is not updated and your commits are not digitally signed. I recommend you learn to sign your commits first! Unsigned commits cannot be accepted!

@Raavi29 Raavi29 closed this Apr 4, 2026
@Raavi29 Raavi29 reopened this Apr 4, 2026
@Raavi29

Raavi29 commented Apr 4, 2026

Copy link
Copy Markdown
Contributor Author

Closing this PR

I was not aware of PR #1240 (in draft) which covers the same vulnerability. Apologies for the duplicate. Will review open and draft PRs more carefully before submitting new modules.

@Raavi29 Raavi29 closed this Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants