十八关(POST-Header Injection - uagent field - Error based)
User-Agent头部注入,先不解释
先看一下页面,页面上反馈了我的IP地址
接着登录看一下吧,登录后发现,页面又回馈了一条信息,返回了我的User-Agent,那这个User-Agent是什么呢,是http请求里面的一个字段,提交的数据是你的浏览器指纹,用于给服务器判断你的浏览器类型的
比如你用手机访问站点,服务器就根据你的User-Agent返回手机端的页面。如果有人写过爬虫,那应该知道。网站会返回你的User-Agent的话,那就说明网站可能与数据库发生了交互。记住一句话,“一切与数据库发生交互的地方都可能存在sql注入”。
这一关需要在User-Agent字段里构造sql语句,所以,我们需要使用burpsuite来进行抓包(没用过的自己百度吧)。这是数据包
那我们来User-Agent中构造一下,先随便改为一个值111
,看网站会不会正常返回数据包。
正常返回了,接着我们尝试在User-Agent字段中构造sql注入语句,看会不会有报错信息,在输入单引号时,产生报错信息
但是吧,这个信息看起来不够简洁明了,不过我们可以先来猜测一下语句,出现问题的部分是192.168.1.102','admin')
,那根据我们前面学到的select和update来看,感觉都不太像,那除了这两个还有啥呢,还有增insert
,删delete
。我们不妨来看一下这几种数据库语句的语法语法。
增
INSERT INTO table_name ( field1, field2,...fieldN ) VALUES ( value1, value2,...valueN );
删
DELETE FROM table_name [WHERE Clause]
改
UPDATE table_name SET field1=new-value1, field2=new-value2 [WHERE Clause]
查
SELECT column_name,column_name FROM table_name [WHERE Clause] [LIMIT N] [ OFFSET M]
这样看起来,这个地方最有可能的就是一个插入语句,我们构造一下,虽然不知道有几个字段,但是我们从后往前推,可以找到我们自己构造的语句的位置。
insert into table_name (.....,xxx,xxx,xxx) values (....,'111'','192.168.1.102','admin');
像这样,我们猜测出语句之后就有思路了,有报错信息就直接先考虑报错注入。可以直接在括号内闭合掉单引号,也可以构造一个完整的插入,再把后边的东西给注释掉,这里同样是三种报错方式都可以用,就不一一演示了。
' or updatexml(1,concat(0x7e,(database()),0x7e),0) or '
上面这个比较万能
1' or updatexml(1,concat(0x7e,(database()),0x7e),0),1,1)#
十九关(POST -Header Injection - Referer field - Error based)
还是头部注入,不过是在referer字段,判断方法几乎和前一关一模一样,不过居然以外的发现,我在插入数据时使用报错注入,写了很多个字段,也依旧能正常报错出来。
1' ,'sadsa','1','1','1' and updatexml(1,concat(0x7e,(database()),0x7e),0))#
二十关(POST - cookie injections - uagent field - error based)
在Cookie字段的注入,还是和前面差不多,不过这一关有两个请求的数据包,可以看到第一个数据包是没有Cookie字段的。所以我们需要在第二个数据包里面的Cookie字段中构造sql语句
后续的步骤就与前两关差不多了,不过,这一关是select语句的,且有数据库回显,可以直接使用联合查询。
二十一关(Cookie injection- base64 encoded-single quotes and parenthesis)
还是Cookie注入,不过是base64编码的
老规矩,我们还是先来登录一下吧,发现还是和前面差不多,但是这个Cookie中的uname值变得比较特别了。
接着,按照上一关的步骤来,但是却会发现,无论我们输入什么字符,都不会报错,而是给我们当成字符串写到Cookie中了。这就不得不联系标题进行思考了,与此同时我们来看一下源码。
if(!isset($_COOKIE['uname']))
{
//.......省略这一段
//如果没有设置cookie,那就输出初始页面
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
setcookie('uname', base64_encode($row1['username']), time()+3600);
print_r(mysql_error());
echo '<img src="../images/flag.jpg" />';
header ('Location: index.php');
}
else
{
print_r(mysql_error());
echo '<img src="../images/slap.jpg" />';
}
}
}
else
{
if(!isset($_POST['submit']))
{
$cookee = $_COOKIE['uname'];
$format = 'D d M Y - H:i:s';
$timestamp = time() + 3600;
echo "YOUR USER AGENT IS : ".$_SERVER['HTTP_USER_AGENT'];
echo "YOUR IP ADDRESS IS : ".$_SERVER['REMOTE_ADDR'];
echo "DELETE YOUR COOKIE OR WAIT FOR IT TO EXPIRE <br>";
echo "YOUR COOKIE : uname = $cookee and expires: " . date($format, $timestamp);
$cookee = base64_decode($cookee);
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
$result=mysql_query($sql);
if (!$result)
{
die('Issue with your mysql: ' . mysql_error());
}
$row = mysql_fetch_array($result);
if($row)
{
echo 'Your Login name:'. $row['username'];
echo 'Your Password:' .$row['password'];
echo 'Your ID:' .$row['id'];
}
else
{
echo '<img src="../images/slap1.jpg" />';
//echo '<img src="../images/Less-20.jpg" />';
}
echo '<center>';
echo '<form action="" method="post">';
echo '<input type="submit" name="submit" value="Delete Your Cookie!" />';
echo '</form>';
echo '</center>';
}
else
{
echo " Your Cookie is deleted";
setcookie('uname', base64_encode($row1['username']), time()-3600);
header ('Location: index.php');
}
$fp=fopen('result.txt','a');
fwrite($fp,'Cookie:'.$cookee."\n");
fclose($fp);
}
我们分析一下流程,首先,总的来看,整个程序有两个分支,一个是没有设置名为uname
的cookie,另一个是设置了。
- 我们访问
index.php
,这时,我们是没有设置cookie 的,于是,就输出了我们所见到的首页上的输入框。 - 我们输出用户名和密码并提交,于是服务器到数据库中进行查询,如果成功查找到对应数据,则给客户端设置一个cookie,cookie值为base64编码的
username
,如果执行出错的话则打印sql错误信息,最后重定向到index.php
。 - 网页被重定向,再次访问了
index.php
,再次进行判定,这次判定到浏览器设置了名为uname
的cookie,于是进入另一个分支。 - 浏览器再次发起请求,服务器取出cookie的值,并且打印出cookie值和cookie的过期时间,也就是这一块儿内容。
- 服务器将取出的cookie值,再进行解码,
$cookee = base64_decode($cookee);
将解码出的数据,作为参数,到数据库中查询,查询成功则返回数据,查询失败则返回错误信息,最后就有了这样的界面。
说完了流程就开始讲方法了,流程和前一关应该是一样的,虽然我没看前一关的源代码,但是,估摸着也就是少了个base64编码解码的过程。
我们既然是在第二个数据包中的Cookie字段构造语句,那也就是从第二个分支入手,我们发送的第二个数据包是这样子的。“%3D”是“=”的url编码。
通过上面的流程我们可以发现,之所以会在cookie位置产生sql注入,是因为服务器取了cookie中的数据,进而与数据库交互,但是却没有防护措施。这中间有个base64解码的过程,所以,我们只需要在第二个数据包中构造sql注入语句,再将其 进行base64编码即可。
burpsuite中自带得有decode模块,可以进行字符串的编码和解码,使用经典的1=1
和1=2
进行判断,出现了不同的结果。
判断出了注入点之后,接下来联合查询一顿操作就好了。
二十二关(cookie lnjection - base64 encoded - double quotes)
这一关,看名字就和前一关差不多,就不讲了
这几关主要都是讲的http头部注入,包括其中的User-Agent
,Refer
,Cookie
字段,除此之外,还涉及到了base64注入,实际上base64注入并没有什么特别之处,只是有时候,服务器将设置的cookie使用了base64编码,所以在SQL注入时,需要在注入时对SQL语句进行编码。
那么有什么方法可以判断一串数据是base64编码呢
- 字符串只可能包含A-Z,a-z,0-9,+,/,=字符
- 字符串长度是4的倍数
- =只会出现在字符串最后,可能没有或者一个等号或者两个等号