PHP 特性3
| 2023-3-27
0  |  Read Time 0 min
 

web110

PHP Version: 7.3.11
仍未解决

知识点

  • 对 PHP 原生类的运用

做题

从这题可以看出,这里考察的是对PHP原生类和原生函数的结合运用,但由于我也没啥知识储备,所以还是得先翻一下资料,顺便看一下hint
想写下列代码尝试一下,利用 FilesystemIterator 获取指定目录下的所有文件,但是不知道为什么只返回了一个文件名?为什么在这题就可以返回flag的txt,如果恰好flag的名字不在第一个怎么办?
令我更不明白的是,为什么我这里调用的是 web110.php,他给我返回了一个 web261.php?
notion image

参考资料

web111

PHP Version: 7.3.11

知识点

  • 变量覆盖

做题

我原本想的是 v1 = ctfshow, v2 = flag 的,执行后发现为null,于是就逐个断点调试看看是什么情况。
notion image
可以看到,这个 $flag 进来以后就没了,那怎么办呢,其实 $flag 在外部已经被定义了,所以他算是一个全局变量,只要我们查看 GLOBALS 的值即可拿到 flag,也就是说 v1 写 ctfshow,v2 写 GLOBALS。

web112

知识点

PHP Version: 7.3.11
  • 函数绕过
  • PHP 伪协议读取文件

做题

首先可以看到,这里面过滤了 ..|http|https|data|input|rot13|base64|string ,如果没有这个,可以考虑用 http://127.0.0.1/flag.php 来绕过。其他绕过方式也可参考参考资料[1]。
然后我们看到 is_file($file) 这里做了一层判断,也就是说不能直接读取文件,不过我们可以借此判断是否存在文件。输入 /?file=/var/www/html/flag.php 返回 hacker! 代表存在该文件。
根据官方提示以及参考资料[2],我们可以通过以下几种方式获取文件
前三种方式不乏都是通过 PHP 流过滤器加上各种转换(见参考资料[3])与最终 resource=flag.php 拿到 flag,最后一种则是通过压缩流与调取本地文件拿到
并且看起来 read= 可以忽略,主要是看转换,更多过滤器可见参考资料 [4]
不过最后一种在 highlight_file 遇到以后是会自动解压吗?不是很懂

参考资料

web113

PHP Version: 7.3.11

知识点

  • 函数绕过
  • PHP 压缩流协议使用
  • 多次软链接绕过 is_file()

做题

非预期解

细节其实和上题差不多,只不过 filter 被限制使用了,还是可以用压缩流来绕过。
但我不明白,为什么不能用 zip:// 和 bzip2:// ,只能用 zlib2:// ?
zlib: 的功能类似 gzopen(),但是 其数据流还能被 fread() 和其他文件系统函数使用。 不建议使用,因为会和其他带“:”字符的文件名混淆; 请使用 compress.zlib:// 替代。

预期解

经过20次软链接可以绕过 is_file()
/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/proc/self/root/var/www/html/flag.php
原来还有 /proc/self/root 软链接这种方法,学到了

web114

PHP Version: 7.3.11

知识点

  • 函数绕过
  • PHP 伪协议读取文件

做题

这题拦截了 compress,拦截了convert,但又不拦截 filter 了,奇怪。
php://filter/resource=flag.php

web115

PHP Version: 7.3.11

代码

知识点

  • 通过 \f 绕过 is_numberic() 与 trim()

做题

首先我们分析题目,此处将十六进制和八进制的方法给pass掉了,所以无法使用十六进制或八进制来直接绕过。其次,此处使用了 is_numeric 与 trim 来判断。is_numeric 用于判断是否为数字,通过 trim 过滤字符,trim 的语法见下
notion image
is_numeric函数在开始判断前,会先跳过所有空白字符。可是题目获取$req[‘number’]的时候明明使用trim过滤了空白字符这时候我们可以引入\f(也就是%0c)在数字前面,来绕过最后那个is_palindrome_number函数,而对于前面的数字判断,因为intval和is_numeric都会忽略这个字符,所以不会影响。 ———————————————— 版权声明:本文为CSDN博主「EvilGenius-」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_36609913/article/details/79296052
所以,我们只需要在36前面添加 %0c 即 \f 的 urlencode 即可绕过,
 

参考资料

web123

PHP Version: 7.4.9

做题

