Skip to content

fix(CVE-2023-5652): reduce false positives with differential timing detection#15954

Open
Eren-Akdag wants to merge 2 commits intoprojectdiscovery:mainfrom
Eren-Akdag:fix/CVE-2023-5652-false-positive
Open

fix(CVE-2023-5652): reduce false positives with differential timing detection#15954
Eren-Akdag wants to merge 2 commits intoprojectdiscovery:mainfrom
Eren-Akdag:fix/CVE-2023-5652-false-positive

Conversation

@Eren-Akdag
Copy link
Copy Markdown
Contributor

PR Information


Problem

The original template uses a single SLEEP(8) request and checks duration >= 8 as the primary detection condition. On targets where wp-admin/admin-ajax.php has a naturally high baseline response time, occasional server-side latency spikes can push the response above 8 seconds without SLEEP(8) ever executing — producing a false positive.

This endpoint always returns HTTP 400, body 0, Content-Type: text/html regardless of whether SQL injection occurs. This means the non-timing conditions (status_code, body, content_type) provide no exploitation signal on their own. The detection relies entirely on duration >= 8, making it vulnerable to server latency noise.

Root Cause — Empirical Evidence

To confirm, identical requests were sent varying only the SLEEP value, measuring response time for each:

Payload Measured Time Expected if SLEEP Executing
Baseline (no payload) 4.40s
SLEEP(0) 5.32s ~4.4s
SLEEP(3) 4.19s ~7.4s
SLEEP(8) 4.25s ~12.4s
SLEEP(15) 3.77s ~19.4s

Timing does not scale with the SLEEP value. SLEEP(15) and SLEEP(0) return in virtually identical time — SLEEP is not executing. The duration >= 8 condition was satisfied purely by server latency.

Despite this, the original template fired a finding when the server spiked to ~13s:

[CVE-2023-5652:dsl-1] [http] [critical] https://REDACTED/wp-admin/admin-ajax.php
[INF] Scan completed in 13.18s. 1 matches found.

Re-running the same scan seconds later with no change to the target:

[INF] Scan completed in 4.38s. No results found.

Classic false positive — the finding does not reproduce reliably.


Fix — Differential Timing Detection

Instead of measuring absolute response time, this fix sends a SLEEP(0) request first to establish a per-target baseline, then compares the SLEEP(8) response against it. The key matcher is:

duration_2 >= duration_1 + 6

This requires the SLEEP(8) request to take at least 6 seconds more than the SLEEP(0) baseline on the same endpoint. No amount of server latency can satisfy this condition unless SLEEP actually executes, because both requests are subject to the same server conditions.

Scenario duration_1 duration_2 d2 >= d1 + 6 Outcome
Slow server, no SQLi (FP case) ~4s ~4s 4 >= 10 → ✗ Blocked
Slow server + SQLi (TP case) ~4s ~12s 12 >= 10 → ✓ Fires
Fast server + SQLi (TP case) ~0.5s ~8.5s 8.5 >= 6.5 → ✓ Fires
Both requests spike (FP case) ~9s ~9s 9 >= 15 → ✗ Blocked

The duration_2 >= 8 absolute check is retained as a secondary safety net for fast servers.

Diff summary:

- - 'duration>=8'
- - 'regex("^0$", body)'
- - 'status_code == 400'
- - 'contains(content_type, "text/html")'

+ - 'duration_2 >= 8'
+ - 'duration_2 >= duration_1 + 6'
+ - 'regex("^0$", body_2)'
+ - 'status_code_2 == 400'
+ - 'contains(content_type_2, "text/html")'

Template validation

  • Validated with a host running a vulnerable version and/or configuration (True Positive)
  • Validated with a host running a patched version and/or configuration (avoid False Positive)

Additional Details

False positive confirmed (original template, non-vulnerable host):

POST /wp-admin/admin-ajax.php HTTP/1.1
Host: REDACTED
Content-Type: application/x-www-form-urlencoded; charset=UTF-8

action=x&taxonomy=hb_room_type&hb_room_type_ordering[1]=0 END, name=(SELECT SLEEP(8)), term_id=CASE when 1=1 THEN 1

HTTP/1.1 400 Bad Request
Content-Type: text/html; charset=UTF-8
Content-Length: 1

0

[CVE-2023-5652:dsl-1] [http] [critical] https://REDACTED/wp-admin/admin-ajax.php
Scan completed in 13.18s. 1 matches found.

Fixed template — no finding on same host:

[INF] Scan completed in 9.43s. No results found.

Differential check correctly blocked: duration_2 (4.8s) >= duration_1 (4.3s) + 64.8 >= 10.3 → ✗


Additional References

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FALSE-POSITIVE] CVE-2023-5652

2 participants