PHP代码审计分段讲解(5)
11 sql闭合绕过
源代码为
<?php if($_POST[user] && $_POST[pass]) { $conn = mysql_connect("*******", "****", "****"); mysql_select_db("****") or die("Could not select database"); if ($conn->connect_error) { die("Connection failed: " . mysql_error($conn)); } $user = $_POST[user]; $pass = md5($_POST[pass]); //select user from php where (user='admin')# //exp:admin')# $sql = "select user from php where (user='$user') and (pw='$pass')"; $query = mysql_query($sql); if (!$query) { printf("Error: %s\n", mysql_error($conn)); exit(); } $row = mysql_fetch_array($query, MYSQL_ASSOC); //echo $row["pw"]; if($row['user']=="admin") { echo "<p>Logged in! Key: *********** </p>"; } if($row['user'] != "admin") { echo("<p>You are not admin!</p>"); } } ?>
POST方式传入user和pass的值,同时连接数据库
if($_POST[user] && $_POST[pass]) { $conn = mysql_connect("*******", "****", "****"); mysql_select_db("****") or die("Could not select database"); if ($conn->connect_error) { die("Connection failed: " . mysql_error($conn)); } $user = $_POST[user]; $pass = md5($_POST[pass]);
将pass的值使用md5处理重新赋值,接着使用sql语句进行查询
$sql = "select user from php where (user='$user') and (pw='$pass')";
查询成功后进入判断
if($row['user']=="admin") { echo "<p>Logged in! Key: *********** </p>"; }
这里可以看到,登录的时候只对查询出结果里面的user进行了判断,当其的值为admin的时候,登录成功,并没有进行密码的校验
所以我们只需要闭合前面的SQL查询语句,令user=admin即可
所以payload为:
admin')#
密码输入什么都无所谓
sql语句最后变成了这样:
$sql = "select user from php where (user='admin')#') and (pw='$pass')";
也就是
$sql = "select user from php where (user='admin')
登录即可获取flag
12 X-Forwarded-For绕过指定IP地址
源代码为:
<?php function GetIP(){ if(!empty($_SERVER["HTTP_CLIENT_IP"])) $cip = $_SERVER["HTTP_CLIENT_IP"]; else if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) $cip = $_SERVER["HTTP_X_FORWARDED_FOR"]; else if(!empty($_SERVER["REMOTE_ADDR"])) $cip = $_SERVER["REMOTE_ADDR"]; else $cip = "0.0.0.0"; return $cip; } $GetIPs = GetIP(); if ($GetIPs=="1.1.1.1"){ echo "Great! Key is *********"; } else{ echo "错误!你的IP不在访问列表之内!"; } ?>
第一次遇到伪造IP的题目是在BugKu的做题平台上,这里的代码使用HTTP头里面的IP信息来进行IP访问列表的判断,而HTTP头的信息是可以通过我们抓包改变的。
这里我们跟题目一样,使用X_FORWARDED_FOR来进行IP的伪造
在请求头里面添加:X-Forwarded-For: 1.1.1.1
即可获取flag
13 md5加密相等绕过
<?php $md51 = md5('QNKCDZO'); $a = @$_GET['a']; $md52 = @md5($a); if(isset($a)){ if ($a != 'QNKCDZO' && $md51 == $md52) { echo "nctf{*****************}"; } else { echo "false!!!"; }} else{echo "please input a";} ?>
将 QNKCDZO MD5加密后,使用GET方式传入a的值,将a进行MD5加密,获取flag的条件为:
if ($a != 'QNKCDZO' && $md51 == $md52) {
传入的a不能为QNKCDZO,有需要令两者的md5加密后的值相等,这里需要用到MD5碰撞的知识
我们重新梳理一遍代码
$md51 = md5('QNKCDZO');
获得的md51的值为
0e830400451993494058024219903391
有意思的地方在于,这串字符串转换成为数字的话,按照科学计数法,它是0的830400451993494058024219903391次方,虽然看上去很大,但是由于底数为0,所以结果也是0,而比较两个md5值的时候是
$md51 == $md52
两个等号时会先进行类型转换,所以我们只需要找到一个md5值也是0e开头的字符串即可,这样它的md5加密结果科学计数法也会是0
当然这个也不需要找了,因为已经有大佬找好了:
https://blog.csdn.net/qq_38603541/article/details/97108663
获得flag