YesWiki CVE-2026-52763
MEDIUMSeverity by source
AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N
Default install permits anonymous page saves (default_write_acl='*') with only a bypassable client-side hashcash check, warranting PR:N; no integrity or availability impact is demonstrated.
Primary rating from Vendor (https://github.com/YesWiki/yeswiki).
CVSS VectorVendor: https://github.com/YesWiki/yeswiki
Lifecycle Timeline
1DescriptionCVE.org
Summary
The recentchanges action (actions/recentchanges.php) accepts a period argument from two disjoint parameter spaces: the URL query string ($_GET['period']) and the action invocation {{recentchanges period="..."}}. A whitelist at line 17 validates only the URL form against ['day','week','month']. The action-argument form takes the else branch at line 33 ($dateMin = $this->GetParameter('period')) with no validation, and the value flows into PageManager::getRecentlyChanged() (includes/services/PageManager.php:196), where it is interpolated into a WHERE time >= '...' ORDER BY time DESC clause without escaping or parameterization. UNION-based injection succeeds, the leaked rows render into the response page via actions/recentchanges.php:43,58 (ComposeLinkToPage($page['tag'])), so any visitor of the trigger page sees the exfiltrated data.
The vulnerability provides arbitrary read of the YesWiki database to anyone who can save the trigger page. On a default install (default_write_acl='*'), this includes anonymous users, subject to the hashcash JS check on the page-edit form. Once the trigger page is saved, every subsequent view fires the injection as the SQLi is stored. Stored SQL injection is reachable through the page-edit flow, with arbitrary database read.
Details
Two issues compose the vulnerability.
actions/recentchanges.phpline 33 reads the action argument and skips the whitelist.
if (isset($_GET['period']) && in_array($_GET['period'], ['day', 'week', 'month'])) {
switch ($_GET['period']) {
case 'day': $d = strtotime('-1 day'); $dateMin = date('Y-m-d H:i:s', $d); break;
case 'week': $d = strtotime('-1 week'); $dateMin = date('Y-m-d H:i:s', $d); break;
case 'month': $d = strtotime('-1 month'); $dateMin = date('Y-m-d H:i:s', $d); break;
}
} else {
$dateMin = $this->GetParameter('period');
}Wiki::GetParameter() (includes/YesWiki.php:895) reads $this->parameter[$key], which is populated from the {{action key=value}} argument list - disjoint from $_GET. The whitelist's if branch only runs when $_GET['period'] matches one of three exact values; in every other case the else branch reads the action argument with no validation, no escaping, no DateTime parse, no regex. The two parameter spaces are independent.
- In
includes/services/PageManager.php,PageManager::getRecentlyChanged()interpolates the value into SQL.
public function getRecentlyChanged($limit = 50, $minDate = ''): ?array
{
if (!empty($minDate)) {
if ($pages = $this->dbService->loadAll(
'select id, tag, time, user, owner from' . $this->dbService->prefixTable('pages')
. "where latest = 'Y' and comment_on = '' and time >= '$minDate' order by time desc"
)) {
return $pages;
}
}
}$minDate is interpolated raw into the query and there is no $this->dbService->escape($minDate) and no parameter binding and no format check.
The default action ACL for recentchanges is * (includes/YesWiki.php:1100, GetModuleACL), so Performer::CheckModuleACL('recentchanges', 'action') returns true for everyone. The injection runs whenever a viewer reaches a page that embeds the action with a malicious period argument.
PoC
Default fresh install so default_write_acl='*'.
- place the SQLi payload on a page
{{recentchanges period="2000-01-01' UNION SELECT 9999 AS id, CONCAT('LEAK_', name, '_', SUBSTRING(password,1,32)) AS tag, NOW() AS time, name AS user, name AS owner FROM yeswiki_users WHERE name='AdminUser' -- "}}The five UNION columns match the id, tag, time, user, owner projection that getRecentlyChanged selects. The tag column is rendered into the response as a hyperlink, exfiltrating the leaked data.
- anyone visits the page
GET /?<TriggerPage> HTTP/1.1
Host: target.exampleThe injected query executes server-side; the tag column is rendered into the page in actions/recentchanges.php:43,58 via ComposeLinkToPage($page['tag']).
Impact
Arbitrary read of any DB column the application's MySQL user can access.
AnalysisAI
Stored SQL injection in YesWiki's recentchanges action enables arbitrary read of the underlying MySQL database by any user who can save a wiki page - on default installations, this includes unauthenticated visitors. The payload is persisted as wiki page content and executes on every subsequent page load, leaking rows (including admin usernames and password hashes) rendered directly into the HTML response as hyperlinks. A fully working UNION-based proof-of-concept is included in the GitHub security advisory, confirming practical exploitability with no public exploit identified at time of analysis in CISA KEV.
Technical ContextAI
YesWiki is a PHP wiki platform distributed via Composer (yeswiki/yeswiki). The root cause is a split parameter-handling path in actions/recentchanges.php: the period value supplied via the URL query string ($_GET['period']) is validated against a strict whitelist (['day','week','month'] at line 17), but the identical parameter supplied via the wiki action syntax {{recentchanges period="..."}} is read by Wiki::GetParameter() (includes/YesWiki.php:895) in the else branch at line 33 - completely bypassing the whitelist. The two parameter sources ($_GET vs. the action argument map $this->parameter) are disjoint, so the whitelist never evaluates the action-supplied value. This unvalidated string flows as $minDate into PageManager::getRecentlyChanged() (includes/services/PageManager.php:196), where it is directly interpolated into a raw SQL string - WHERE time >= '$minDate' ORDER BY time DESC - with no parameterized binding, no escape() call, and no format check. This is a textbook CWE-89 (Improper Neutralization of Special Elements in an SQL Command). The recentchanges action ACL defaults to *, so the injection executes for every page visitor without any action-level access check.
RemediationAI
Apply the upstream fix available at commit 5da27474c3ee62270c8a6b9d7055d494cdbd38e5 (https://github.com/YesWiki/yeswiki/commit/5da27474c3ee62270c8a6b9d7055d494cdbd38e5); upstream fix available (commit), but a specifically tagged patched release version is not independently confirmed from available data - verify that a tagged release incorporating this commit exists before updating production systems. The vendor advisory is at https://github.com/YesWiki/yeswiki/security/advisories/GHSA-89v6-j5x6-cmj3. As compensating controls while the patch is deployed: restrict page-write access by changing default_write_acl from '*' to require authentication (e.g., @admins or a specific group), which eliminates the anonymous exploitation path but changes site behavior for public-editing wikis; alternatively, restrict or disable the recentchanges action via the YesWiki ACL system to prevent the vulnerable action from executing. Hardening the MySQL application user's grants to the minimum required tables also limits the blast radius of exploitation.
In PHP versions 7.1.x below 7.1.33, 7.2.x below 7.2.24 and 7.3.x below 7.3.11 in certain configurations of FPM setup it
sapi/cgi/cgi_main.c in PHP before 5.3.12 and 5.4.x before 5.4.2, when configured as a CGI script (aka php-cgi), does not
(1) boardData102.php, (2) boardData103.php, (3) boardDataJP.php, (4) boardDataNA.php, and (5) boardDataWW.php in Netgear
The '/common/download_agent_installer.php' script in the Quest KACE System Management Appliance 8.0.318 is accessible by
ProjectSend versions prior to r1720 are affected by an improper authentication vulnerability. Rated critical severity (C
Roundcube Webmail contains a critical PHP object deserialization vulnerability (CVE-2025-49113, CVSS 9.9) that allows au
Util/PHP/eval-stdin.php in PHPUnit before 4.8.28 and 5.x before 5.6.3 allows remote attackers to execute arbitrary PHP c
Palo Alto Networks PAN-OS management web interface contains an authentication bypass allowing unauthenticated attackers
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
Nagios XI version xi-5.7.5 is affected by OS command injection. Rated high severity (CVSS 8.8), this vulnerability is re
The get_referers function in /opt/ws/bin/sblistpack in Sophos Web Appliance before 3.7.9.1 and 3.8 before 3.8.1.1 allows
The Backup Migration plugin for WordPress is vulnerable to Remote Code Execution in all versions up to, and including, 1
Same weakness CWE-89 – SQL Injection
View allShare
External POC / Exploit Code
Leaving vuln.today
GHSA-89v6-j5x6-cmj3