DEV Community

ShowDoc 3.9.2 and the username field that ends up as PHP

ShowDoc 3.9.2 and the username field that ends up as PHP Chinese security firm QiAnXin published QVD-2026-61708 on 4 September 2026. The advisory covers ShowDoc, a documentation and API-definition tool that teams commonly run on an internal host. The flaw is an unauthenticated remote code execution issue in deployments backed by SQLite, and it is fixed in version 3.9.3. How a registration endpoint becomes a shell The vulnerable entry point is registerByVerify , a registration route that accepts a verification code and creates a user account without a session. ShowDoc validates the submitted username by trimming whitespace and then storing it. Any character that survives the trim is written into the account record. In SQLite deployments that record lives in a file named Sqlite/showdoc.db.php , which sits under the web root and carries a .php extension. The file is designed to open with a guard that stops direct requests from leaking database contents, but the trick is the same one that has broken PHP applications for two decades. If attacker input can be written into the file body, the guard only covers the header, and a request for the file hands the rest of the content to the PHP interpreter. A username that contains PHP tags therefore becomes executable code the moment the file is requested over HTTP. The advisory describes the result as arbitrary command execution with the privileges of the web server user, which also means database tampering and a convenient place to keep a webshell. Two conditions make this reliable rather than theoretical. The registration route carries no authentication, and the database file is reachable at a predictable path. Neither requires a misconfiguration beyond accepting the default layout. Exposure and the shape of the number Eagle Map telemetry cited in the advisory counts 20,491 related risk assets across 4,866 IP addresses, all in China. That is a fingerprint-based count from one mapping platform and the advisory does not publish the query behind it. It shows scale, and it does not tell you which of those hosts run SQLite rather than MySQL, which matters here because the MySQL backend does not put a PHP file in the web root. Fixes and interim measures The clean fix is to upgrade to ShowDoc 3.9.3 or later, where the username field is validated against an allowlist and the character set that reaches the database is restricted. Release builds are published on the project's GitHub releases page. If the upgrade has to wait, the advisory lists three measures that each break the chain. Close registration by setting register_open to 0 in the options table, so the vulnerable route cannot be reached at all. Add a deny rule in Nginx for the /Sqlite/ directory, so the database file is never served by PHP even if it contains unexpected content. Move the SQLite file out of the web root, for example into a path outside the served tree, or add a byte-order guard at the head of the file. Where the deployment allows it, switching to MySQL removes this particular sink entirely. Detection notes Because the payload is stored before it is executed, the artifact persists. Review new rows in the user table, look for usernames that contain angle brackets or PHP open tags in the database file, and check the web server log for requests to a path ending in showdoc.db.php . Those three checks cover the write, the stored evidence, and the trigger. Limits The advisory does not report exploitation in the wild, and no public report ties it to a specific intrusion. Whether a given instance is affected depends on the database backend and on whether registration is open to unauthenticated callers. References - QiAnXin CERT, ShowDoc registerByVerify unauthenticated remote code execution advisory (QVD-2026-61708): https://www.secrss.com/articles/93694 - ShowDoc releases, version 3.9.3 and later: https://github.com/star7th/showdoc/releases Top comments (0)

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.