php代码审计题目总结

[HCTF 2018]WarmUp 1

拿道题发现了一个图片,我们直接bp:
发现了一个source.php应该就是源码
在这里插入图片描述
在这里插入图片描述
发现了一个hint.php,进去后:在这里插入图片描述
先来看源码:

 <?php
    highlight_file(__FILE__);
    class emmm
    {
        public static function checkFile(&$page)
        {
            $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
            if (! isset($page) || !is_string($page))//判断$page是否为空以及是否为字符串 {
                echo "you can't see it";
                return false;
            }

            if (in_array($page, $whitelist)) //判断whitelist中是否有page的值,这是in_arry()函数的作用{
                return true;
            }

            $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );//截取变量$page首次出现?之前的值
            if (in_array($_page, $whitelist)) {
                return true;
            }

            $_page = urldecode($page);
            $_page = mb_substr(
                $_page,
                0,
                mb_strpos($_page . '?', '?')
            );
            if (in_array($_page, $whitelist)) {
                return true;
            }
            echo "you can't see it";
            return false;
        }
    }

    if (! empty($_REQUEST['file'])//判断file是否为空
        && is_string($_REQUEST['file'])//判断file是否为字符串
        && emmm::checkFile($_REQUEST['file'])//调用checkFile函数来检查变量file
    ) {
        include $_REQUEST['file'];
        exit;
    } else {
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
    }  
?> 

代码审计:

isset() 函数定义和用法: isset — 检测变量是否已设置并且非 NULL

mb_substr()定义和用法: mb_substr() 函数返回字符串的一部分,之前我们学过 substr()
函数,它只针对英文字符,如果要分割的中文文字则需要使用 mb_substr()

mb_strpos (haystack ,needle ): haystack:要被检查的字符串。 needle:要搜索的字符串。 (PHP >= 4.0.6, PHP 5, PHP 7) mb_strpos — 查找字符串在另一个字符串中首次出现的位置。

例如:

<?php > header("Content–type:text/html;chartset=utf-8");//中文查找中,尽量要声明一下页面的编码为UTF-8 > $str = 'Rose.io博客'; echo mb_strpos($str,'io'); ?> 输出结果为:5
该题中:
     $_page = mb_substr(
                $page,
                0,
                mb_strpos($page . '?', '?')
            );
先来看mb_strpos($page . '?', '?')
输出page变量中`?`所在的位置
那么这一小段代码的意思就是输出page变量中从0开始到第一个?所在位置结束前的值。

in_array(value,array,type):
参数:
value 必需。规定要在数组搜索的值。
array 必需。规定要搜索的数组。
type 可选。如果设置该参数为 true,则检查搜索的数据与数组的值的类型是否相同。
如果给定的值 value 存在于数组 array 中则返回 true。如果第三个参数设置为 true,函数只有在元素存在于数组中且数据类型与给定值相同时才返回 true。
如果没有在数组中找到参数,函数返回 false。
注释:如果 value 参数是字符串,且 type 参数设置为 true,则搜索区分大小写。

本题:
if (in_array($_page, $whitelist))
{
return true;}

判断 w h i t e l i s t 中 是 否 存 在 whitelist中是否存在 whitelistpage的值

那么开始绕过吧:
只需要让那些if语句返回true
根据提示,flag在ffffllllaaaagggg中,四层目录,%253f是将?经过两次url编码后得到的结果,在服务器接受参数时会进行一次url解码,执行checkFile()函数时再次进行url解码,其实在这里不对?进行编码也是可以的,那么构建payload:

?file=source.php%253f/../../../../ffffllllaaaagggg

flag{a40d629e-0f4c-4388-b0aa-ed082f59e947}

ezBypass

题目链接

 <?php 
error_reporting(1);
highlight_file(__FILE__);
include('flag.php');

if ($_GET["shy1"] != hash("md4", $_GET["shy1"]))
{
    echo "<br>";
    die('Theshy is locked');
}

if (isset($_GET['shy2'])) {
    $message = json_decode($_GET['shy2']);
    $password ="*********";
    if ($message->password == $password) {
            $s = $_SERVER['QUERY_STRING'];
            if( substr_count($s, '_') !== 0 || substr_count($s, '%5f') != 0 ){
                exit('hahahahahaha!');
        }
         if($_GET['s_h_y_3'] !== '857857' && preg_match('/^857857$/', $_GET['s_h_y_3'])){
                echo $flag;
        }
    } 
    else {
        echo "NONONO";
    }
 }
 else{
     echo "GOGOGO";
 }

?> 

需要我们去绕过这几个if语句
md4绕过

if ($_GET["shy1"] != hash("md4", $_GET["shy1"]))
{
    echo "<br>";
    die('Theshy is locked');
}

md4可以使用科学计数法绕过。我们需要找一个明文是一个科学计数法0e开头的,其加密后密文仍然为0e开头的。

令shy1=0e251288019,

md4后为:0e874956163641961271069404332409

payload:?shy1=0e251288019

成功绕过!

json_decode编码绕过

if (isset($_GET['shy2'])) {
    $message = json_decode($_GET['shy2']);
    $password ="*********";

我们传入的shy2变量会经过json编码,变量password是一串字符串。

json_encode() 对PHP 变量进行json编码,转换为字符串类型的json对象

json_decode() 对 JSON 格式的字符串进行编码并且把它转换为 PHP 变量
例如:

<?php
$a=array('password'=>'123');
var_dump(json_encode($a));
?>

在这里插入图片描述
“= =”与“= = =”比较操作符问题
php有两种比较方式,一种是“= =”一种是“= = =”这两种都可以比较两个数字的大小,但是有很明显的区别。
“= =”:会把两端变量类型转换成相同的,在进行比较。这个是根据字符类型强制转换来定义的,int类型的字节数大于char类型的字节数,强制转换的过程中不会损失信息
“= = =”:会先判断两端变量类型是否相同,在进行比较。
在两个相等的符号中,一个字符串与一个数字相比较时,字符串会转换成数值。
那么password就会被强制转换成数值0。

payload:shy2={"password":0}

弱类型绕过

 if ($message->password == $password) {
            $s = $_SERVER['QUERY_STRING'];    
            if( substr_count($s, '_') !== 0 || substr_count($s, '%5f') != 0 ){
                exit('hahahahahaha!');
        }
           if($_GET['s_h_y_3'] !== '857857' && preg_match('/^857857$/', $_GET['s_h_y_3'])){
                echo $flag;   
        }

substr_count($s,’_’):输出变量s中出现下划线的次数。
在URL中GET请求当输入.或空格或_都会被忽略,所以s_h_y_3即s h y 3或s.h.y.3,这两个都可行。
^是用来匹配字符串的开始位置
$是用来匹配字符串的结束位置
相当于一个限定条件,也就是以8开始,以7结尾
变量不能等于857857但是正则匹配需要匹配到857857才会输出flag。
url的%0a为换行污染,可以绕过正则:
payload:s.h.y.3=857857%0a

最终的payload为:

?shy1=0e251288019&shy2={"password":0}&s.h.y.3=857857%0a
在这里插入图片描述

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值