思路错了。。我一开始在想怎么给 fl0g 赋值为 flag_give_me,但完全没有想到在eval可以直接echo一个$flag。。。
我们按照代码的判断条件来操作,结果最后发现 POST 上去的小数点 . 被转换为了下划线 _
notion image
注意: 变量名中的点和空格被转换成下划线。例如 <input name="a.b" /> 变成了 $_REQUEST["a_b"]。
那有什么办法呢?结果后来发现,原来[也会被转换,PHP会将 [ 转换为 . 这不刚好应了我的意吗?
按照题目,第一个 [ 会被置换为下划线,之后的.就不会被转换,因此该题中 CTF_SHOW.COM 的参数应为 CTF[SHOW.COM
所以最后请求参数为

参考资料

web125

PHP Version: 7.4.9

知识点

  • 在eval中调用函数,使用其他变量来绕过检查。

做题

我们其实可以在eval的参数中再eval其他变量,例如这样: eval($_GET[0]) ,然后再设置参数0为 echo $flag;,不就可以了嘛?
请求参数:

web126

知识点

  • 使用 parse_str 将字符串解析成多个变量

做题

草,前面没提到这个 $a=$_SERVER['argv']; 我都忘了有这个东西了,还以为发挥作用的是 ?a=1+flag=xxx 这么厉害呢。。。
由题目,我们可以使用变量覆盖来使变量 $fl0g 的值为 flag_give_me ,但我们又不能直接传入 $_GET ,那怎么办呢?
刚好由 hint,我发现题目传入的参数是 /?a=1+fl0g=flag_give_me ,我还在好奇为什么不能用 & 而需要用 + ,经过下面的分析就明白了。
使用 + 时,argv会被分成两个,分别为 a=1 以及 fl0g=flag_give_me,而此时 $_GET 只有一个数组成员。
notion image
但我使用 & 时,argv还是回被分成2个,$_GET 此时就会变为两个,会被判断条件 !isset($_GET['fl0g']) 所拦截。

parse_str

提交 fun 设置为 parse_str($a[1]) 即可获得flag,请求参数如下

assert

这个函数的作用,有点类似于eval?但我就不明白了,你小米把我内测资格取消掉,还把我的内测分把300多分扣到55分,你是傻的吗!
为什么eval不行?它碰撞到了哪个正则规则吗?
在assert内允许不是分号结尾的语句,例如 assert('$a=test');,但是eval内必须要为分号结尾,所以将assert改为eval时,还需要把 GET 参数 fl0g 中的flag_give_me 后面添加分号,这样就可以拿到flag了。
请求参数如下

参考资料

web127

PHP Version: 7.3.11

做题

这里面, $_SERVER['QUERY_STRING'] 会提取出请求 URL 中 /? 后的参数,也就是 GET 参数的 urlencode 版。但是,由于下划线被waf阻止,我们似乎不能直接使 ctf_show 的值为 ilove36d (说起来这ctfshow的创始人是不是有什么特殊的xp天天喜欢36d的
上回书说道,彼时的璃月
我们在web123中提过,某些字符可以被转换。所以,参照该表,我们还可以用的字符为空格。
最后请求参数为

web128

PHP Version: 5.6.40

代码

知识点

  • 对 _() 函数的了解与使用

做题

在 PHP 中,启用了 gettext 扩展的 PHP 程序上,直接调用 () 方法等同于调用 gettext(),也就是说,调用 ("hello"); 会使 PHP 返回 hello 字符串。同时,在此题中使用 get_defined_text 可以获得被定义的变量。由于此处 check() 不允许变量 f1 携带任何字母和数字字符,所以只能从f2进行下手。
在此题中,也就等同于只能访问一个方法使得其获得flag。我们可以使用 /?f1=_&f2=get_defined_vars 来获得 flag

其他问题

  • 有没有只通过一个函数来getshell的方法,比如说匿名函数?
  • 有没有可以通过一个函数+一个参数,但是关键的控制函数(如eval,system等)被限制使用来getshell的方法?

参考资料

toxic
利用gettext实现多国语系支持! 这里我们主要介绍window平台下使用php的扩展gettext实现程序的国际化。 步骤一:搭建环境 1,首先查看你的php扩展目录下是否有php_gettext.dll这个文件,如果没有,这就需要你下载一个或是从其他地方拷贝一个,然后放到php扩展目录。 2,打开php.ini,查找";extension=php_gettext.dll" ,然后去除注释,重启apache。 步骤二:原理讲解 假如你的没有国际化的程序里有这样的代码, echo "你好";,而国际化的程序你要写成 echo gettext("你好");,然后再在配置文件里添加"你好"相对应的英文"Hi"。 这时,中国地区浏览都会在屏幕上输出"你好",而美国地区浏览都会在屏幕上输出"Hi"。也就是说,最终显示什么是根据你的配置文件而定的,如果找不到配置文件,才会输出程序里面的内容。 步骤三:编码测试 1,我们在d:\www下面新建文件hi.php,详细代码如下 1 这时你运行改程序,只会输出"Hi"。但我们是中国人,我们不认识"Hi", 我们只认识"你好",这时就要配置文件出马。配置文件的生成一般借助一款工具。 下载地址:http:// nchc.dl.sourceforge.net/sourceforge/gnuwin32/gettext-0.14.4.exe 安装好以后,为了在任意目录里使用,需要把"安装路径/bin"添加到系统环境变量里。 步骤四:配置文件的生成 1,我们假设你的工具已经安装好,并且可以在任意目录使用。现在就要运行cmd,并把路径切换到d:\www下面,也就是hi.php所在目录。 键入xgettext -d hi hi.php --from-code=gb2312,然后执行,这时你可以看到新生成一个hi.po文件,注意:--from-code=gb2312,其中gb2312还可以是utf-8。 2,打开hi.po文件,显示如下: # SOME DESCRIPTIVE TITLE. # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package.
  • GitTalk
Catalog