feat(vulnerability): add detection module for CVE-2025-24813 (Apache …#1368
feat(vulnerability): add detection module for CVE-2025-24813 (Apache …#1368PhucQuan wants to merge 3 commits intoOWASP:masterfrom
Conversation
…Tomcat RCE). Signed-off-by: PhucQuan <153093559+PhucQuan@users.noreply.github.com>
Summary by CodeRabbit
WalkthroughAdds a new YAML vulnerability module that detects CVE-2025-24813 in Apache Tomcat via a two-step HTTP probe: a partial PUT to test DefaultServlet writeability and a subsequent GET with a JSESSIONID to detect deserialization error indicators. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Suggested labels
Suggested reviewers
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml (1)
49-63: Pair scheme and port instead of fuzzing the full matrix.
nettacker_fuzzerexpands these arrays as a Cartesian product, so this definition probeshttp://…:443,https://…:80, etc. on every host. That is 10 URLs per step and 20 requests total, most of which are avoidable noise or timeouts. Consider encoding only realistic pairs or separate payload entries for the common defaults.Also applies to: 78-92
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines 49 - 63, The nettacker_fuzzer currently uses independent arrays data.schema and data.ports which are expanded as a Cartesian product via input_format (producing mismatched pairs like http:443); update the fuzzer to supply only realistic scheme/port pairs instead of separate schema and ports arrays—either replace data.schema and data.ports with a single list of paired entries (e.g., entries that bind "http"→80, "https"→443, "http"→8080, etc.) or create separate nettacker_fuzzer payloads each with a fixed input_format and a single port/schema combo; modify the YAML under nettacker_fuzzer (refer to input_format, data.schema, data.ports) accordingly so only intended host:port scheme combinations are probed.
🤖 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/apache_tomcat_cve_2025_24813_vuln.yaml`:
- Around line 18-21: The probe currently performs a mutating PUT to a fixed path
'/nettacker.session' and follows with a GET using 'JSESSIONID=.nettacker', but
the module metadata claims "safe, non-destructive" and "No actual
deserialization is triggered" which is inaccurate; change the check to be
non-mutating (e.g., replace the PUT with a non-destructive probe such as a
conditional HEAD/OPTIONS or a harmless probe that only checks allowed methods),
or if you must keep the write-prerequisite test, switch the PUT target to a
randomized artifact name (append a strong random suffix to '/nettacker.session')
and implement best-effort cleanup (issue a DELETE or overwrite cleanup request
after the test) and update the YAML description field to clearly state that the
probe may create/modify a session artifact and could exercise session-loading
paths (remove the absolute "No actual deserialization is triggered" claim);
update references to the GET that uses 'JSESSIONID=.nettacker' to use the
randomized cookie or avoid triggering session load.
- Around line 1-98: Commit signatures are missing on this PR so pre-merge checks
will fail; re-sign commits and force-push the branch. If only the last commit
needs signing, run git commit --amend -S --no-edit && git push
--force-with-lease; if multiple commits, interactively rebase and sign each (git
rebase -i --exec "git commit --amend -S --no-edit" <base>) then git push
--force-with-lease. Ensure the branch contains only signed commits before
merging and remind contributors to always use signed commits for Nettacker PRs.
- Around line 14-17: The "Affected versions" metadata in
nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml is missing Tomcat
8.5.x; update the Affected versions section to include the 8.5 range (e.g.,
"Apache Tomcat 8.5.x: 8.5.0 to 8.5.100") OR add a brief explanatory note in the
YAML (near the Affected versions or description fields) explicitly stating that
EOL branches were intentionally excluded and linking to the NVD/CVE reference;
edit the "Affected versions" block or the description/reference field
accordingly so the omission is not ambiguous.
- Around line 6-21: Step 2 (the check that matches status_code: ^500$) is too
generic and must be changed: either remove Step 2 and mark the module as a
prerequisite-only detector that only verifies DefaultServlet write-enabled via
the partial PUT 201/204 check, or strengthen Step 2 to look for Tomcat-specific
deserialization signatures instead of any 500. If you strengthen it, replace the
generic status_code: ^500$ rule with combined assertions that match Tomcat error
bodies/headers (e.g., response body regexes for
"java.lang.ClassNotFoundException", "java.io.NotSerializableException",
"java.lang.ArithmeticException" stack traces referencing org.apache.catalina or
session persistence classes, and Server/Servlet container headers like
"Apache-Coyote" or "Apache Tomcat") and keep status 500 only as a secondary
condition; also update the module description to reflect whether it is
prerequisite-only or confirms Tomcat session-deserialization evidence.
---
Nitpick comments:
In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml`:
- Around line 49-63: The nettacker_fuzzer currently uses independent arrays
data.schema and data.ports which are expanded as a Cartesian product via
input_format (producing mismatched pairs like http:443); update the fuzzer to
supply only realistic scheme/port pairs instead of separate schema and ports
arrays—either replace data.schema and data.ports with a single list of paired
entries (e.g., entries that bind "http"→80, "https"→443, "http"→8080, etc.) or
create separate nettacker_fuzzer payloads each with a fixed input_format and a
single port/schema combo; modify the YAML under nettacker_fuzzer (refer to
input_format, data.schema, data.ports) accordingly so only intended host:port
scheme combinations are probed.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 3cb89354-cdc1-427d-8d4f-e9aae20cc7df
📒 Files selected for processing (1)
nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml
| info: | ||
| name: apache_tomcat_cve_2025_24813_vuln | ||
| author: PhucQuan | ||
| severity: 9.8 | ||
| description: > | ||
| CVE-2025-24813 is a critical path equivalence vulnerability in Apache Tomcat's | ||
| partial PUT feature. When the DefaultServlet has write permissions enabled | ||
| (readonly=false) and partial PUT is supported (enabled by default), an attacker | ||
| can upload a malicious serialized Java object to a crafted filename containing | ||
| an internal dot (e.g. /uploads/nettacker.session). Tomcat internally converts | ||
| path separators to dots, storing the file where Tomcat's file-based session | ||
| persistence will later deserialize it. The attacker then sends a GET request | ||
| with Cookie: JSESSIONID=.nettacker to trigger deserialization and achieve RCE. | ||
| Affected versions: | ||
| - Apache Tomcat 9.x: 9.0.0.M1 to 9.0.98 | ||
| - Apache Tomcat 10.x: 10.1.0-M1 to 10.1.34 | ||
| - Apache Tomcat 11.x: 11.0.0-M1 to 11.0.2 | ||
| This module performs a safe, non-destructive detection by sending a partial PUT | ||
| request with a benign payload and checking if the server accepts it (HTTP 201/204), | ||
| which indicates the DefaultServlet has write permissions enabled — a required | ||
| prerequisite for exploitation. No actual deserialization is triggered. | ||
| reference: | ||
| - https://nvd.nist.gov/vuln/detail/CVE-2025-24813 | ||
| - https://tomcat.apache.org/security-9.html | ||
| - https://tomcat.apache.org/security-10.html | ||
| - https://tomcat.apache.org/security-11.html | ||
| - https://www.cisa.gov/known-exploited-vulnerabilities-catalog | ||
| profiles: | ||
| - vuln | ||
| - http | ||
| - apache | ||
| - critical_severity | ||
| - rce | ||
| - cve | ||
| - cve2025 | ||
| - cisa_kev | ||
|
|
||
| payloads: | ||
| - library: http | ||
| steps: | ||
| - method: put | ||
| timeout: 10 | ||
| headers: | ||
| User-Agent: "{user_agent}" | ||
| Content-Range: "bytes 0-3/10" | ||
| Content-Type: "application/octet-stream" | ||
| ssl: false | ||
| url: | ||
| nettacker_fuzzer: | ||
| input_format: "{{schema}}://{target}:{{ports}}/nettacker.session" | ||
| prefix: "" | ||
| suffix: "" | ||
| interceptors: | ||
| data: | ||
| schema: | ||
| - "http" | ||
| - "https" 10BC0 | ||
| ports: | ||
| - 80 | ||
| - 443 | ||
| - 8080 | ||
| - 8443 | ||
| - 8888 | ||
| data: "TEST" | ||
| response: | ||
| condition_type: and | ||
| conditions: | ||
| status_code: | ||
| regex: "^(201|204)$" | ||
| reverse: false | ||
| - method: get | ||
| timeout: 10 | ||
| headers: | ||
| User-Agent: "{user_agent}" | ||
| Cookie: "JSESSIONID=.nettacker" | ||
| ssl: false | ||
| url: | ||
| nettacker_fuzzer: | ||
| input_format: "{{schema}}://{target}:{{ports}}/" | ||
| prefix: "" | ||
| suffix: "" | ||
| interceptors: | ||
| data: | ||
| schema: | ||
| - "http" | ||
| - "https" | ||
| ports: | ||
| - 80 | ||
| - 443 | ||
| - 8080 | ||
| - 8443 | ||
| - 8888 | ||
| response: | ||
| condition_type: and | ||
| conditions: | ||
| status_code: | ||
| regex: "^500$" | ||
| reverse: false |
There was a problem hiding this comment.
@PhucQuan, please re-push with signed commits before merge.
Nettacker pre-merge checks fail if any commit in this PR is unsigned. If you only need to fix the latest commit: git commit --amend -S --no-edit && git push --force-with-lease; for multiple commits, rebase with signing enabled and force-push the rewritten branch.
Based on learnings: When reviewing any pull request in the OWASP/Nettacker repository, always remind the PR author to use signed commits and explicitly state that the PR fails pre-merge checks if any commits are unsigned.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines 1
- 98, Commit signatures are missing on this PR so pre-merge checks will fail;
re-sign commits and force-push the branch. If only the last commit needs
signing, run git commit --amend -S --no-edit && git push --force-with-lease; if
multiple commits, interactively rebase and sign each (git rebase -i --exec "git
commit --amend -S --no-edit" <base>) then git push --force-with-lease. Ensure
the branch contains only signed commits before merging and remind contributors
to always use signed commits for Nettacker PRs.
| This module performs a safe, non-destructive detection by sending a partial PUT | ||
| request with a benign payload and checking if the server accepts it (HTTP 201/204), | ||
| which indicates the DefaultServlet has write permissions enabled — a required | ||
| prerequisite for exploitation. No actual deserialization is triggered. |
There was a problem hiding this comment.
This probe mutates the target and is not the “safe, non-destructive” check the metadata promises.
A 201/204 here means the scanner has created or modified /nettacker.session, and the fixed probe name makes repeated scans collide with each other or with a real resource. The follow-up GET with JSESSIONID=.nettacker also appears to exercise the session-loading/deserialization path described for the RCE branch, so “No actual deserialization is triggered” is misleading. Please either keep this module to the write-prerequisite check only, or switch to a randomized artifact with best-effort cleanup and update the description to reflect the side effects. The deserialization point is an inference from the official RCE preconditions plus this crafted session probe. (tomcat.apache.org)
Also applies to: 41-64, 71-76
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines
18 - 21, The probe currently performs a mutating PUT to a fixed path
'/nettacker.session' and follows with a GET using 'JSESSIONID=.nettacker', but
the module metadata claims "safe, non-destructive" and "No actual
deserialization is triggered" which is inaccurate; change the check to be
non-mutating (e.g., replace the PUT with a non-destructive probe such as a
conditional HEAD/OPTIONS or a harmless probe that only checks allowed methods),
or if you must keep the write-prerequisite test, switch the PUT target to a
randomized artifact name (append a strong random suffix to '/nettacker.session')
and implement best-effort cleanup (issue a DELETE or overwrite cleanup request
after the test) and update the YAML description field to clearly state that the
probe may create/modify a session artifact and could exercise session-loading
paths (remove the absolute "No actual deserialization is triggered" claim);
update references to the GET that uses 'JSESSIONID=.nettacker' to use the
randomized cookie or avoid triggering session load.
… (CVSS 9.8, CISA KEV). Detection via partial PUT to session dir (HTTP 409) + GET with crafted JSESSIONID to trigger deserialization (HTTP 500). Signed-off-by: PhucQuan <153093559+PhucQuan@users.noreply.github.com>
| status_code: | ||
| regex: "^500$" | ||
| reverse: false | ||
| body: |
There was a problem hiding this comment.
There is no field named "body" , Please correct it to "content" .
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 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/apache_tomcat_cve_2025_24813_vuln.yaml`:
- Around line 116-124: The response condition is using the unrecognized key
"body" so the regex is ignored; update the "response.conditions.body" entry to
use the supported key "content" (preserving the existing regex and reverse flag)
so the payload pattern
"ClassNotFoundException|InvalidClassException|StreamCorruptedException|deserializ|java\\.io"
is applied (i.e., change the block under response -> conditions -> body to
response -> conditions -> content while keeping regex and reverse values).
- Around line 100-115: The two separate nettacker_fuzzer blocks (input_format in
both steps) can pick different schema:port combos and break the exploit chain;
change Step 1 to record the exact executed endpoint and make Step 2 depend on it
by adding dependent_on_temp_event to Step 2 (or move the nettacker_fuzzer to the
shared payload level so both steps use the same fuzzer expansion). Concretely,
update the Step 1 definition that uses nettacker_fuzzer to emit/save the
resolved endpoint (host:port with schema) into a temp event, then in the Step 2
block replace its nettacker_fuzzer input with a reference to that temp event via
dependent_on_temp_event so Step 2 reuses the exact endpoint Step 1 used
(alternatively, collapse nettacker_fuzzer into the payload definition so both
steps inherit the same expansion).
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d14be2df-b605-424f-857a-3bb15570478e
📒 Files selected for processing (1)
nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml
…ing note Signed-off-by: PhucQuan <153093559+PhucQuan@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (3)
nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml (3)
57-59:⚠️ Potential issue | 🔴 CriticalStep 2 still is not bound to Step 1’s resolved endpoint.
The comments say the fuzzer is shared at payload level, but both steps still declare independent
url.nettacker_fuzzerblocks. On targets exposing multiple schemes/ports, the PUT can land on one endpoint while the GET probes another, which breaks the chain and can misclassify hosts. Reuse Step 1’s resolved URL in Step 2 via a temp-event dependency instead of re-fuzzing there.Also applies to: 72-88, 95-121
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines 57 - 59, The two steps both declare independent url.nettacker_fuzzer blocks so Step 2 can re-resolve a different scheme/port than Step 1; instead make Step 2 consume Step 1’s resolved URL via a temp-event dependency (e.g., have Step 1 emit the resolved URL into a temp event and change Step 2 to read that temp-event value instead of declaring its own url.nettacker_fuzzer), remove the duplicate url.nettacker_fuzzer in Step 2, and update the payload references so Step 2 uses the Step1 temp-event variable for the target URL.
20-31:⚠️ Potential issue | 🟠 MajorRandomize the session artifact name.
The updated mutating note is accurate, but the fixed
f3b2a19d4cID makes repeated or concurrent scans against the same host share state. A leftover partial file can influence later runs, and Step 2 will also target that stale artifact via the hardcoded cookie. Generate a per-run suffix and thread it through both the PUT path andJSESSIONID, with best-effort cleanup if the engine supports it.Also applies to: 74-88, 104-104
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines 20 - 31, Replace the hardcoded session artifact name "f3b2a19d4c.session" and the fixed JSESSIONID value with a per-run randomized suffix so each scan uses a unique artifact; ensure the generated suffix is used consistently in the PUT path (the uploads/../sessions/<ID>.session partial PUT) and in the Cookie header (JSESSIONID=<ID>) for Step 1 and Step 2, and add a best-effort cleanup attempt to remove the leftover partial file after the scan completes if the engine supports cleanup.
1-130:⚠️ Potential issue | 🟠 Major@PhucQuan, please make sure every commit in this PR is signed before merge.
Nettacker pre-merge checks fail if any commit is unsigned. If only the latest commit needs fixing,
git commit --amend -S --no-edit && git push --force-with-leaseis enough; otherwise, rebase-sign each commit and force-push the rewritten branch.Based on learnings: When reviewing any pull request in the OWASP/Nettacker repository, always remind the PR author to use signed commits and explicitly state that the PR fails pre-merge checks if any commits are unsigned.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines 1 - 130, The PR contains unsigned commits (author PhucQuan) which will fail Nettacker pre-merge checks; fix by signing every commit in this branch: if only the latest commit is unsigned, amend it to add a GPG signature and force-push the branch; if multiple commits are unsigned, perform an interactive rebase and sign each commit, then force-push the rewritten branch with lease so the branch history is updated with signed commits.
🤖 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/apache_tomcat_cve_2025_24813_vuln.yaml`:
- Around line 69-70: The YAML currently contains a payload expressed as a
quoted/escaped string which YAML parses as text and causes UTF-8 re-encoding;
replace that escaped-string payload with a true binary value (use the YAML
!!binary tag with the base64-encoded Java serialization bytes, or a literal
binary block) so Nettacker/aiohttp receives raw bytes unchanged; update the
payload field in apache_tomcat_cve_2025_24813_vuln.yaml (the serialized Java
payload entry) to the binary form and keep the Content-Range header consistent
with the actual byte length.
---
Duplicate comments:
In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml`:
- Around line 57-59: The two steps both declare independent url.nettacker_fuzzer
blocks so Step 2 can re-resolve a different scheme/port than Step 1; instead
make Step 2 consume Step 1’s resolved URL via a temp-event dependency (e.g.,
have Step 1 emit the resolved URL into a temp event and change Step 2 to read
that temp-event value instead of declaring its own url.nettacker_fuzzer), remove
the duplicate url.nettacker_fuzzer in Step 2, and update the payload references
so Step 2 uses the Step1 temp-event variable for the target URL.
- Around line 20-31: Replace the hardcoded session artifact name
"f3b2a19d4c.session" and the fixed JSESSIONID value with a per-run randomized
suffix so each scan uses a unique artifact; ensure the generated suffix is used
consistently in the PUT path (the uploads/../sessions/<ID>.session partial PUT)
and in the Cookie header (JSESSIONID=<ID>) for Step 1 and Step 2, and add a
best-effort cleanup attempt to remove the leftover partial file after the scan
completes if the engine supports cleanup.
- Around line 1-130: The PR contains unsigned commits (author PhucQuan) which
will fail Nettacker pre-merge checks; fix by signing every commit in this
branch: if only the latest commit is unsigned, amend it to add a GPG signature
and force-push the branch; if multiple commits are unsigned, perform an
interactive rebase and sign each commit, then force-push the rewritten branch
with lease so the branch history is updated with signed commits.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: c23aa2a9-2df8-410c-a09a-fce0f49122fc
📒 Files selected for processing (1)
nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml
| Content-Type: "application/octet-stream" | ||
| Content-Range: "bytes 0-54/100" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify Nettacker forwards YAML `data` directly to aiohttp without converting it to bytes.
sed -n '1,35p' nettacker/core/lib/http.py
sed -n '139,186p' nettacker/core/lib/http.pyRepository: OWASP/Nettacker
Length of output: 2839
🌐 Web query:
In aiohttp's client API, when ClientSession.request(..., data=) is used, is the body UTF-8 encoded before sending, and what is the supported way to send an exact raw binary request body instead?
💡 Result:
Yes. If you pass a Python str as the request body (e.g. ClientSession.request(..., data="...")), aiohttp turns it into a StringPayload and encodes it to bytes using the charset from the request Content-Type header, defaulting to UTF‑8 if no charset is specified. [2] (This is also reflected in aiohttp’s request-body handling docs: str is “Text data (encoded using charset from Content-Type)”. [1])
To send an exact raw binary body (no text encoding step), the supported approach is to pass bytes-like data instead, e.g.:
await session.request("POST", url, data=b"\x00\xff\x01...")
# or: bytearray(...) / memoryview(...)aiohttp treats bytes/bytearray as raw binary data for the body. [1]
🏁 Script executed:
#!/bin/bash
# Find and show the send_request function that actually calls aiohttp
grep -n "async def send_request" nettacker/core/lib/http.py
# Show the section around the aiohttp.ClientSession call
rg "ClientSession|aiohttp.request" -A 10 nettacker/core/lib/http.py | head -50Repository: OWASP/Nettacker
Length of output: 467
🏁 Script executed:
#!/bin/bash
# Display the YAML vulnerability module file around the mentioned lines
cat -n nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml | sed -n '60,100p'Repository: OWASP/Nettacker
Length of output: 2053
🏁 Script executed:
#!/bin/bash
python3 << 'EOF'
import yaml
# Sample the YAML data value from line 88
yaml_str = r'''
data: "\xac\xed\x00\x05\x73\x72"
'''
parsed = yaml.safe_load(yaml_str)
data_value = parsed['data']
print(f"Type: {type(data_value)}")
print(f"Length: {len(data_value)}")
print(f"Repr: {repr(data_value)}")
print(f"Byte values: {[hex(ord(c)) for c in data_value[:8]]}")
# Simulate what aiohttp does: encode str as UTF-8
utf8_encoded = data_value.encode('utf-8')
print(f"\nAfter UTF-8 encoding:")
print(f"Type: {type(utf8_encoded)}")
print(f"Length: {len(utf8_encoded)}")
print(f"Hex: {utf8_encoded.hex()}")
EOFRepository: OWASP/Nettacker
Length of output: 246
The payload data must be binary, not a YAML-escaped string.
YAML parses "\xac\xed\x00\x05..." as a Python str of Unicode characters (e.g., ¬ for \xac, í for \xed). When Nettacker passes this str to aiohttp, aiohttp encodes it as UTF-8 before sending. This expands multi-byte characters: \xac becomes c2 ac (2 bytes), \xed becomes c3 ad (2 bytes), etc. The 55-byte Java serialization stream grows beyond 110 bytes, corrupting the binary structure and invalidating the Content-Range: bytes 0-54/100 header. The exploit payload will not deserialize.
Use binary encoding in the YAML (e.g., !!binary tag with base64, or escape as literal bytes) so Nettacker receives raw bytes, not a text string.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@nettacker/modules/vuln/apache_tomcat_cve_2025_24813_vuln.yaml` around lines
69 - 70, The YAML currently contains a payload expressed as a quoted/escaped
string which YAML parses as text and causes UTF-8 re-encoding; replace that
escaped-string payload with a true binary value (use the YAML !!binary tag with
the base64-encoded Java serialization bytes, or a literal binary block) so
Nettacker/aiohttp receives raw bytes unchanged; update the payload field in
apache_tomcat_cve_2025_24813_vuln.yaml (the serialized Java payload entry) to
the binary form and keep the Content-Range header consistent with the actual
byte length.
…Tomcat RCE).
Proposed change
Added a new vulnerability module for CVE-2025-24813. This module performs a safe detection for Apache Tomcat Path Equivalence RCE. Verified the logic against documentation and CISA KEV requirements.
Type of change
Checklist
make pre-commitand confirm it didn't generate any warnings/changesmake test, I confirm all tests passed locallydocs/folder