[鹤城杯 2021]EasyP

题目复现链接:https://www.nssctf.cn/problem/463

题目源码:

<?php
include 'utils.php';

if (isset($_POST['guess'])) {
    $guess = (string) $_POST['guess'];
    if ($guess === $secret) {
        $message = 'Congratulations! The flag is: ' . $flag;
    } else {
        $message = 'Wrong. Try Again';
    }
}

if (preg_match('/utils\.php\/*$/i', $_SERVER['PHP_SELF'])) {
    exit("hacker :)");
}

if (preg_match('/show_source/', $_SERVER['REQUEST_URI'])){
    exit("hacker :)");
}

if (isset($_GET['show_source'])) {
    highlight_file(basename($_SERVER['PHP_SELF']));
    exit();
}else{
    show_source(__FILE__);
}
?> 

审计代码第一眼可以看到只需要POST传参guess,使其值为secret即可获取到flag
但四处寻找无果,只能转换思路,尝试从utils.php文件中入手
代码中存在highlight_file函数,可以读取文件,这里便是题目的突破点

知识点

$_SERVER超全局变量

查阅官方文档,$_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等信息的 array。这个数组中的条目由 Web 服务器创建,所以不能保证每个 Web 服务器都提供全部条目;服务器可能会忽略一些,或者提供此处没有列举出来的其它内容。

简单来说,这是一个包含了各种信息的数组,而在题目中:
$_SERVER['PHP_SELF']用于获取当前正在执行的脚本文件的路径和名称
$_SERVER['REQUEST_URI']用于获取当前请求的URI(统一资源标识符),包括路径和查询参数部分。

他们在仅访问某脚本时返回的值完全一样:

但当传递参数则会有不同的返回:

basename()函数

该函数返回路径中的文件名部分,可以近似地认为是返回最后一个/之后的内容

该函数有一个利用的点在于当传入的参数为非ASCII码、乱码、中文等特殊字符时会将其抛弃

PHP参数解析特性

PHP会自动将参数转换为有效的变量名:
1.删除空白符
2.将特殊字符[+ .转化成下划线_

正则表达式/utils.php/*$/i

utils\.php:匹配字符串中的"utils.php"部分,因为".“在正则表达式中是一个元字符,需要使用转义符”“来匹配实际的点号。
\/:匹配斜杠字符”/“。
*:表示前面的斜杠可以出现0次或多次,即”/"可以出现0个或多个。
$:表示匹配字符串结尾。
i:表示忽略大小写。

Payload

知识点已经罗列完毕,现在回到题目中
思路已经明确了:修改URI,绕过waf,利用代码中的文件读取函数去进行文件读取
最终payloado:
/index.php/utils.php/%ff?show[source=1

其中%ff用来绕过第一个匹配,[用来绕过第二个匹配,payload经过PHP_SELFbasename()的作用后只剩下utils.php,达到读取文件的结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值