【sqli-labs】闯关记录17~20
【less-17】基于密码的报错注入
1、源码分析
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,15); //只取输入值的前15个字符
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc()) //该函数是获取magic_quotes_gpc状态
{
$value = stripslashes($value); //删除由addslashes()添加的反斜杠
}
// Quote if not a number
if (!ctype_digit($value)) //判断是否都是数字
{
$value = "'" . mysql_real_escape_string($value) . "'"; //转义字符\x00,\n,\r,\,',",\x1a
}
else
{
$value = intval($value); //返回变量$value的int值
}
return $value;
}
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
//making sure uname is not injectable
$uname=check_input($_POST['uname']); //只对用户名的输入做了转义
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname."\n");
fwrite($fp,'New Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username= $uname LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
//echo $row;
if($row) //要想进入if语句,必须知道一个正确的用户名
{
//echo '<font color= "#0000ff">';
$row1 = $row['username'];
//echo 'Your Login name:'. $row1;
$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";
mysql_query($update);
echo "<br>";
if (mysql_error())
{
echo '<font color= "#FFFF00" font size = 3 >';
print_r(mysql_error()); //输出错误
echo "</br></br>";
echo "</font>";
}
else
{
echo '<font color= "#FFFF00" font size = 3 >';
//echo " You password has been successfully updated " ;
echo "<br>";
echo "</font>";
}
echo '<img src="../images/flag1.jpg" />';
//echo 'Your Password:' .$row['password'];
echo "</font>";
}
else
{
echo '<font size="4.5" color="#FFFF00">';
//echo "Bug off you Silly Dumb hacker";
echo "</br>";
echo '<img src="../images/slap1.jpg" />';
echo "</font>";
}
}
?>
get_magic_quotes_gpc()
函数:获取magic_quotes_gpc状态,判断是否自动对传入的参数做了转义,该函数已经从php7起就废弃了。
ctype_digit(text)
函数:判断字符串是否全为数字,是则返回True,否则返回false.
mysql_real_escape_string()
函数:转义字符\x00,\n,\r,,’,",\x1a
intval($value)
函数:返回变量$value的int值,默认是10进制, intval() 不能用于 object,否则会产生 E_NOTICE
错误并返回 1。
从上面的代码分析可知,后端只对用户名的输入做了转义处理,而且如果用户名校验成功后就直接更改密码了,对密码并没有做任何处理,就直接拼接到sql语句中执行了,存在明显的sql注入漏洞。
2、漏洞利用思路:
可以使用burp暴力破解用户名,拿到正确的用户名后直接对password进行sql注入
设置uname为变量 | 设置字典 |
---|---|
开始攻击 | 攻击结果 |
---|---|
如图所示,爆破出一个用户名为admin.
如图所示,可以任意更改admin用户的密码。
//接下来拿着正确的用户名admin,对password进行sql注入
password字段输入单引号报错
从报错信息来看后端是单引号闭合。
尝试全集更新:password输入123456' or 1=1#
如图所示,密码全部更新为1。因为后端的逻辑是UPDATE users SET password = '123456' or 1=1# WHERE username='admin'
,因为'123456' or 1=1
恒为真,所以给password赋值为1,所以全集password字段更新为1。
//可以使用报错注入,一步步脱裤。
123' and updatexml(1,concat(0x7e,user(),database(),version()),2)#
【less-18】基于http头user-Agent字段注入
1、源码分析
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
function check_input($value)
{
if(!empty($value))
{
// truncation (see comments)
$value = substr($value,0,20);
}
// Stripslashes if magic quotes enabled
if (get_magic_quotes_gpc())
{
$value = stripslashes($value);
}
// Quote if not a number
if (!ctype_digit($value))
{
$value = "'" . mysql_real_escape_string($value) . "'";
}
else
{
$value = intval($value);
}
return $value;
}
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
echo "<br>";
echo 'Your IP ADDRESS is: ' .$IP;
echo "<br>";
//echo 'Your User Agent is: ' .$uagent;
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']); //对用户名和密码都进行了转义
/*
echo 'Your Your User name:'. $uname;
echo "<br>";
echo 'Your Password:'. $passwd;
echo "<br>";
echo 'Your User Agent String:'. $uagent;
echo "<br>";
echo 'Your User Agent String:'. $IP;
*/
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Agent:'.$uname."\n");
fclose($fp);
$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)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)"; //$uagent和$IP字段并未做处理,明显存在sql注入漏洞
mysql_query($insert);
//echo 'Your IP ADDRESS is: ' .$IP;
echo "</font>";
//echo "<br>";
echo '<font color= "#0000ff" font size = 3 >';
echo 'Your User Agent is: ' .$uagent;
echo "</font>";
echo "<br>";
print_r(mysql_error());
echo "<br><br>";
echo '<img src="../images/flag.jpg" />';
echo "<br>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
?>
$_SERVER
是 PHP 预定义变量之一,可以直接使用,它是一个包含了诸如头信息(header)、路径(path)及脚本位置(script locations)信息的数组。详细
$_SERVER[‘SERVER_ADDR’] 当前运行脚本所在服务器的 IP 地址 $_SERVER[‘REMOVE_ADDR’] 浏览当前页面的用户 IP 地址,注意与 $_SERVER[‘SERVER_ADDR’] 的区别 $_SERVER[‘HTTP_USER_AGENT’] 其中需要检查用户的 agent 字符串,它是浏览器发送的 HTTP 请求的一部分。
有上述代码可知,后端对用户名和密码均作了转义,绕过难度比较大。但是登录校验成功后,没有对$uagent字段(请求头中的User-Agent字段)做过滤就直接拼接在insert语句中,明显存在sql注入漏洞。
在后面的代码中,将$uagent字段未做过滤直接输出到页面中,存在反射型xss漏洞,攻击者可以利用并盗取用户cookie.
2、漏洞利用
1、基于insert报错注入:
构造payload | 成功爆出数据库名 |
---|---|
后台sql拼接逻辑:
INSERT INTO security
.uagents
(uagent
, ip_address
, username
) VALUES (‘xiamo’ or updatexml(1,concat(0x7e,database()),0) or’’, ‘$IP’, $uname)
2、反射型xss测试:
插入payload | 成功弹窗 |
---|---|
【less-19】基于http头referer字段注入
1、测试流程
测试过了用户名和密码,都无法注入
先登录看看
如图所示,据此判断注入点可能在http头的referer字段
用burp抓包测试:
输入单引号测试 | 报错判断出闭合方式为’) |
---|---|
报错注入payload:' or extractvalue(1,concat(0x7e,user())) or '
基于insert报错注入 | 成功爆出用户名 |
---|---|
//xss测试:
插入payload | 弹窗成功 |
---|---|
2、源码分析
没有新增函数
【less-20】基于cookie的注入
1、测试流程
试过了用户名和密码框都不行
登录进来看看:
发现有一个button,是用来删除cookie的,初步判断可能是一个基于delete的报错注入。
点击delete,用burp抓包看看:
猜测后端sql语句是:delete from 表名 where uname=’$uname’
于是构造payload:' or updatexml(1,concat(0x7e,version()),2) '
拼接后的sql语句为:delete from 表名 where uname=’’ or updatexml(1,concat(0x7e,version()),2) ‘’
插入payload | 没有成功 |
---|---|
报错显示sql中有limit语句,并且是单引号闭合的。
于是猜测后端应该是select语句
重新构造payload:1' and 1=2 union select user(),database(),version()#
插入payload | 成功! |
---|---|
2、源码分析
没有新增的函数,只是在后端没有对cookie字段值进行过滤。