记录SQL靶场的代码审计学习。
sqli-Less-1
原代码:
<?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";}
?>
漏洞点在于:
(1)参数的输入
if(isset( $_GET[‘id’]))
{
$id= $_GET[‘id’];
(2)使用拼接来进行SQL语句查询
$ sql=“SELECT * FROM users WHERE id=’ $id’ LIMIT 0,1”;
(3)明文密码的直接输出
if( $row){
echo “< font size=‘5’ color= ‘#99FF00’>”;
echo ‘Your Login name:’. $ row[‘username’];
echo “< br>”;
echo ‘Your Password:’ .$row[‘password’];
echo “< /font>”;
}
SQL注入存在的原因是对用户输入的$id没有进行任何过滤,在进行SQL语句查询的时候,也是直接进行字符串的拼接。
防御,参数化查询:
①
$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
②
$stmt = $mysqli->prepare('SELECT * FROM users WHERE id = ?');
sqlib-Less-2
与第一关类似:
$ sql=“SELECT * FROM users WHERE id=$id LIMIT 0,1”;
看SQL查询语句,参数id的值为数字型。
sqlib-Less-3
$ sql=“SELECT * FROM users WHERE id=(‘$id’) LIMIT 0,1”;
与上一关的区别,参数闭合方式
sqlib-Less-4
$ sql=“SELECT * FROM users WHERE id=($id) LIMIT 0,1”;
与上一关的区别,参数闭合方式
sqlib-Less-5
原代码:
<?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";}
?>
漏洞点:
print_r(mysql_error());
相比上面的几关,第五关没有进行明文密码的输出,但存在一个报错回显的函数。
sqlib-Less-6
print_r(mysql_error());
与上一关的区别,参数闭合方式不同
sqlib-Less-7
原代码:
<?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";}
?>
漏洞成因:
if($row)
{echo 'You are in.... Use outfile......';}
else
{echo 'You have an error in your SQL syntax';}
虽然还是直接拼接的SQL参数查询,但代码中没有涉及报错信息的回显,也没有将密码以明文形式输出,但在代码中存在一个if语句,如果输入的内容不正确,会出现错误提示:‘You have an error in your SQL syntax’。据此可以进行布尔盲注。
sqlib-Less-8
echo ‘You are in… Use outfile…’;
同上一关,参数闭合方式不同
sqlib-Less-9
if($row)
{echo ‘You are in… Use outfile…’;}
else
{echo ‘You are in… Use outfile…’;}
页面没有错误回显,也不存在页面变化,但参数的输入因为没有进行过滤(直接拼接到SQL查询语句),可以利用时间盲注。
sqlib-Less-10
与上一关的区别,参数闭合方式
sqlib-Less-11
原代码:
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
// take the variables
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname=$_POST['uname'];
$passwd=$_POST['passwd'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'User Name:'.$uname);
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);
// connectivity
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
if($row)
{
//echo '<font color= "#0000ff">';
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
//echo " You Have successfully logged in\n\n " ;
echo '<font size="3" color="#0000ff">';
echo "<br>";
echo 'Your Login name:'. $row['username'];
echo "<br>";
echo 'Your Password:' .$row['password'];
echo "<br>";
echo "</font>";
echo "<br>";
echo "<br>";
echo '<img src="../images/flag.jpg" />';
echo "</font>";
}
else
{
echo '<font color= "#0000ff" font size="3">';
//echo "Try again looser";
print_r(mysql_error());
echo "</br>";
echo "</br>";
echo "</br>";
echo '<img src="../images/slap.jpg" />';
echo "</font>";
}
}
?>
漏洞点:
@ $ sql=“SELECT username, password FROM users WHERE username=’ $uname’ and password=’ $passwd’ LIMIT 0,1”;
参数没有过滤,密码明文输出,SQL参数直接拼接查询,POST传参,闭合后直接进行显注。
sqlib-Less-12
与上一关的区别,参数闭合方式不同
sqlib-Less-13
if($row)
{…}
else
{print_r(mysql_error());}
数据库获取的内容无法直接显示,但代码存在有报错信息回显的函数,报错注入。
sqlib-Less-14
与上一关的区别,参数闭合方式不同
sqlib-Less-15
if($row)
{
echo "<br>";
echo '<font color= "#FFFF00" font size = 4>';
echo '<font size="3" color="#0000ff">';
}
else
{
echo '<font color= "#0000ff" font size="3">';
//print_r(mysql_error());
}
}
报错函数被注释,但登录失败与成功的页面回显不同,使用布尔盲注。
sqlib-Less-16
与上一关的区别,参数闭合方法不同
sqlib-Less-17
原代码:
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);
if($row)
{
//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
{...}
...
}
else
{...}
}
?>
输入的参数没有做过滤,参数直接拼接到SQL查询语句,有报错信息的回显,使用报错注入。
sqlib-Less-18
原代码:
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
echo "<br>";
echo 'Your IP ADDRESS is: ' .$IP;
echo "<br>";
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
//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)
{
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
echo 'Your User Agent is: ' .$uagent;
print_r(mysql_error());
}
else
{print_r(mysql_error());}
}
?>
对于用户名和密码的输入做了验证,不存在注入点
$ uname = check_input( $_POST[‘uname’]);
$ passwd = check_input($_POST[‘passwd’]);
漏洞成因:
(1)参数uagent的的输入没有做过滤
$uagent = $_SERVER['HTTP_USER_AGENT'];
$IP = $_SERVER['REMOTE_ADDR'];
echo 'Your IP ADDRESS is: ' .$IP;
(2)SQL插入语句直接拼接
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
#只有当用户名和密码输入都正确时,才会将ip和uagent的值插入到数据库中
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
mysql_query($insert);
echo 'Your User Agent is: ' .$uagent;
(3)报错信息回显函数
print_r(mysql_error()
存在报错注入,但注入点在uagent
sqlib-Less-19
$insert="INSERT INTO `security`.`referers` (`referer`, `ip_address`) VALUES ('$uagent', '$IP')";
mysql_query($insert);
echo 'Your Referer is: ' .$uagent;
和上一关的区别在于,页面显示的数据来自referer字段,注入点也在referer位置。
sqlib-Less-20
#对cookie的值没有做过滤
if(!isset($_COOKIE['uname']))
#用户名和密码还是做了过滤
if(isset($_POST['uname']) && isset($_POST['passwd']))
{
$uname = check_input($_POST['uname']);
$passwd = check_input($_POST['passwd']);
}
#发现SQL查询语句中,直接拼接的cookie参数
$sql="SELECT * FROM users WHERE username='$cookee' LIMIT 0,1";
在cookie处存在报错注入
sqlib-Less-21
if(!isset($_COOKIE['uname']))
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1";
#本来以为只是闭合方式不同,后面抓完包,发现还多了个base64的加密
setcookie('uname', base64_encode($row1['username']), time()-3600);
#又去看了19关的代码,发现cookie没有经过加密
setcookie('uname', $row1['username'], time()-3600);
和上一关的区别,闭合方式不同,使用了base64加密
sqlib-Less-22
if(!isset($_COOKIE['uname']))
$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';
echo "<br></font>";
$sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
与上一关的区别,闭合方式不同。
sqlib-Less-23
if(isset($_GET['id']))
{
$id=$_GET['id'];
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
}
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
对参数id的输入内容做了过滤,将以下三种字符做了过滤:
.#
–+
空格
相当于把闭合符给过滤掉了,需要绕过。
将最后一个字段作为输入闭合
or关键词绕过
(详细绕过姿势,见上篇博客)
sqlib-Less-24
$username = mysql_real_escape_string($_POST["login_user"]);
$password = mysql_real_escape_string($_POST["login_password"]);
$sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
方法1:
mysql_real_escape_string()函数对特殊字符做了转义,这里可以用宽字节注入%df
方法2:
在密码修改处,没有对username的输入进行转义,可进行二次注入
$username= $_SESSION["username"];
sqlib-Less-25
#黑名单防御
$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
#and和or字段被过滤
function blacklist($id)
{
$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
$id= preg_replace('/AND/i',"", $id); //Strip out AND (non case sensitive)
return $id;
}
绕过:大小写、双写,&&和||
0~15关代码审计,详细见大佬文章:
sql注入——php源码的审计(以sql-lab 1~15为例)(超详细)
后续待更新……