CVE-2026-56738
phpMyFAQ has SQL Injection in `StopWords::add()` — Unescaped Stop Word Insertion
phpMyFAQ is an open source FAQ web application. The StopWords::add() method inversions prior to 4.1.6 builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path. An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database. Version 4.1.6 fixes the issue.
Attack profile
How easy it is to exploit
- Attack vector
- Network
- Complexity
- Low
- Privileges needed
- High
- User interaction
- None
What an attacker can affect
- Confidentiality
- High
- Integrity
- High
- Availability
- None
Exploit likelihood
What each source reports
CVE List Score used
8.5
phpMyFAQ has SQL Injection in `StopWords::add()` — Unescaped Stop Word Insertion
phpMyFAQ is an open source FAQ web application. The StopWords::add() method inversions prior to 4.1.6 builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path. An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database. Version 4.1.6 fixes the issue.
- Record
CVE-2026-56738- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-89
- Updated
- 2026-11-02
EUVDEUVD-2026-86289
8.5
phpMyFAQ is an open source FAQ web application. The StopWords::add() method inversions prior to 4.1.6 builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path. An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database. Version 4.1.6 fixes the issue.
- Record
EUVD-2026-86289- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Updated
- 2026-11-02
GitHub AdvisoriesGHSA-rw77-vq4g-x3hp
8.5
phpMyFAQ has SQL Injection in `StopWords::add()` — Unescaped Stop Word Insertion
Summary
The StopWords::add() method in phpMyFAQ builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path.
An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database.
Affected Code
File: phpmyfaq/src/phpMyFAQ/StopWords.php
Method: add() (approx. lines 60–75 in the audited revision)
$sql = sprintf(
"INSERT INTO %s VALUES(%d, '%s', '%s')",
$this->getTableName(),
$id,
$this->configuration->getDb()->escape($this->language), // language IS escaped
$word // <-- $word is NOT escaped
);
$word is taken directly from the administrative form input (the new stop word to add) and concatenated into the SQL string via sprintf("'%s'", ...) with no call to the database driver's escape() method.
Contrast with the safe sibling method
Method: update() (line 82 in the audited revision)
$this->configuration->getDb()->escape($word)
update() — which modifies an existing stop word — correctly escapes $word before use. add() does not perform the same escaping on the equivalent value. This inconsistency between two methods handling the same data type is the root cause: the escaping convention used throughout the rest of the file was not applied uniformly to this one insertion path.
Proof of Concept
Precondition: Attacker has valid administrator credentials (or has otherwise obtained an authenticated administrator session, e.g. via a separate session-hijacking or CSRF vector).
Attack steps:
-
Authenticate to the phpMyFAQ administration panel.
-
Navigate to the Stop Words management feature.
-
Submit a new stop word with the following value instead of a normal word:
test', 'en'); DROP TABLE faqstopwords; -- -
The resulting SQL statement sent to the database becomes (table/column names approximate, based on the traced
sprintftemplate):INSERT INTO faqstopwords VALUES(1, 'en', 'test', 'en'); DROP TABLE faqstopwords; --') -
The injected
DROP TABLE faqstopwords;statement executes as a second SQL statement (subject to the database driver/PDO configuration permitting multi-statement execution; even where multi-statement execution is disabled, the same injection point allows classic single-statement SQLi techniques such asUNION-based data extraction or boolean/time-based blind injection against other tables the database user can access).
Impact
- Confidentiality: An attacker with this access can use UNION-based or blind SQL injection techniques to read data from other tables in the database (e.g. user credentials, FAQ content marked as private/internal, session data) that the database user account has permission to access.
- Integrity: Arbitrary
INSERT/UPDATE/DELETEstatements can be appended, allowing modification of unrelated application data. - Availability: As demonstrated in the PoC, structural statements like
DROP TABLEcan be injected, directly impacting application availability.
Mitigating factor: Exploitation requires an authenticated administrator session. This is not exploitable by an anonymous or low-privilege user. This lowers the severity from Critical/High to Medium, consistent with phpMyFAQ's own threat model where administrators are a trusted role — but it remains a genuine defense-in-depth failure: a compromised or malicious admin…
- Record
GHSA-rw77-vq4g-x3hp- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-89
- Updated
- 2026-11-02
NVD
8.5
phpMyFAQ is an open source FAQ web application. The StopWords::add() method inversions prior to 4.1.6 builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path. An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database. Version 4.1.6 fixes the issue.
- Record
CVE-2026-56738- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X - Weakness
- CWE-89
- Updated
- 2026-11-02
OSV
8.5
phpMyFAQ has SQL Injection in `StopWords::add()` — Unescaped Stop Word Insertion
phpMyFAQ is an open source FAQ web application. The StopWords::add() method inversions prior to 4.1.6 builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path. An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database. Version 4.1.6 fixes the issue.
- Record
CVE-2026-56738- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-89
- Updated
- 2026-11-02
OSVGHSA-rw77-vq4g-x3hp
8.5
phpMyFAQ has SQL Injection in `StopWords::add()` — Unescaped Stop Word Insertion
Summary
The StopWords::add() method in phpMyFAQ builds a SQL INSERT statement using sprintf() and inserts the user-supplied stop word value directly into the query string without calling the application's database escaping function on it. A sibling method, StopWords::update(), which modifies an existing stop word, correctly escapes the same kind of input. The omission is isolated to the add() (insert) code path.
An authenticated administrator who can reach the stop-word management feature can submit a crafted value as the "word" parameter that breaks out of the SQL string literal and injects arbitrary SQL, including statements to drop tables, exfiltrate data, or modify other rows in the database.
Affected Code
File: phpmyfaq/src/phpMyFAQ/StopWords.php
Method: add() (approx. lines 60–75 in the audited revision)
$sql = sprintf(
"INSERT INTO %s VALUES(%d, '%s', '%s')",
$this->getTableName(),
$id,
$this->configuration->getDb()->escape($this->language), // language IS escaped
$word // <-- $word is NOT escaped
);
$word is taken directly from the administrative form input (the new stop word to add) and concatenated into the SQL string via sprintf("'%s'", ...) with no call to the database driver's escape() method.
Contrast with the safe sibling method
Method: update() (line 82 in the audited revision)
$this->configuration->getDb()->escape($word)
update() — which modifies an existing stop word — correctly escapes $word before use. add() does not perform the same escaping on the equivalent value. This inconsistency between two methods handling the same data type is the root cause: the escaping convention used throughout the rest of the file was not applied uniformly to this one insertion path.
Proof of Concept
Precondition: Attacker has valid administrator credentials (or has otherwise obtained an authenticated administrator session, e.g. via a separate session-hijacking or CSRF vector).
Attack steps:
-
Authenticate to the phpMyFAQ administration panel.
-
Navigate to the Stop Words management feature.
-
Submit a new stop word with the following value instead of a normal word:
test', 'en'); DROP TABLE faqstopwords; -- -
The resulting SQL statement sent to the database becomes (table/column names approximate, based on the traced
sprintftemplate):INSERT INTO faqstopwords VALUES(1, 'en', 'test', 'en'); DROP TABLE faqstopwords; --') -
The injected
DROP TABLE faqstopwords;statement executes as a second SQL statement (subject to the database driver/PDO configuration permitting multi-statement execution; even where multi-statement execution is disabled, the same injection point allows classic single-statement SQLi techniques such asUNION-based data extraction or boolean/time-based blind injection against other tables the database user can access).
Impact
- Confidentiality: An attacker with this access can use UNION-based or blind SQL injection techniques to read data from other tables in the database (e.g. user credentials, FAQ content marked as private/internal, session data) that the database user account has permission to access.
- Integrity: Arbitrary
INSERT/UPDATE/DELETEstatements can be appended, allowing modification of unrelated application data. - Availability: As demonstrated in the PoC, structural statements like
DROP TABLEcan be injected, directly impacting application availability.
Mitigating factor: Exploitation requires an authenticated administrator session. This is not exploitable by an anonymous or low-privilege user. This lowers the severity from Critical/High to Medium, consistent with phpMyFAQ's own threat model where administrators are a trusted role — but it remains a genuine defense-in-depth failure: a compromised or malicious admin…
- Record
GHSA-rw77-vq4g-x3hp- CVSS 4.0
- 8.5 High
CVSS:4.0/AV:N/AC:L/AT:N/PR:H/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N - Weakness
- CWE-89
- Updated
- 2026-11-02
Affected products
Affected packages
| Package | Affected | Fixed |
|---|---|---|
phpmyfaq/phpmyfaqPackagist |
through 4.1.5 | 4.1.6 |
thorsten/phpmyfaqPackagist |
through 4.1.5 | 4.1.6 |
phpmyfaq/phpmyfaqPackagist |
before 4.1.6, plus listed versions 2.10.0-alpha2.8.02.8.0-RC2.8.0-RC22.8.0-RC3 Show 45 moreShow less2.8.0-RC42.8.0-alpha22.8.0-alpha32.8.0-beta2.8.0-beta22.8.0-beta32.8.12.8.102.8.112.8.122.8.132.8.142.8.152.8.162.8.172.8.182.8.192.8.22.8.202.8.212.8.222.8.232.8.242.8.252.8.262.8.272.8.282.8.292.8.32.8.42.8.52.8.62.8.72.8.82.8.92.9.02.9.0-alpha2.9.0-alpha22.9.0-alpha32.9.0-alpha42.9.0-beta2.9.0-beta22.9.0-rc2.9.0-rc22.9.0-rc3 |
4.1.6 |
thorsten/phpmyfaqPackagist |
before 4.1.6, plus listed versions 2.10.0-alpha2.8.02.8.0-RC2.8.0-RC22.8.0-RC3 Show 45 moreShow less2.8.0-RC42.8.0-alpha22.8.0-alpha32.8.0-beta2.8.0-beta22.8.0-beta32.8.12.8.102.8.112.8.122.8.132.8.142.8.152.8.162.8.172.8.182.8.192.8.22.8.202.8.212.8.222.8.232.8.242.8.252.8.262.8.272.8.282.8.292.8.32.8.42.8.52.8.62.8.72.8.82.8.92.9.02.9.0-alpha2.9.0-alpha22.9.0-alpha32.9.0-alpha42.9.0-beta2.9.0-beta22.9.0-rc2.9.0-rc22.9.0-rc3 |
4.1.6 |
History
| Recorded | Changed | Sources |
|---|---|---|
| first indexed | CVE List, EUVD, GitHub Advisories, NVD, OSV |
Dates are when Every CVE recorded each change. Upstream dates may differ.
In short
CVE-2026-56738 is a high vulnerability (CVSS 8.5) in Thorsten Phpmyfaq, published September 24, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.26%, the 17th percentile. Fixed in phpmyfaq/phpmyfaq 4.1.6.
References
github.com/thorsten/phpMyFAQ/security/advisories/GHSA-rw77-vq4g-x3hp
github.com/thorsten/phpMyFAQ/commit/d56ef5d75c3c007de095bc4c13b470c7ac783f0f
nvd.nist.gov/vuln/detail/CVE-2026-56738
github.com/thorsten/phpMyFAQ/releases/tag/4.1.6
github.com/advisories/GHSA-rw77-vq4g-x3hp
github.com/CVEProject/cvelistV5/tree/main/cves/2026/56xxx/CVE-2026-56738.json
github.com/thorsten/phpMyFAQ
Left out here: 248 versions and the rest of 2 source descriptions. The JSON record has them.