After Hours CVEs : Uncovering Path Traversal Vulnerabilities in Open Source

5 minute read

TL;DR: We found some path traversal issues in open source projects!

Disclaimer: This research was conducted strictly independent of my employer (excluded from scope). All opinions and views in this article are my own. When citing, please call me an Independent Security Researcher.

Introduction and Goal

On May 02, 2024 CISA released an advisory on “Secure by Design Alert: Eliminating Directory Traversal Vulnerabilities in Software”.

CISA Path Traversal advisory

Me and my good friend Kartik used this as motivation and started looking for issues in open source projects. The idea was not only to identify issues but also to help developers fix them either by suggesting solutions or raising a PR.

Preventive measures

But before we dive in we wanted to cover some of the preventive measures suggested by CISA in the document here

  1. Consider generating a random identifier for each file and storing associated metadata separately (e.g., in a database) rather than using user input when naming files.

One great example of this is by actual-server: here, they have a route called /download-user-file.

 1app.get("/download-user-file", async (req, res) => {
 2  let accountDb = getAccountDb()
 3  let fileId = req.headers["x-actual-file-id"]
 4  if (typeof fileId !== "string") {
 5    // FIXME: Not sure how this cannot be a string when the header is
 6    // set.
 7    res.status(400).send("Single file ID is required")
 8    return
 9  }
10
11  // Do some authentication
12  let rows = accountDb.all(
13    "SELECT id FROM files WHERE id = ? AND deleted = FALSE",
14    [fileId]
15  )
16  if (rows.length === 0) {
17    res.status(400).send("User or file not found")
18    return
19  }
20
21  res.setHeader("Content-Disposition", `attachment;filename=${fileId}`)
22  res.sendFile(getPathForUserFile(fileId))
23})

The fileID is an ID generated by the database and is checked against the database for existence first. If the value is found, only then is the file returned. In my opinion, the developers were likely attempting to implement authentication checks and unintentionally secured it against path traversal (probably). Irrespective, they are spot on with the secure design; they generated a random identifier and stored the metadata in the database.

  1. In the case where the above approach is not taken, strictly limit the types of characters that can be supplied in file names, e.g., by restricting to alphanumeric characters . Also ensure that uploaded files do not have executable permissions.

While it might not always be feasible or possible to use the first suggested preventive measure, the second point should be easy to follow and implement. This is what we ended up suggesting or adding in the code with our PRs to fix the vulnerabilities we found.

However, sometimes it might be a feature, like in CVE-2024-43797 where ONLY admins are allowed to write directories anywhere in the system.

CVEs

1. CVE-2024-39918

Base Score: 4.3 MEDIUM
Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:N
Stars: 157

Quick Links: (NIST, POC)

  1. Issue: Path traversal occurred due to a lack of sanitization of user input for the file name. However, this was slightly different because the issue was with the arguments rather than the file name itself and a file with only “.png” extension could be written anywhere in the system. Commit:8afc00247c1d7e6c7b37356a5f6282b486e596fa introduced the issue.

  2. POC: Here’s the Loom video POC of me reproducing the issue.

  3. Fix: The fix was to remove all the special characters and replace them with a single “-”. We didn’t go for a fancy fix because we already had a function to do this for us. Fixed in Commit:e4eaeca6493b21cd515b582fd6c0af09ede54507

2. CVE-2024-XXXXX

Base Score: 10.0 CRITICAL
Vector: CVSS:3.0/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
Stars: 2.1k

(we don’t have a CVE for this yet)

  1. Issue: Path traversal occurred due to a lack of sanitization of user input for the file name. This issue sort of combined Unrestricted file upload vulnerability as well. I could upload any file, with any extension and content anywhere in the system. Commit:8b81f0dd7e804859a776c51e09faec9e266af293 introduced the issue.

  2. POC: Here’s the Loom video of me reproducing the issue.

  3. Fix: Two fixes went here.

    1. First the dev used simple if statement to check what the fileName started with and ended with. Commit:760d01ca71cb1bbb85cef64a61c9784fab7965a0. This isn’t a foolproof fix and still leaves room for path traversal vulnerabilities. Additionally, the file upload vulnerability still exists.
    2. The second and final fix was to check if the file matched the exact naming pattern defined by the regex. This ensures that even if a file with a .xyz extension is uploaded, it is saved with a .webm extension, else rejected. Commit:8414e4e108bc721d3ffbb48f87e95485b7650795 which fixed the issue.

3. CVE-2024-43797

Base Score: 5.4 Medium
Vector: CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:N/I:L/A:L
Stars: 6.4k

Quick Links: NIST, POC

  1. Issue: The web app allowed admins to store libraries, including various file types like .txt and .pdf, anywhere in the server’s filesystem. However, this feature was intended only for admin users. We discovered an issue where non-admin users could exploit the endpoint to create arbitrary directories on the server. While not a traditional Path Traversal vulnerability, the impact was equivalent due to a Role-Based Access Control (RBAC) flaw. Commit(s) which introduced the issue

  2. POC: Here’s a Loom video of us reproducing the issue.

  3. Fix: The fix involved adding a check for the admin permissions in the code.Commit:8774e6be718147759cf33412c896568f4eb892c2 which fixed the issue

4. CVE-2024-47769

Base Score: 7.5
Vector: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
stars: 6.3k

Quick Links: (NIST, POC)

  1. Issue: The CRM application allowed unauthenticated users to browse files from the /public endpoint. Due to missing sanitization on the subPath variable, an attacker can exploit the endpoint to read any arbitrary file from the server. Commit:7b1d935c5b316ec3c6056e03b93d922c6d814c7b introduced the issue.

  2. POC: Here’s the POC for the issue.

  3. Fix: The fix commit involved adding a filter for the subPath variable Commit:0d623e1753a40442571954053de9fbb5072a8417 .

Conclusion

Most of these issues arose from using unsanitized user input in the path.join() function, leading to security vulnerabilities. To mitigate these risks, developers should follow security best practices from CISA and OWASP.

Closing Remarks

We aimed to assess the advisory’s severity by identifying and fixing issues independently, minimizing the burden on OSS developers. As security engineers, we recognize the need to improve our security reporting and remediation, given developers’ limited incentives. For each vulnerability found, we raised pull requests and asked developers to apply for CVEs, ensuring we avoid exaggerating or creating unnecessary alarms for users. Avoiding something like this.

I hope you found this useful and educational. Thanks and happy hunting! :)

END