WIZER CTF #27: Privacy Policy Viewer Level 2

If you're a returning visitor to our CTF Recaps, feel free to dive straight into the insights! For first-time explorers, let us quickly introduce you to the essence of these recaps. Wizer CTFs were introduced to challenge developers, encouraging them to adopt a hacker's mindset and thereby code more securely. This initiative is a pivotal part of our new security awareness training, specially crafted for development teams - Wizer's Secure Code Training for Developers!

After a challenge retires, our Wizer Wizard and CTO, Itzik Spitzen, crafts takeaways that offer valuable insights into the challenge, focusing on the defensive perspective for your script. Curious to test-drive a CTF before delving into the notes? Visit wizer-ctf.com – it's free, and there's something for all skill levels!

Link to challenge #27

Goal

In this challenge, we're identifying a bypass for Directory Traversal (a.k.a. Path Traversal) protection. Let's have a look!

Description of code

The code of the challenge showcases a UI and an endpoint of a simple "Privacy Policy Viewer". The UI invokes an API endpoint upon receiving a query argument of the company name, which in turn retrieves the privacy policy file from a dedicated folder named `/privacyPolicies` on the server. Each company is assumed to have a text/html file, named after the company which includes the privacy policy of the company. The developers of the code of Challenge #17 realized that they had a vulnerability in their code, Directory Traversal was possible, hence they worked on remediating it by removing all the occurrences of `../` from the company name input field, see below:


chal27_search_replace

 

Take a look at the full code:


chal27_h8745d

 

What’s wrong with that approach?

In reviewing the code, while the straightforward Directory Traversal vulnerability of the endpoint is seemingly resolved due to the replaceAll(), there's a simple bypass for the protection in place. Hackers love search & replace of substrings since they can commonly bypass it by creating text which results in exactly what they want to achieve after the replace process is completed.

What would a successful Directory Traversal bypass attack look like in this case?

An attacker could exploit the endpoint (or the UI) to retrieve practically any system file which is within the privileges of the account running the web-server process. For example, in the original code (Challenge #17) the required `passwd` file could be retrieved by specifying `../` multiple times to traverse back to the root folder and then into `/etc/passwd`. The exact number of `../` required to get to the root folder, could be easily discovered by trial and error and in fact specifying a larger than needed number of `../` would still work. However due to the protection put in place, in our case, the `companyName` argument could be manipulated to include instances of `..././`instead of the straightforward `../` to achieve directory traversal post replace.

So what?

Directory Traversal allows the attacker to target specific files under the OS, the app and any other system installed on the server to read information and gain unauthorized access to sensitive pieces of information. This could very easily lead to taking full control over the server or alternatively getting data from various configuration files, which could risk other systems as well.

Main Takeaways:

  • Avoid supplying a filename directly as user-input:
    The most effective way to prevent path traversal vulnerabilities is to avoid passing user-supplied input to filesystem APIs altogether. Most application functions that do this can be rewritten to deliver the same behavior in a safer way. In our example, the developer could have used a mapping of company names to file names, then use the company name to retrieve the file name from the mapping, and then use the file name to retrieve the file content.
  • Search & replace of risky substrings isn't a very good sanitization strategy:
    While the developer did a good job in removing the `../` from the input, the search & replace strategy isn't a very good sanitization strategy. Hackers love search & replace of substrings since they can commonly bypass it by creating text which results in exactly what they want to achieve after the replace process is completed. A better approach would be to validate the input against a required pattern, in this case, the developer could have blocked the `../` altogether by using `companyId` instead of the `companyName` input value and making sure it's of the required format (UUID for example).

 

Wanna join us on our next challenge? Sign up for our mailing list at wizer-ctf.com.

CODE WIZER!

Past Challenges

CTFs For Developers