Zer0pts2020-Can you guess it

网络安全·CTF · 2023-12-03 · 588 人浏览

一、源码审计

进入靶场,发现有一个表单和源码展示链接。
Pasted image 20220803230355.png
先看源码,进行审计。

include 'config.php'; // FLAG is defined in config.php
if (preg_match('/config\.php\/*$/i', $_SERVER['PHP_SELF']))
{
    exit("I don't know what you are thinking, but I won't let you read it :)");
}

if (isset($_GET['source']))
{
    highlight_file(basename($_SERVER['PHP_SELF']));
    exit();
}
//------------------分界线------------------
$secret = bin2hex(random_bytes(64));
if (isset($_POST['guess']))
{
    $guess = (string) $_POST['guess'];
    if (hash_equals($secret, $guess))
    {
        $message = 'Congratulations! The flag is: ' . FLAG;
    }
    else
    {
        $message = 'Wrong.';
    }
}

$_SERVER['PHP_SELF']存储的是当前运行脚本的路径,源码分界线以上是通过获取$_SERVER['PHP_SELF']中的值来高亮源码的功能,但似乎能进行SSRF,先看分界线以下。

通过生成一个64字节的随机数并转为十六进制数作为密钥,要求用户输入的guess参数与密钥能通过hash_equals()的比较,如果通过则展示flag。

hash_equals函数目前没有什么漏洞,它甚至能防止时序攻击。那么我们只能通过尝试改变$_SERVER['PHP_SELF']来进行SSRF。

假设我们有方法操作$_SERVER['PHP_SELF'],将其赋值为config.php,不过preg_match()函数的匹配成功条件是以config.php结尾的字符串。注意到basename()函数,这个函数有一个漏洞不再赘述,利用这个我们可以绕过preg_match()的死亡exit。

那么如何操作$_SERVER['PHP_SELF']中的值?

Apeach解析问题

这个问题不会出现在Nginx(1.15.11)上,我测试了Apeach(2.4.39),$_SERVER['PHP_SELF']中的值取决于url。

测试代码:

//test.php
echo $_SERVER['PHP_SELF'];
  • 访问http://127.0.0.1/test.php
  • Output: /test.php
  • 访问http://127.0.0.1/test.php/flag.php
  • Output: /test.php/flag.php
  • 访问http://127.0.0.1/test.php/flag.php?source
  • Output: /test.php/flag.php

这个特性保证了我们正常访问了test.php也能操作$_SERVER['PHP_SELF']的值。这使得在这个题中我们可以改变highlight_file()的文件,实现SSRF。

二、payload构造

访问http://xxx.xxx/index.php/config.php/%ff?source
Pasted image 20220803235604.png
原理解释:
index.php: 访问index.php
/%ff: 绕过preg_match,$_SERVER['PHP_SELF']中的值为/index.php/config.php/%ff
?source: 触发高亮

首先通过/%ff绕过preg_match()basename()/index.php/config.php/%ff处理为config.php,然后被highlight_file()读取源码。

PHP伪协议 SSRF Apeach解析漏洞 588 Views
本站已在互联网运行了 Theme Jasmine by Kent Liao