Nginx, a versatile web server pivotal to numerous internet infrastructures, has held a dominant market share since its inception in 2004, with widespread adoption across websites and Docker containers. This article delves into the intricacies of Nginx, focusing on the location and alias directives that are central to how Nginx handles specific URLs. We also explore potential vulnerabilities arising from misconfigurations and demonstrate how they can lead to security exploits, drawing on research presented at the BlackHat 2018 conference by Orange Tsai.

The guide further illustrates these points through a thorough examination of popular open-source repositories using GitHub Code Search to identify potential Nginx configuration vulnerabilities. Real-world case studies involving Bitwarden and Google’s HPC Toolkit highlight the significant risk of data exposure if these vulnerabilities are not addressed. Additionally, we introduce NavGix, an automated tool designed to detect these vulnerabilities in a black-box manner, providing comprehensive insights into Nginx’s complexities, vulnerabilities, and potential misconfigurations.

Brief Overview of Nginx

Nginx is a versatile web server that can also function as a reverse proxy, load balancer, mail proxy, and HTTP cache. The software was created and publicly released in 2004.

As per W3Tech’s data, as of June 2022, Nginx holds the highest market share among web servers, with 33.6% of websites on the internet utilizing it. Additionally, according to Docker, Nginx is the most deployed technology in their containers. This significant popularity makes vulnerabilities related to Nginx all the more critical and intriguing.

Location and Alias Directives

The location directive is a block directive that can contain other directives and is used to define how Nginx should handle requests for specific URLs, they can be defined.

It is often used in conjunction with the alias directive to map URLs to specific file locations on the server. the directives can be defined in the nginx.conf file or in a separate configuration file.

The syntax for the location directive is as follows:

location [modifier] /path/to/URL {
    # other directives
}

The modifier is optional and can be one of the following:

  • =: Exact match
  • ~: Case-sensitive regular expression match
  • ~*: Case-insensitive regular expression match
  • ^~: Prefix match (stop searching if this matches)

Here is an example of how to use the location directive in the nginx.conf file:

location /assets/ { # defines a location block for requests matching /assets
    
    alias /opt/production/assets/; # maps the request to the assets folder
    
}

Identifying Misconfigurations

At the BlackHat 2018 conference, Orange Tsai presented his research on breaking URL parsers. Among other impressive findings, he demonstrated a technique discovered in a 2016 CTF challenge from HCTF, created by @iaklis.

For the technique to be applicable, the following conditions must be met:

  • The location directive should not have a trailing slash in its path;
  • An aliasdirective must be present within the location context, and it must end with a slash.

Achieving Impact

In the vulnerable example above, Nginx will match any URLs that start with /img and serve whatever follows that slash with the alias path /var/images/ prepended.

This implies that both a request for /img/profile.jpg and a request for /imgprofile.jpg would return the same file. Because since the alias directive ends with a trailing slash, an additional slash is not necessary after the matched location.

Taking into account that we can access the target folder through any request URL starting with /img, we can attempt to access the ever-present .. directory, thereby reaching the parent directory of the target directory by issuing a request to /img.. for the given example.

If we receive a redirection response from Nginx, we can assume that Nginx has located the directory and is attempting to redirect us to /img../, as it commonly does when accessing a directory.

And we do!

Consequently, this implies that any file or child directory within the parent directory of the target folder will be accessible to us, and Nginx will readily serve them. In our lab example, this means we could access all files in the /var/ folder, given that the target folder in the configuration is /var/images/. This allows us to utilize simple payloads, such as a GET to, /img../log/nginx/access.log to download a log file located on /var/log/nginx/access.log.

We can even see our previous tests!

The severity of this vulnerability can fluctuate significantly depending on the project, extending from a negligible impact to a critical one. The degree of its repercussions is primarily determined by whether the exposed directory holds sensitive data that may facilitate additional attacks or result in the disclosure of private information.

Achieving Impact Without a Slash on Alias

Same vulnerability, but without a trailing slash on alias.

