PostgreSQL

shodan : "port:5432 PostgreSQL" fofa : app="PostgreSQL

注入

  • PostgreSQL数据库注入笔记

通过 docker 搭建环境

wget -O f8x-dev https://f8x.io/dev
bash f8x-dev -postgres

相关文章

相关案例

相关工具

  • No-Github/postgresql_udf_help - PostgreSQL 提权辅助脚本

  • T3st0r-Git/hack_postgres - 便捷地使用 PostgreSQL 自定义函数来执行系统命令,适用于数据库管理员知道 postgres 密码却不知道 ssh 或 RDP 密码的时候在服务器执行系统命令。


MSF 爆破

信息收集

查看服务器端版本

列目录

列出数据库

查看支持的语言

查看安装的扩展

查看服务器 ip 地址


账号操作

查看当前用户是不是管理员权限

查询密码

可以看到,目前查询到的用户 hash 已经是 scram-sha-256,在以前的版本是加盐md5

我们可以查询当前的加密方式

添加用户

修改一个角色为管理员角色

更改密码

查看用户

查看管理员用户

获取用户角色


PostgreSQL 读文件

方法1 pg_read_file

方法2

方法3 lo_import

lo_import 允许指定文件系统路径。该文件将被读取并加载到一个大对象中,并返回该对象的 OID。


PostgreSQL 写文件

写 webshell 所需的利用条件

  • 拥有网站路径写入权限

  • 知道网站绝对路径

方法1 COPY

COPY 命令可以用于表和文件之间交换数据,这里可以用它写 webshell

也可以 base64 一下

方法2 lo_export

lo_export 采用大对象 OID 和路径,将文件写入路径。

方法3 lo_export + pg_largeobject

如果内容过多,那么首先创建一个 OID 作为写入的对象, 然后通过 0,1,2,3… 分片上传但是对象都为 12345 最后导出到 /tmp 目录下, 收尾删除 OID

写的文件每一页不能超过 2KB,所以我们要把数据分段,这里我就不拿 .so 文件为例了,就随便写个 txt 举个例子

或者还可以用 lo_put 在后面拼接进行写入

结束记得清理 OID 内容


PostgreSQL 创建文件夹

通过 log_directory 创建文件夹

方法来自于 https://www.yulegeyu.com/2020/11/16/Postgresql-Superuser-SQL%E6%B3%A8%E5%85%A5-RCE%E4%B9%8B%E6%97%85/ 这篇文章的场景

描述

配置文件中的 log_directory 配置的目录不存在时,pgsql 启动会失败,但是如果日志服务已启动,在修改 log_directory 配置后再 reload_conf 目录会被创建

原理

logging_collector 配置是否开启日志,只能在服务开启时配置,reloadconf 无法修改,log_directory 用来配置 log 日志文件存储到哪个目录,如果 log_directory 配置到一个不存在的目录,pgsql 会创建目录。

利用条件

  • 目标已经配置了 logging_collector = on

复现测试

拿靶机中的 postgresql 为例,先查看配置文件的路径

查看内容

将配置文件中的 log_directory 配置修改

转为 base64 格式

进入靶机,可以看到 f0x 目录已经创建


PostgreSQL 带外数据


PostgreSQL 提权

利用 UDF 命令执行

描述

在 8.2 以前,postgresql 不验证 magic block,可以直接调用本地的 libc.so

8.2 以上版本,需要自己编译 so 文件去创建执行命令函数,可以自己编译反弹 shell 后门,也可以用 sqlmap 提供好的

  • https://github.com/sqlmapproject/sqlmap/tree/master/data/udf/postgresql

复现测试

可以参考 No-Github/postgresql_udf_help

PL/Python 扩展

描述

PostgreSQL 可以支持多种存储过程语言,官方支持的除了 PL/pgSQL,还有 TCL,Perl,Python 等。

复现测试

默认 PostgreSQL 不会安装 Python 的扩展,这里我手动在靶机上安装下进行复现

先看下版本, pg 14

搜索下有没有对应的 plpython3u 版本安装

有,那么直接装

安装完毕后记得注册下扩展

查看是否支持 plpython3u

创建一个 UDF 来执行我们要执行的命令

创建好 UDF 后,进行调用

利用 session_preload_libraries 加载共享库

方法来自于 https://www.yulegeyu.com/2020/11/16/Postgresql-Superuser-SQL%E6%B3%A8%E5%85%A5-RCE%E4%B9%8B%E6%97%85/ 这篇文章的场景

描述

session_preload_libraries 只允许 superuser 修改,但可以加载任意目录的库,session_preload_libraries 配置从 pg10 开始存在,低于 pg10 时,可以使用 local_preload_libraries,不过该配置只允许加载 $libdir/plugins/ 目录下的库,需要将库写入到该目录下。

当每次有新连接进来时,都会加载 session_preload_libraries 配置的共享库。

和上面的利用 UDF 命令执行一样,不过不同点在于上面一个是创建 function 加载,这个方式是通过改配置文件中的 session_preload_libraries 进行加载,这里就不复现了

利用 ssl_passphrase_command 执行命令

方法来自于 https://pulsesecurity.co.nz/articles/postgres-sqli 这篇文章的场景

描述

当配置文件中配置了 ssl_passphrase_command ,那么该配置在需要获取用于解密SSL文件密码时会调用该配置的命令。

通过上传 pem,key 到目标服务器上,读取配置文件内容,修改配置文件中的ssl配置改为我们要执行的命令,通过lo_export覆盖配置文件,最后通过 pg_reload_conf 重载配置文件时将执行命令

利用条件

  • 需要知道 PG_VERSION 文件的位置 (不是 PG_VERSION 文件也行,pgsql限制私钥文件权限必须是0600才能够加载,pgsql目录下的所有0600权限的文件都是可以的,但覆盖后没啥影响的就 PG_VERSION 了)

复现

这里以靶机上已经存在的2个密钥文件为例

通过文件读取获取私钥

对私钥文件加密

上传 private_passphrase.key 到目标服务器上

由于 pgsql 限制私钥文件权限必须是 0600 才能够加载,这里搜索 pgsql 目录下的所有 0600 权限的文件,发现 PG_VERSION 文件符合条件,而且覆盖也没有太大影响

PG_VERSION 与 config_file 文件同目录,上传私钥文件覆盖 PG_VERSION,可绕过权限问题。

在靶机中查看验证是否写入成功

读取配置文件内容

在原始配置文件内容末尾追加上ssl配置

转为 base64 格式

可以看到,重新加载配置文件后,ssl_passphrase_command 中的命令已经执行

CVE-2018-1058 PostgreSQL 提权漏洞

漏洞描述

PostgreSQL 其 9.3 到 10 版本中存在一个逻辑错误,导致超级用户在不知情的情况下触发普通用户创建的恶意代码,导致执行一些不可预期的操作。

相关文章

POC | Payload | exp

CVE-2019-9193 PostgreSQL 高权限命令执行漏洞

漏洞描述

PostgreSQL 其 9.3 到 11 版本中存在一处“特性”,管理员或具有“COPY TO/FROM PROGRAM”权限的用户,可以使用这个特性执行任意命令。

利用条件

  • 版本 9.3-11.2

  • 超级用户或者 pg_read_server_files 组中的任何用户

相关文章

POC | Payload | exp

CVE-2020-25695 权限提升

相关文章