Skip to main content
VulnerabilityPublished Updated

CVE-2026-34036: dolibarr/dolibarr · Dolibarr Core Discloses Sensitive Data via Authenticated Local File Inclusion in selectobject.php

Affects dolibarr/dolibarrSource GCVE Database

0

Not known to be exploited · public detection template (Nuclei) · CVSS 6.5 Medium : upgrade to 23.0.0 when convenient.

Data as of 26 Oct 2026, 17:16 UTC

CVSS 3.1 base score
6.5Medium
How severe the flaw is on the 0–10 CVSS scale.
EPSS
1.4% chance of exploitation in 30 days – higher than 73% of CVEsExploit Prediction Scoring System: the likelihood attackers will use this flaw soon.
Patch
Available – fixed in 23.0.0
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:N/A:N

Exploitation evidence

  1. Disclosed: evidence found.

    CVE published 27 Mar 2026

  2. Weaponised: no evidence on record.

    No public exploit code indexed in Metasploit or Exploit-DB

  3. Exploited in the wild: no evidence on record.

    Not in CISA KEV and no source reports exploitation

  4. Observed by OffSeq Mirage: no evidence on record.

    No attack traffic recorded by OffSeq Mirage sensors

A missing step is not evidence of safety. Sources: cve.org (opens in a new tab), the Metasploit, Exploit-DB and nuclei-templates index as of 26 Oct 2026.

What to do

Upgrade dolibarr/dolibarr to 23.0.0.

Affected software

ProductAffectedFixed in
Packagistdolibarr/dolibarrAffected
  • <23.0.0
Fixed in
  • 23.0.0

Check your own hosts for these packages with threat-finder (opens in a new tab), our free open-source scanner.

Description

# Authenticated Local File Inclusion (LFI) via selectobject.php leading to sensitive data disclosure ## Target Dolibarr Core (Tested on version 22.0.4) ## Summary A Local File Inclusion (LFI) vulnerability has been discovered in the core AJAX endpoint `/core/ajax/selectobject.php`. By manipulating the `objectdesc` parameter and exploiting a fail-open logic flaw in the core access control function `restrictedArea()`, an authenticated user with no specific privileges can read the contents of arbitrary non-PHP files on the server (such as `.env`, `.htaccess`, configuration backups, or logs…). ## Vulnerability Details The vulnerability is caused by a critical design flaw in `/core/ajax/selectobject.php` where dynamic file inclusion occurs **before** any access control checks are performed, combined with a fail-open logic in the core ACL function. - **Arbitrary File Inclusion BEFORE Authorization:** The endpoint parses the `objectdesc` parameter into a `$classpath`. If `fetchObjectByElement` fails (e.g., by providing a fake class like `A:conf/.htaccess:0`), the application falls back to `dol_include_once($classpath)` at **line 71**. At this point, the arbitrary file is included and its content is dumped into the HTTP response buffer. This happens *before* the application checks any user permissions. - **Access Control Bypass (Fail-Open):** At **line 102**, the application finally attempts to verify permissions by calling `restrictedArea()`. Because the object creation failed, the `$features` parameter sent to `restrictedArea()` is empty (`''`). Inside `security.lib.php`, if the `$features` parameter is empty, the access check block is completely skipped, leaving the `$readok` variable at `1`. Because of this secondary flaw, the script finishes cleanly with an HTTP 200 OK instead of throwing a 403 error. This allows any authenticated user to bypass ACLs and include files. While PHP files cause a fatal error before their code is displayed, the contents of any text-based file (like `.htaccess`, `.env`, `.json`, `.sql`) are dumped into the HTTP response before the application crashes. ## Steps to Reproduce - Log in to the Dolibarr instance with any user account (no specific permissions required). - Intercept or manually forge a GET request to the following endpoint: ``` GET /core/ajax/selectobject.php?outjson=0&htmlname=x&objectdesc=A:conf/.htaccess:0 ``` - Observe the HTTP response. The contents of the `conf/.htaccess` file will be reflected in the response body right before the PHP Fatal Error message. - *(Optional)* Run the attached Python PoC to automate the extraction: ``` python3 poc.py --url http://target.com --username '<username>' --password '<password>' --file conf/.htaccess ``` ## Impact An attacker with minimal access to the CRM can exfiltrate sensitive files from the server. This can lead to the disclosure of environment variables (`.env`), infrastructure configurations (`.htaccess`), installed packages versions, or even forgotten logs and database dumps, paving the way for further attacks. ## Suggested Mitigation - **Input Validation & Whitelisting:** The `$classpath` must be strictly validated or whitelisted before being passed to `dol_include_once()`. - **Execution Flow Correction:** The file inclusion logic must never be executed before the user's authorization has been fully verified. - **Enforce Fail-Secure ACLs:** Modify `restrictedArea()` in `core/lib/security.lib.php` so that if the `$features` parameter is empty, access is explicitly denied (`$readok = 0`) instead of allowed by default. ## Disclosure Policy & Assistance The reporter is committed to coordinated vulnerability disclosure. This vulnerability, along with the provided PoC, will be kept strictly confidential until a patch is released and explicit authorization for public disclosure is given. Should any further technical details, logs, or testing of the remediation once a patch has been developed be needed, the reporter is available to assist. Thank you for the time and commitment to securing Dolibarr. Best Regards, Vincent KHAYAT (cnf409) ## Video PoC https://github.com/user-attachments/assets/4af80050-4329-4c88-8a54-e2b522deb844 ## PoC Script ```python #!/usr/bin/env python3 """Dolibarr selectobject.php authenticated LFI PoC""" import argparse import html import re import urllib.error import urllib.parse import urllib.request from http.cookiejar import CookieJar LOGIN_MARKERS = ("Login @", "Identifiant @") LOGOUT_MARKERS = ("/user/logout.php", "Logout", "Mon tableau de bord") def request( opener, base_url, method, path, params=None, data=None, timeout=15 ): url = f"{base_url.rstrip('/')}{path}" if params: url = f"{url}?{urllib.parse.urlencode(params)}" payload = urllib.parse.urlencode(data).encode("utf-8") if data else None req = urllib.request.Request(url, method=method.upper(), data=payload) req.add_header("User-Agent", "dolibarr-lfi-poc/1.0-securitytest-for-dolibarr")

References

Community reviews

Loading reviews…