A question that may arise is whether this vulnerability can still be exploited without the trailing slash on the alias directive. The answer is yes, but it would mean that using traversal sequences to escape the directory would no longer be possible. This is because everything after the matched location is appended to the alias, and appending a .. sequence to a path without a trailing slash would only result in a non-existent folder name. e.g /var/images../

However, we can still exploit this misbehavior to access other directories that have a name starting with the target directory name. As a result, we might not be able to access it /var/images/../log/, but we could still access a directory  /var/images_confidential by making a GET request to /img_confidential.

In this case, Nginx appends _confidential to the /var/images target path, effectively serving URLs from the combined path of /var/images and _confidential which results in /var/images_confidential.

Hunting Open-Source Repositories

As a starting point in our search for this vulnerability, we chose to explore popular GitHub repositories that displayed this issue. Identifying this specific vulnerability in environments with access to source code becomes significantly more feasible, primarily due to two main factors:

  1. Detection: Utilizing straightforward code analysis tools, such as regular expression searches, allows us to effectively pinpoint potentially vulnerable Nginx configuration files within these projects.
  2. Exploitation: Having knowledge of the exact target directory that has been aliased empowers us to set up a local instance, examine the aliased directories using a local shell, and determine which files can be accessed through the vulnerability.

GitHub Code Search is a feature available on GitHub, the web-based platform for version control and collaboration using Git. This feature enables users to search for code across all public repositories hosted on the platform, making it especially useful for developers seeking examples, libraries, or solutions to specific coding challenges.

Additionally, GitHub Code Search can be employed to search for snippets of vulnerable code within popular projects. This can be accomplished through a variety of methods, such as simple string matches, regular expressions, path filters, and more. For example, to search for the Nginx Alias Traversal vulnerability, the following regular expression can be used:

