php代码审计(二)

第一题

error_reporting(0);

show_source(__FILE__);

$flag = 'you_get_me!';

 

if (isset ($_GET['password'])) {

   if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)

       echo '

You password must bealphanumeric

';

   else if (strpos ($_GET['password'], '--') !== FALSE)

       die($flag);

   else

       echo '

Invalid password

';

}

?>

解题:

1. 知识:isset 函数、strpos函数、ereg函数、die函数

(1)isset函数是检测变量是否设置的函数,若变量不存在或者变量存在但值为NULL,则返回FALSE;若变量存在且值不为NULL,返回TRUE。

(2)ereg函数判断正则表达式,限制变量形式

2. 分析:首先,本题中用GET方式提交password,isset函数监测变量确实被设置则返回TRUE进行下面的操作,否则返回FALSE。接下来用ereg函数判断正则表达式,限制了password的形式只能是一或多个数字、大小写字母,很显然这里面不能有“--”,但是往下看,strpos()对password进行匹配,要求password里面必须有“--”才能输出flag,那么假设我们真的有“--”,接下来执行die,退出程序,所以程序到底是要求我们有“--”还是没有呢?这就很迷啊(无奈脸)。于是我们上网搜索一下ereg这个函数有什么漏洞或者问题。

3. 问题与漏洞:因为ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配。

Payload:

?password=1234%00--

【注】:最后一定要加上“--”,%00前面的是数字或大小写字母

php代码审计(二)_第1张图片

第二题

show_source(__FILE__); 
$a=0; 
$b=0; 
$c=0; 
if (isset($_GET['x1'])) 

        $x1 = $_GET['x1']; 
        $x1=="1"?die("ha?"):NULL; 
        switch ($x1) 
        { 
        case 0: 
        case 1: 
                $a=1; 
                break; 
        } 

$x2=(array)json_decode(@$_GET['x2']); 
if(is_array($x2)){ 
    is_numeric(@$x2["x21"])?die("ha?"):NULL; 
    if(@$x2["x21"]){ 
        ($x2["x21"]>2017)?$b=1:NULL; 
    } 
    if(is_array(@$x2["x22"])){ 
        if(count($x2["x22"])!==2 OR !is_array($x2["x22"][0])) die("ha?"); 
        $p = array_search("XIPU", $x2["x22"]); 
        $p===false?die("ha?"):NULL; 
        foreach($x2["x22"] as $key=>$val){ 
            $val==="XIPU"?die("ha?"):NULL; 
        } 
        $c=1; 


if($a && $b && $c ){ 
    echo 'you get flag!'; 
}else{
echo 'try again!';
}
?>

解题:

1. 知识:isset 函数、switch-case语句、json_decode函数、is_array函数、is_numeric函数、count函数、array_search函数

(1)isset()函数是检测变量是否设置的函数,若变量不存在或者变量存在但值为NULL,则返回FALSE;若变量存在且值不为NULL,返回TRUE。

(2)json_decode()函数是对 JSON 格式的字符串进行解码,接受一个 JSON 编码的字符串并且把它转换为 PHP 变量,参数是待解码的字符串。

(3)is_numeric()函数是检测变量是否为数字或数字字符串的,如果参数是数字和数字字符串则返回 TRUE,否则返回 FALSE。

(4)array_search()函数是在数组中搜索某个键值,并返回对应的键名。如果找到了该值,匹配元素的键名会被返回。如果没找到,则返回FALSE。在PHP 4.2.0 之前,函数在失败时返回NULL而不是 FALSE。

2. 分析:首先通读代码,可以看出最后只有使a,b,c都赋值了才能得到flag。

(1)利用代码的逻辑漏洞可绕过x1

php代码审计(二)_第2张图片

(2)上网可以查到JSON的标准格式


(3)字符串比较0=0,0='aaa'都是可以的,所以x2的x21只要是一个大于2017的数+字母就可以绕过,注意是大于2017

(4)x2的x22要求有两个元素,继续分析,又出现了和第一个题中类似的问题,到底是应该有“XIPU”还是没有没呢?

(5)我想问题应该出在array_search这个函数上,那么上网搜索一下这个函数的漏洞。

3. 问题与漏洞:array_search函数先判断传入的是不是数组,然后循环遍历数组中的每个值,没有的话,每个值转化为int类型,再判断传入的数组有没有。

Payload:

?x1=0&x2={"x21":"2018k","x22":[[4],0]}

php代码审计(二)_第3张图片

第三题

error_reporting(0);

$pass = "xxxxxxxx"; 

$password = $_GET['password']; 

if(strcmp($password,$pass) == 0) 

   echo "flag"; 

}else{

        echo"try again";

}

?>

解题:

1. 知识:strcmp 函数

strcmp函数是二进制安全字符串的比较,如果 str1 小于 str2 返回 < 0; 如果 str1 大于 str2 返回 > 0;如果两者相等,返回 0。

2. 分析:这道题……毫无疑问问题出在字符串比较的函数上,查一下这个函数的漏洞吧

3.问题与漏洞:使用strcmp函数比较会返回0,0==0,那么就会得到flag了

Payload:

?password[]=1

php代码审计(二)_第4张图片


你可能感兴趣的:(PHP)