Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
phpmyadmin-csrf-sql — phpMyAdmin 5.2.3 - High - Remote - CSRF - token strip on /sql | Kitploit
Tools/GitHubGitHub/abraxas/phpmyadmin-csrf-sql
Vulnerability AnalysisExploitationWeb Application ExploitationWeb SecurityPenetration TestingLabs & Practice
GitHubabraxas/phpmyadmin-csrf-sql

phpmyadmin-csrf-sql

phpMyAdmin 5.2.3 - High - Remote - CSRF - token strip on /sql

View Repository
4 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Abraxas Labs - phpmyadmin-csrf-sql

abraxaslabs.tech  ·  github.com/abraxas  ·  @abraxas_null  ·  [email protected]  ·  phpmyadmin-csrf-sql

phpmyadmin-csrf-sql

Class: CSRF Reach: Remote

phpMyAdmin 5.2.3 (tag RELEASE_5_2_3, commit 962857e). Common.php builds the PSR-7 request from globals before checkTokenRequestParam. On mismatch, Sanitize::removeRequestVars clears $_POST and $_GET but not that snapshot. $sql_query is then copied from $request->getParsedBodyParam('sql_query'). AJAX POSTs abort on token mismatch. Non-AJAX POSTs continue. SqlController prefers stripped $_POST['sql_query'] and otherwise keeps the global.

A victim with a phpMyAdmin session cookie is enough. POST index.php?route=/sql with sql_query and no valid token, and without ajax_request. The SELECT runs as that MySQL user. Default CookieSameSite=Strict in 5.2.3 blocks many cross-site browsers. Same-site, Lax, None, or HTTP-auth still hit it. This is a broken CSRF control either way.

IDno CVE yet
ClassCSRF
ReachRemote. Default CookieSameSite=Strict blocks many cross-site browsers. Same-site / Lax / None / HTTP-auth remain.
CWECWE-352
CVSSHigh: 8.1 CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:H/A:N
ProductphpMyAdmin
Affected5.2.3 tag RELEASE_5_2_3 (962857e)
AuthVictim phpMyAdmin session cookie (or HTTP auth). No valid CSRF token.
LicenseGNU Affero GPL v3.0
Lab127.0.0.1:19240 only

What an attacker can do

Anyone who can cause the victim browser to POST to phpMyAdmin without ajax_request can run SQL as that MySQL user.

PrivilegeMethod / pathLab-proven or inferred
Run attacker SQL as the victim MySQL account (integrity + recon of that SQL box)POST index.php?route=/sql sql_query=... db=... no token, no ajax_requestLab-proven. Results body contained PMA-CSRF-SQL-WITNESS. General log showed the SELECT as appuser
Abort the same handler on AJAXSame POST with ajax_request=1Lab-proven. Token mismatch. INSERT marker row absent. General log did not run that INSERT
Skip handlers that only read stripped $_POSTPOST /database/structure/drop-table without a tokenLab-proven. keepme still present
Same gap on export (SaveDir), partition DROP/TRUNCATE, account lock, /config/set, pmadb createAny handler that reads the PSR-7 body after the stripInferred. Not exercised

Closed on this lab: unauthenticated PMA (cookie login required first), AJAX routes (they exit on mismatch), drop-table without a token, OS shell. Default Strict SameSite means a classic cross-site form often will not send the cookie; the leftover is still a failed CSRF check on same-site and on Lax/None deploys.

How I found it

Eight parallel source hunts of RELEASE_5_2_3. Common.php creates $request = createFromGlobals() before checkTokenRequestParam(). On mismatch, Sanitize::removeRequestVars() clears $_POST/$_GET only. Non-AJAX continues. SqlController uses global $sql_query if $_POST is empty. Route GET|POST /sql.

Wrong turns: treating AJAX /sql as the leftover (it aborts Token mismatch); treating drop-table as the leftover (that handler only reads stripped $_POST); treating default Strict SameSite as "CSRF is closed" (the control is still broken; same-site / Lax / None remain).

Lab

python3 phpmyadmin-csrf-sql-Abraxas-Labs.py

or

cd lab
./run.sh

Loopback only: http://127.0.0.1:19240. Images phpmyadmin:5.2.3 and mysql:8.0. Compose project phpmyadmin-csrf-sql. The PoC is a same-site loopback POST (Strict SameSite still sends the cookie). Witness PMA-CSRF-SQL-WITNESS.

SUCCESS phpmyadmin-csrf-sql sql-ran=yes ajax-abort=yes drop-held=yes PMA-CSRF-SQL-WITNESS

The fix

On mismatch, replace the request with an empty body, or refuse all POSTs, not only AJAX. Do not copy sql_query from a stale request. Fail closed like logout.

References

  • github.com/phpmyadmin/phpmyadmin tag RELEASE_5_2_3 (962857e)
  • libraries/classes/Common.php request snapshot before token strip
  • Sanitize::removeRequestVars clears $_POST/$_GET only
  • SqlController global $sql_query
  • Same pin leftovers: phpmyadmin-webauthn · phpmyadmin-pmadb-central-sqli · phpmyadmin-designer-json-sqli · phpmyadmin-setup-validate
  • CWE-352

License

GNU Affero GPL v3.0. See LICENSE. Loopback lab only. No warranty.

Download Tool