/location /[_.a-zA-Z0-9-/]*[^/][s]{[sn]*alias /[_.a-zA-Z0-9-/]*/;/

Upon examining the search results for this query, it becomes evident that a significant number of repositories contain this specific vulnerability.

Due to the inherent limitations of regular expressions, they may not be ideally suited for matching code syntax. For instance, this particular regular expression will not match vulnerable configuration files containing comments between the directives. However, it serves as a starting point for our analysis.

Case Study #1: Leaking Bitwarden’s vault, logs, and certificates.

Bitwarden is an open-source password manager that helps users securely store and manage their passwords, credentials, and other sensitive information. It offers features such as password generation, autofill, and synchronization across devices. Bitwarden supports various platforms, including Windows, macOS, Linux, Android, iOS, and web browsers through extensions. Users can access their data through a web vault, desktop apps, mobile apps, or browser extensions.

Bitwarden also offers a self-hosted option for those who want to maintain their own server, which is the one we are going to examine.

If we search for ways to create a self-hosted instance of the Bitwarden server, one of the presented ways is through the Unified docker method, which is a setup made for simplifying the deployment of the platform.

100K+ downloads!

Since our regular expression gave a match for Bitwarden’s repository, we started dwelving into the code base searching for potentially vulnerable Nginx configurations, which is when we found the following inside the folder for the unified docker setup.

If this config is used, then it means all files on /etc/bitwarden/attachments/ will be accessible on the URL /attachments, but looking back at the exploit details, this also means that any files present on /etc/bitwarden/ will be downloadable also.

But let’s not get ahead of ourselves, we first must assess the impact of the exposure. To do that, we can either explore the code base or fire up a local instance and list the directory with a local shell.

Looking into the Dockerfile for that image, we find more info about that directory and what files it can contain:

[...]
ENV BW_DB_FILE="/etc/bitwarden/vault.db"
[...]
Dockerfile

It seems like this environment variable sets where the vault database is saved, and we can see that vault.db is located on /etc/bitwarden.

Bitwarden only saves the database in that location if the user chooses to use SQLite as a database provider.

Therefore, if we issue an unauthenticated request to http:///attachments../vault.db, we will download the entire Bitwarden SQLite3 database.

We can also fetch log files, which have a predictable filename and can all be downloaded by accessing the following paths:

  • /attachments../logs/api.log
  • /attachments../logs/admin.log
  • /attachments../logs/identity.log
  • /attachments../logs/notifications.log

And, of course, the certificate file was also exposed in that folder. To access it, all you would need to do is issue a request to /attachments../identity.pfx.

The data protection keys were also accessible, but these did not have a predictable filename, therefore, leaking them was not possible.

This vulnerability has been disclosed to Bitwarden and has since then been fixed. Bitwarden issued a US$6000 bounty, which is the highest bounty they issued on their HackerOne program.

Case Study #2: Google HPC Toolkit – Leaking Google Cloud Credentials

During our foray through GitHub, we chanced upon a software solution developed by Google, known as the Cloud HPC Toolkit. This was introduced in 2022, designed as a robust framework to facilitate the deployment of high-performance computing (HPC) environments on Google Cloud.

The HPC Toolkit boasts a Django-based web application front-end, granting users the ability to manage their HPC environments conveniently via a web interface.

Upon scrutinizing the configuration section identified by our regular expression, we discovered that a vulnerable path had indeed been defined. This path was aliased to ../hpc-toolkit/community/front-end/website/static/, implying that issuing a request to /static../ would provide us with access to the website folder.

Interestingly, we found that the SQLite database was also exposed within this folder and could be accessed through a specific URL:

curl http:///static../db.sqlite3 -O

Moreover, the Django secret key was accessible at the following location:

curl http://35.204.135.69/static../.secret_key

Gaining access to this database is highly critical for the application, as the primary function of the HPC Toolkit appears to be the orchestration of large-scale Google Cloud resources. In the event of a compromise, an attacker could potentially gain control over a victim’s GCP account credentials, which are stored in the SQLite database.

sqlite> select * from ghpcfe_credential;
1|production key|{
  "type": "service_account",
  "project_id": "andunduaindadaww",
  "private_key_id": "3acb9f[... redacted from report ...]7c69",
  "private_key": "-----BEGIN PRIVATE KEY-----nMIIEv[... redacted from report ...] 5Kdkvg=n-----END PRIVATE KEY-----n",
  "client_email": "adwaw[...].com",
  "client_id": "105114036295455180401",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/adwaw1f13f1f13-tkfe-sa%40andunduaindadaww.iam.gserviceaccount.com"
}|1
sqlite>

The Google VRP Team recognized our work by awarding us a $500 reward for uncovering this vulnerability. They believed the impact on the application wasn’t severe enough to warrant a larger reward. I toyed with the idea of debating the reward amount with them, but ultimately decided against it. After all, the recognition of our efforts was a reward in itself, and that was more than enough for us.

There are several methods to detect this vulnerability without necessitating access to the Nginx configuration file. Initially, potential location aliases can be identified by extracting links from the HTML source-code on the website’s main page. Subsequently, directory traversal can be attempted using the techniques outlined in the earlier sections of this report.

In the absence of extractable links, it is feasible to perform a minor brute-force attack targeting common aliases. The ensuing list has demonstrated promising results during our testing phase:

	var dictionary = []string{
		"static",
		"js",
		"images",
		"img",
		"css",
		"assets",
		"media",
		"lib",
	}

An automated tool, NavGix, has been created to aid in the enumeration and testing of aliased directories for traversal vulnerabilities. It is publicly available for download and use on its respective GitHub page.

Sample usage of navgix

Upon the identification of a directory susceptible to traversal by NavGix, it becomes possible to employ additional tools to fuzz for other accessible folders or files within the traversed directory. The primary objective here should be to locate files of interest that could potentially provide further impact, such as a configuration file containing secrets, log files, or source-code.

Conclusion

Wrapping up, while Nginx is a robust and incredibly versatile tool that fuels a significant portion of the internet, it’s easily susceptible to certain inconsistencies. These potential pitfalls are often a result of misconfigurations, which can inadvertently transform this reliable powerhouse into a possible weak link. Nginx’s approach to security leaves a significant onus on developers to avoid hazardous configurations, underscoring the importance of thorough understanding and cautious implementation.

Our journey through the world of open-source repositories and real-life case studies like Bitwarden and Google’s HPC Toolkit underlines just how significant these vulnerabilities can be. It’s a sobering reminder that even the most reliable systems can have their Achilles’ heel.

Read More