SQL手注入门

导语

SQL注入漏洞作为臭名昭著的漏洞,已经有很多全自动攻击的工具了,但是我们是优秀的同学,我们要会用工具,还知道工具的原理。

寻找SQL注入漏洞

SQL注入常常出现在可以传递参数的位置,包括URL参数、搜索框、目录名、文件名等等,很多马虎的管理者因为对参数的过滤不严导致被攻击者所利用。
常见判断是否存在注入的语句有
数字型:

and 1=1/and 1=2
or 1=1/or 1=2
\+ \- \* / \> < < = \> = \*
1 like1/1 like 2

字符型:

and '1'='1 /and '1'='2
or '1'='1/or '1'='2
+' /+' -' /-' \> < <= \>=
1' like '1/1' like '2

只要我们对sql语句的掌握够深,类似的判断语句还很多

实战学习

用了ctfhub的sql注入题目。
首先整数型注入,按照提示输入个1

下面也显示了对应的语句,但是我们发现他是select *,我们的注入语句是显示所有的查找到的条目,可是这里只返回了一条语句,猜测经过处理只显示一个条目。于是我们使用limit来验证猜测

这条语句理论上应该返回3个条目或者报错,然而却只返回一个条目,因此我们的猜测是正确的。解决的问题也简单,我们只要输入一个不存在的id,这时后端查找到的是NULL,于是就可以显示我们的union select的内容了。
接下来我们使用order by来判断条目的字段数量。


在3的时候就没有回显了,我们也可以判断出后端做了处理不显示报错信息。
接下来我们应该使用union来判断条目的字段对应显示在那个位置,但是我们一共就俩字段,可以判断,但没必要。
直接看数据库名

得到数据库的名字是sqli
然后information_schema3连



顺利得到flag。

常见的获取敏感信息的函数

user()                      数据库用户名
current_user()              当前数据库用户名
database()                  数据库名
version()                   MYSQL数据库版本
@@datadir                   读取数据库路径
@@basedir                   MYSQL安装路径
@@version_compile_os        获取操作系统版本
load_file()                 MYSQL读取本地文件的函数

举一反三

那么我们就基本可以总结书sql注入的普遍思路了。

  1. 判断是否有注入点
  2. 使用order by来判断返回的条目的字段数量
  3. 使用union判断每个字段的显示位置
  4. 使用database()等函数获取有用的信息
  5. 大声叫喊奥利给!

盲注

盲注和注入的最大区别在于他不会返回给你东西,只会在出错的时候报错或者显示不正常,因此盲注的payload通常类似下面
id=1 and (select length(database()))>4 //判断数据库名称的长度
id=1 and select ascii(substr(database(),1,1))>119 //判断数据库名第一个字符的ascii码
基本上除了比注入麻烦好多以外没什么特别难的

报错注入

报错注入也是查询结果不给显示的时候使用的,主要依赖floor() extractvalue()(updatexml())函数

floor()的报错注入

准确地说应该是floor()、rand()、group by的报错注入。
我们看下面这句

select count(*),(concat(floor(rand(0)*2),'@',(select version())))x from users group by x

rand()函数的作用是随机生成一个0~1的数字,他还能接受一个seed的参数作为随机种子。rand(0)就是生成一个伪随机序列,自己试一下可以发现他是0110110。
而报错的主体是group by。
group by会形成一个虚拟表,首先以group by后面的表项作为主键,扫描select的每一个条目,将具有相同的主键的两个表项合并。这个过程对主键进行了两次运算。第一次是获取主键,第二次是向虚拟表中插入这个表项的时候。
在我们这个例子里,报错的过程大概是这样

  1. 获取主键的名称,扫描users表的第一项,假设我们的数据库版本号是5.7.19,根据rand(0)的序列,x的值为0@5.7.19(user只是单纯的提供我们能进行几次x的插入的工具表),此时虚拟表是空的,发现不存在这个条目,于是向其中添加一个条目,此时再次运算x的值为1@5.7.19,那么此时这个虚拟表如下
xcount(*)
1@5.7.19count(*)
  1. 扫描下一个,获取主键,这里应该是1@5.7.19,发现在表里有,因此表变为(count(*)函数是统计有多少行的,null也包含,实际上就是个占位的。主键是1@5.7.19。)
xcount(*)
1@5.7.19count(*)

3.再下一个,主键是0@5.7.19,表内没有这个值,因此要插入
但是 ,插入表的时候再次计算得到x是1@5.7.19,也就是要往表里再插入一条1@5.7.19,count(*)的条目,由于主键是唯一的,所以必然会报错,这一条的结果也就返回了出来。

看到这里,相信大家都懂了,那么就有人要问了,万一我的user表不够长咋办啊?gnls你user表连三项都没有你这小破站是干啥的?那你去找个seed能生成0101或者1010序列的⑧

extractvalue()

extractvalue() :对XML文档进行查询的函数,其实就是相当于我们熟悉的HTML文件中用 <div><p><a>标签查找元素一样。
语法:extractvalue(目标xml文档,xml路径)
第二个参数 xml中的位置是可操作的地方,xml文档中查找字符位置是用 /xxx/xxx/xxx/…这种格式,如果我们写入其他格式,就会报错,并且会返回我们写入的非法格式内容,而这个非法的内容就是我们想要查询的内容。
直接使用~/XXX的非法格式

select username from security.user where id=1 and (extractvalue(‘anything’,concat(‘~’,(select database()))))

于是他就会报错返回想要的内容。
此外还有updatexml()函数有相同的用法,只要把xml路径改成不合法的格式即可。

select username from security.user where id=1 and (updatexml(‘anything’,concat(‘~’,(select database())),’anything’))

参考
https://blog.csdn.net/qq_41059320/article/details/89281125
https://blog.csdn.net/he_and/article/details/80455884
https://blog.csdn.net/zpy1998zpy/article/details/80631036

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值