CVE-2018-25088 (Python, published 2023-07-18T13:15Z)
Description: value: A vulnerability, which was classified as critical, was found in Blue Yonder postgraas_server up to 2.0.0b2. Affected is the function _create_pg_connection/create_postgres_db of the file postgraas_server/backends/postgres_cluster/postgres_cluster_driver.py of the component PostgreSQL Backend Handler. The manipulation leads to sql injection. Upgrading to version 2.0.0 is able to address this issue. The patch is identified as 7cd8d016edc74a78af0d81c948bfafbcc93c937c. It is recommended to upgrade the affected component. VDB-234246 is the identifier assigned to this vulnerability.
Severity: nan (CVSS v3 base score: 9.8)
Weakness: CWE-89 \u2014 Improper Neutralization of Special Elements used in an SQL Command ('SQL Injection')
The product constructs all or part of an SQL command using externally-influenced input from an upstream component, but it does not neutralize or incorrectly neutralizes special elements that could modify the intended SQL command when it is sent to a downstream component. Without sufficient removal or quoting of SQL syntax in user-controllable inputs, the generated SQL query can cause those inputs to be interpreted as SQL instead of ordinary user data.
Repository: https://github.com/blue-yonder/postgraas_server
Files changed:
postgraas_server/backends/postgres_cluster/postgres_cluster_driver.py
tests/test_integration/backends/postgres_cluster/test_postgres_cluster_driver.py
tests/test_integration/test_backend_behaviour.py
Commit message: Harden the database creation against SQL injections

If using the PostgreSQL backend, database creation was previously vulnerable to SQL injections. This commit fixes these.

There are two tests which no longer behave as expected and have been disabled for now. They use usernames that previously broke the SQL statement but have now become valid. We might want to think about restricting the possible username somewhat again.


Vulnerable code:
            cur.execute("SELECT 1 FROM pg_database WHERE datname='{}';".format(db_name))
            cur.execute("SELECT 1 FROM pg_roles WHERE rolname='{}';".format(db_user))
            create_role = "CREATE USER {db_username} WITH PASSWORD '{db_pwd}';".format(**connection_dict)
            drop_role = "DROP ROLE {db_username};".format(**connection_dict)
            grant_role = 'GRANT {db_username} TO "{postgraas_user}";'.format(
                db_username=connection_dict['db_username'], postgraas_user=get_normalized_username(config['username'])
            )
            create_database = "CREATE DATABASE {db_name} OWNER {db_username};".format(**connection_dict)
                cur.execute(create_role)
                cur.execute(grant_role)
            # saidly 'CREATE DATABASE' cannot run inside a transaction block
                cur.execute(create_database)
                cur.execute(drop_role)

Fixed code:
from psycopg2.sql import SQL, Identifier
            cur.execute("SELECT 1 FROM pg_database WHERE datname=%s;", (db_name, ))
            cur.execute("SELECT 1 FROM pg_roles WHERE rolname=%s;", (db_user, ))
                cur.execute(SQL("CREATE USER {} WITH PASSWORD %s;").format(
                    Identifier(connection_dict['db_username']),
                ), (
                    connection_dict['db_pwd'],
                ))
                cur.execute(SQL("GRANT {} TO {};").format(
                    Identifier(connection_dict['db_username']),
                    Identifier(get_normalized_username(config['username'])),
                ))
            # sadly 'CREATE DATABASE' cannot run inside a transaction block
                cur.execute(SQL("CREATE DATABASE {} OWNER {};").format(
                    Identifier(connection_dict['db_name']),
                    Identifier(connection_dict['db_username']),
                ))
                cur.execute(SQL("DROP ROLE {};").format(
                    Identifier(connection_dict['db_username']),
                ))
    @pytest.mark.xfail(reason='Username now valid due to hardening against SQL injections.')
    @pytest.mark.xfail(reason='Username now valid due to hardening against SQL injections.')