天天看点

pg通过自定义函数_Pgsql堆叠注入场景下通过`CREATE FUNCTION`来实现命令执行

pg通过自定义函数_Pgsql堆叠注入场景下通过`CREATE FUNCTION`来实现命令执行

前言 在本篇文章中我将分享如何在

PostgreSQL

堆叠注入场景中通过

CREATE FUNCTION

关键字来实现命令执行的思路。 简要信息如下:

  • CVE:N/A
  • CVSS:4.1 (AV:N/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L)
  • 适用环境:Windows、Linux、Unix

在新版的

PostgreSQL

中:

  • 12.3
  • 11.8
  • 10.13
  • 9.6.18
  • 9.5.22

其数据库超管用户被限制只允许从默认目录读取后缀为

.dll

.so

动态库文件,举例如下:

  • Windows:C:\Program Files\PostgreSQL\11\lib
  • Unix/Linux:/var/lib/postgresql/11/lib

此外,默认情况下

NETWORK_SERVICE

postgres

这两个系统用户对该目录均无写入权限。但是经过鉴权的数据库超管用户可以通过调用

lo_import

函数将文件写入

pg_largeobject

系统表,再更新对应的数据内容将原本的内容替换为我们的恶意代码(通常是反弹个shell),随后通过

lo_export

函数转储数据至动态库目录,最终生成我们的恶意动态库文件。

CREATE FUNCTION

的另一个骚操作就是可以接收指定目录来遍历其动态库中的相关函数。因此只要已鉴权用户可以将动态库文件写入对应的存储目录,然后通过

CREATE FUNCTION

的目录遍历特性来加载动态库文件就可以实现命令执行。   利用流程

1. 通过

lo_import

获得一个

OID

pg_largeobject

系统表保存了那些标记为

large object(大对象)

的数据。每个

大对象

都会关联其被创建成功时分配的

OID

标志。此后

大对象

都分解成足够小的数据块并关联

pageno

字段来存储

pg_largeobject

里。每页的数据定义为

LOBLKSIZE(目前是BLCKSZ/4或者通常是 2K 字节)

该过程需使用

lo_import

函数,举例如下:

在Windwos场景下这里我们还可以使用

UNC路径

,如果使用该项技术则可跳过3.3,但我希望兼容Unix/Windows平台,所有没有使用。

2. 基于

OID

来进行数据替换

现在,我们基于

OID

的值来替换

pg_largeobject

表中的数据,将其对应内容替换为我们的恶意代码。这些

恶意代码

最终需要基于目标数据库的完整版本来进行编译还要匹配对应的系统架构。对于超过2048字节大小的文件,

pg_largeobject

表需使用

pageno

字段来将文件分割成大小为2048字节大小的数据块。分割示例如下:

通过使用PostgreSQL中的

object identifier types

,可以跳过第1阶段(并且仅对第2阶段执行单个语句执行),但是我没有时间确认这一点。

3. 使用

lo_export

函数生成恶意动态库

现在我们可以通过

lo_export

来转储之前变相导入的数据来生恶意的动态库文件。不过这一步不能指定目录,因为这样做会触发

PostgreSQL

内置的安全检查,而且就算能绕过该检查,

NETWORK_SERVICE

(Unix/Linux场景下为

postgres

)帐户也存在路径限制,搞不定搞不定。

4. 基于恶意动态库文件创建函数

我在以往的研究中提到过,可以使用绝对路径(包括

UNC

)来加载基于

Postgresql 9.x

的扩展从而执行系统命令。

@zerosum0x0

师傅也有相关的 操作笔记 。不过那个时候对系统用户的文件操作权限并没有那么多的限制。

如今几年过去了,PostgreSQL官方决定禁用

CREATE FUNCTION

时使用绝对路径导致现在这种技术已经失效了。不过现在我们可以很方便地从对应的默认动态库目录中遍历并加载我们转储的恶意动态库文件,举例如下:

4. 反弹shell

成功创建

connect_back

函数后,直接通过

select

指令来调用:

  问题现状

ZDI团队

咨询过PostgreSQL官方对该问题的意见,但无后文,后来我得知官方并不打算修复此问题,因为官方认为该问题属于正常系统功能而不是漏洞。   造个轮子 代码如下,将生成poc.sql文件,以超管用户在数据库上逐步执行,或将poc.sql中的sql命令逐个通过注入点执行:

跑一下展示下效果:

译文声明

译文仅供参考,具体内容表达以及含义原文为准。

pg通过自定义函数_Pgsql堆叠注入场景下通过`CREATE FUNCTION`来实现命令执行

戳“阅读原文”查看更多内容