PHP代码审计系列(五)

文章详细分析了PHP代码中的几个安全审计点,包括数字验证正则表达式绕过、弱类型整数比较绕过、MD5函数验证绕过以及switch语句中的0比较绕过。通过示例代码和绕过payload,展示了如何在这些场景下进行安全防护和潜在的攻击手段。
摘要由CSDN通过智能技术生成

PHP代码审计系列(五)

本系列将收集多个PHP代码安全审计项目从易到难,并加入个人详细的源码解读。此系列将进行持续更新。

数字验证正则绕过

源码如下

<?php

error_reporting(0);
$flag = 'flag{test}';
if  ("POST" == $_SERVER['REQUEST_METHOD']) 
{ 
    $password = $_POST['password']; 
    if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
    { 
        echo 'Wrong Format'; 
        exit; 
    } 
    while (TRUE) 
    { 
        $reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; 
        if (6 > preg_match_all($reg, $password, $arr)) 
            break; 
        $c = 0; 
        $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; 
        //>=3,必须包含四种类型三种与三种以上
        if ("42" == $password) echo $flag; 
        else echo 'Wrong password'; 
        exit; 
    } 
}

?>

通读代码逻辑如下

首先有一个判断,若POST传入的password字符串长度小于12或字符串中存在空格或TAB则输出Wrong Format退出脚本

if (0 >= preg_match('/^[[:graph:]]{12,}$/', $password)) //preg_match — 执行一个正则表达式匹配
    { 
        echo 'Wrong Format'; 
        exit; 
    }

接下来进入死循环

匹配规则为标点符号、数字、大小写字母

$reg = '/([[:punct:]]+|[[:digit:]]+|[[:upper:]]+|[[:lower:]]+)/'; 

若判断匹配规则超过6次直接退出循环

if (6 > preg_match_all($reg, $password, $arr)) 

遍历数组,若password正则匹配(包含三种或三种以上的类型)则变量c增加1

array('punct', 'digit', 'upper', 'lower')
foreach ($ps as $pt) 
        { 
            if (preg_match("/[[:$pt:]]+/", $password)) 
                $c += 1; 
        } 

若c小于3直接退出循环

if ($c < 3) break; 

最后如果判断42==password则输出flag

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

绕过payload

password=42.0e+000000

成功输出flag

在这里插入图片描述

弱类型整数大小比较绕过

源码如下

<?php

error_reporting(0);
$flag = "flag{test}";

$temp = $_GET['password'];
is_numeric($temp)?die("no numeric"):NULL;    
if($temp>1336){
    echo $flag;
} 

?>

通读代码,会将password进行数字判断如果为数字则终止脚本

is_numeric($temp)?die("no numeric"):NULL; 

并且必须大于1336

if($temp>1336){
    echo $flag;
} 

利用弱类型绕过,payload:1337a,在比较时会is_numeric会判断为字符串成功绕过。由于PHP弱类型一个整形和一个其他类型比较时1337a会被转为1337再进行比较

在这里插入图片描述

md5函数验证绕过

源码如下

<?php

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

?>

主要绕过的是这句话

if(md5($temp)==0)

很多都可以绕过

xxx.php?password
xxx.php
xxx.php?password=1
...

md5函数true绕过注入

源码如下

<?php 
error_reporting(0);
$link = mysql_connect('localhost', 'root', 'root');
if (!$link) { 
  die('Could not connect to MySQL: ' . mysql_error()); 
} 
// 选择数据库
$db = mysql_select_db("security", $link);
if(!$db)
{
  echo 'select db error';
  exit();
}
// 执行sql
$password = $_GET['password'];
$sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";
var_dump($sql);
$result=mysql_query($sql) or die('<pre>' . mysql_error() . '</pre>' );
$row1 = mysql_fetch_row($result);
var_dump($row1);
mysql_close($link);
?>

主要绕过的就是以下sql

$sql = "SELECT * FROM users WHERE password = '".md5($password,true)."'";

需要password在md5加密后实现sql注入

例如:

SELECT * FROM admin WHERE pass = ''or'xxx'

而ffifdyop字符串在md5后为

276f722736c95d99e921722cf9ed621c

该hex转换为字符串为

'or'6<trash>

在这里插入图片描述

最终payload=ffifdyop

switch没有break字符与0比较绕过

源码如下

<?php

error_reporting(0);

if (isset($_GET['which']))
{
    $which = $_GET['which'];
    switch ($which)
    {
    case 0:
    case 1:
    case 2:
        require_once $which.'.php';
         echo $flag;
        break;
    default:
        echo GWF_HTML::error('PHP-0817', 'Hacker NoNoNo!', false);
        break;
    }
}

?>

该题在比较which值时,当传入的是字符串(无法转换为数字)在与0比较时为true,而在判断为0时并没有break会直接向下执行到case2输出flag,而不是直接默认default。

payload为包含文件名:?which=xxx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值