Advisory: Pydio Cells: Cross-Site Scripting via File Download Pydio Cells implements the download of files using presigned URLs which are generated using the Amazon AWS SDK for JavaScript [1]. The secrets used to sign these URLs are hardcoded and exposed through the JavaScript files of the web application. Therefore, it is possible to generate valid signatures for arbitrary download URLs. By uploading an HTML file and modifying the download URL to serve the file inline instead of as an attachment, any included JavaScript code is executed when the URL is opened in a browser, leading to a cross-site scripting vulnerability. Details ======= Product: Pydio Cells Affected Versions: 4.1.2 and earlier versions Fixed Versions: 4.2.0, 4.1.3, 3.0.12 Vulnerability Type: Cross-Site Scripting Security Risk: high Vendor URL: https://pydio.com/ Vendor Status: notified Advisory URL: https://www.redteam-pentesting.de/advisories/rt-sa-2023-004 Advisory Status: published CVE: CVE-2023-32751 CVE URL: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-32751 Introduction ============ "Pydio Cells is an open-core, self-hosted Document Sharing and Collaboration platform (DSC) specifically designed for organizations that need advanced document sharing and collaboration without security trade-offs or compliance issues." (from the vendor's homepage) More Details ============ When a file named "xss.html" is downloaded in the Pydio Cells web application, a download URL similar to the following is generated: https://example.com/io/xss/xss.html ?AWSAccessKeyId=gateway &Expires=1682495748 &Signature=920JV0Zy%2BrNYXjak7xksAxRpRp8%3D &response-content-disposition=attachment%3B%20filename%3Dxss.html &pydio_jwt=qIe9DUut-OicxRzNVlynMf6CTENB0J-J[...] The URL is akin to a presigned URL as used by the Amazon S3 service. It contains the URL parameter "response-content-disposition" which is set to "attachment" causing the response to contain a "Content-Disposition" header with that value. Therefore, the browser downloads the file instead of interpreting it. The URL also contains a signature and expiry timestamp, which are checked by the backend. Unlike a presigned URL as used by S3, the URL also contains the parameter "pydio_jwt" with the JWT of the user for authentication. Furthermore, the access key with the ID "gateway" is referenced, which can be found in the JavaScript sources of Pydio Cells together with the secret: ------------------------------------------------------------------------ _awsSdk.default.config.update({ accessKeyId: 'gateway', secretAccessKey: 'gatewaysecret', s3ForcePathStyle: !0, httpOptions: { timeout: PydioApi.getMultipartUploadTimeout() } }); ------------------------------------------------------------------------ With this information it is possible to change the URL parameter "response-content-disposition" to the value "inline" and then calculate a valid signature for the resulting URL. Furthermore, the content type of the response can be changed to "text/html" by also adding the URL parameter "response-content-type" with that value. This would result in a URL like the following for the previously shown example URL: https://example.com/io/xss/xss.html? AWSAccessKeyId=gateway &Expires=1682495668 &Signature=HpKue0YQZrnp%2B665Jf1t7ONgfRg%3D &response-content-disposition=inline &response-content-type=text%2Fhtml &pydio_jwt=qIe9DUut-OicxRzNVlynMf6CTENB0J-J[...] Upon opening the URL in a browser, the HTML included in the file is interpreted and any JavaScript code is run. Proof of Concept ================ Upload a HTML file into an arbitrary location of a Pydio Cells instance. For example with the following contents: ------------------------------------------------------------------------