目录
1、web127
2、web128
3、web129
4、web130
5、web131
1、web127
代码审计:
$ctf_show = md5($flag);
将 $flag 变量进行 MD5 哈希运算,并将结果赋值给 $ctf_show。
$url = $_SERVER['QUERY_STRING'];
获取当前请求的查询字符串(query string),查询字符串是 URL 中位于问号 (?) 之后的部分,通常包含一个或多个参数和值。
之后对查询字符串采用正则匹配过滤掉了一些符号,符合要求则会将 $_GET 数组中的键值对作为变量导入到当前的符号表中。换句话说,extract($_GET); 会将 URL 查询参数中的每个键值对转换成同名的变量。
最后要求 $ctf_show==='ilove36d' 就会输出 flag。
由于下划线被过滤掉了,我们采用非法字符参数名转换绕过,payload:
?ctf show=ilove36d
原本空格、点都是非法的,中括号也是可行的,但是中括号和点被过滤了,因此这里使用空格。
2、web128
代码审计:
check($str) 函数检查字符串 $str 是否包含数字或字母,如果包含,返回 false,否则返回 true。
也就是说传入的 f1 不能包含大小写字母和数字。
var_dump(call_user_func(call_user_func($f1,$f2)));
call_user_func 函数:用于调用指定的回调函数,并可以传递参数给该回调函数,第一个参数是被调用的回调函数,其余参数是回调函数的参数。
这里还进行了嵌套:
(1)内层 call_user_func($f1, $f2)
首先调用 $f1 函数,并传递参数 $f2,结果是 $f1($f2) 的返回值。
(2)外层 call_user_func(...)
外层 call_user_func 接收内层调用的返回值作为它的第一个参数,要正确执行,内层返回值应该是一个函数名或可调用的回调,外层 call_user_func 将再次调用这个返回的回调函数,不传递任何额外的参数。
最后,var_dump 将打印出外层 call_user_func 的返回值。
新知识:gettext 函数
php 扩展目录下如果有 php_gettext.dll,就可以用 _() 来代替 gettext() 函数,_() 就是 gettext() 的别名,常常被用来简化代码。
gettext 函数用于在 PHP 应用程序中实现国际化(i18n)和本地化(l10n),说白了就是根据当前语言环境输出翻译后的字符串。
我们测一下 phpinfo,payload:
?f1=_&f2=phpinfo
那么我们如何输出 $flag 呢?
使用 get_defined_vars() 函数,该函数会返回由所有已定义变量所组成的数组,其中肯定就包括了 $flag,payload:
?f1=_&f2=get_defined_vars
拿到 flag:ctfshow{d7ac7aa1-12c0-4813-8671-786cc26a35d1}
3、web129
stripos 函数:查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
用法:stripos(string,find,start)
参数 | 描述 |
---|---|
string | 必需。规定被搜索的字符串。 |
find | 必需。规定要查找的字符。 |
start | 可选。规定开始搜索的位置。 |
代码审计:
如果变量 $f 包含子字符串 'ctfshow',并且位置大于 0,
就会调用 readfile 函数读取文件内容并输出。
看了一下提示,不太清楚这里这个 ctfshow 目录是猜出来的?payload:
?f=/ctfshow/../../../../var/www/html/flag.php
然后又试了一下,穿一层其实就到了根目录:
?f=/ctfshow/../var/www/html/flag.php
查看源码:
拿到 flag:ctfshow{eeabef32-301f-4abe-a668-69e458e8ef80}
此外还参考了师傅们的其他方法:
(1)利用 filter 伪协议支持多种编码方式,而无效的编码方式就被忽略掉了
payload:
?f=php://filter/convert.iconv.utf8.utf16|ctfshow/resource=flag.php
(2)远程文件包含
错误示范:
这里我直接将文件命名为 ctfshow.php
】
内容如下,先测一下 phpinfo:
包含解析成功
试了下命令执行:
返回 0,可能位置没对(还试了 /var/www/html/flag.php 也没有成功)
再试一下一句话木马:
执行成功
看了下当前确实是在 html 下,但是无法查看上一层目录的文件
后面才发现,我这里调用的就是我自己服务器上的木马,回显的内容也是我服务器里面的东西,并没有搞到题目环境里面去。
应该将一句话木马写为 txt 后缀:
包含进去了但是调用不成功
还是说不是这样来的,不太会这个,知道怎么来的师傅可以讲解一下,谢谢。
4、web130
晃眼一看是不能匹配到 'ctfshow',仔细一看:+? 这部分是一个非贪婪模式的匹配,匹配任意单个字符(除了换行符),+ 表示匹配前面的字符一次或多次,? 表示尽可能少地匹配字符,避免匹配过多。换句话说只是要求 ctfshow 前面不能有字符。
但是下面 stripos 函数又要求 'ctfshow' 不能出现开头,不过仔细一看,这里是强等于,会先比较类型,stripos 函数如果未发现字符串会返回 FALSE,但是这里是可以找到字符串 ctfshow 的,因此返回字符串第一次出现的位置,尽管 stripos 函数返回 0 ,但是与 FALSE 进行强比较时还是会返回 false,因为 0 表示整数值的零,FALSE 表示布尔值的假,数据类型不同,也就是说 if 语句还是不会成立,走的是输出 flag。
只有弱比较时才是相等的:
payload:
f=ctfshow
拿到 flag:ctfshow{9d0c4a57-e9a2-4d7f-9328-ec30e5508eef}
还可以使用数组绕过:
f[]=111
5、web131
这里既要求 ctfshow 前面不能有字符,但又要求得找到字符串 36Dctfshow。
利用 preg_match 的回溯绕过,回溯次数默认上限是 100 万。
先生成一百万个字符:
<?php
// 设置生成字符串的长度
$length = 1000000;
// 生成包含一百万个数字 "1" 的字符串
$onesString = str_repeat('1', $length);
// 输出结果
echo $onesString;
?>
payload:
f=100万个字符加上36Dctfshow
拿到 flag:ctfshow{cc7a5bff-350e-4f22-863b-e604a2679ecf}