◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。
想搞好代码审计,必须要搞懂其中一些危险函数危险应用,以及过滤不足,
故以 CTF 来练习。
preg_match — 执行匹配正则表达式
返回值:
**preg_match()返回 的匹配次数。 它的值将是0次(不匹配)或1次,因为preg_match()在第一次匹配后 将会停止搜索。preg_match_all()不同于此,它会一直搜索直到到达结尾。 如果发生错误preg_match()**返回 。
数组绕过
当匹配数组是返回false绕过。
intval()函数用于获取变量的整数值。
intval()函数通过使用指定的进制 base 转换(默认是十进制),返回变量 var 的 integer 数值。 intval() 不能用于 object,否则会产生 E_NOTICE 错误并返回 1。
参数说明:
$var:要转换成 integer 的数量值。
$base:转化所使用的进制。
如果 base 是 0,通过检测 var 的格式来决定使用的进制:
如果字符串包括了 "0x" (或 "0X") 的前缀,使用 16 进制 (hex);否则,
如果字符串以 "0" 开始,使用 8 进制(octal);否则,
将使用 10 进制 (decimal)。
传参一个数既要使其不强等于,又要使得函数处理后的结果强等于,结合上述函数解释
构造
题目要求,传参 cmd.
但是第一个正则匹配要求多行匹配,但是另一个要求有去掉修饰符要求不匹配.那么就应该能想到是截断。
第一个匹配多行,第二个只匹配单行,那么我们可以构造进行匹配,当多行匹配的时候前后都是,
还可以这里有有两个条件,第一个需要是php,第二个又不可以php,不过有个差距就是m模式,/m代表匹配多行数据,第一个if有匹配到第二行的php,而第二个if匹配不到为假。
CVE-2017-15715
https://blog.csdn.net/qq_46091464/article/details/108278486
同样考点是,但这道题不同于web90,而是弱比较,所以说等肯定不行的。
这里用到十六进制或者八进制
https://www.runoob.com/php/php-intval-function.html
也可以科学计数法,在第一个if会计数比较,在函数中会被看做字符串。
过滤了字母,但我们可以使用八进制
查找 "php" 在字符串中第一次出现的位置:
strpos() 函数对大小写敏感。
返回字符串在另一字符串中第一次出现的位置,如果没有找到字符串则返回 FALSE。
比上一关增加条件,strpos函数限制了传参第一位不能为0,如果为0,就die.
但是如果找不到的话又会die.
仔细观察这里时强等于。
我们可以在八进制前加一个空格
或者用小数点
或者再加个 +
又增加过滤了
构造
也可以
可以看到不能直接等于,
但是我们可以构造路劲让其显示
这里是强比较。
弱比较的话可以百度有好多md5加密后是0e开头的,弱比较 0=0
强比较
如果传入函数的不是字符串而是数组,那么就会返回, null=null绕过。
构造
还有md5强碰撞
https://blog.csdn.net/EC_Carrot/article/details/109525162
https://www.cnblogs.com/kuaile1314/p/11968108.html
三米符运算,和传址(引用)
那么看最后要求那么我们就可以直接随意get传参一个,然后post传参即可获得flag.
看看wp:
、意为当没有设置第三个函数时,比较是会自动转换数据类型,也就是弱比较。
那么我们传入就相当于若等于.
构造
这里有问题,又学费了。
php 的运算符竟然比 高。
https://www.jb51.net/article/42425.htm
&& > || >=> and > or
https://www.php.net/manual/zh/language.operators.precedence.php
所以这时候就很清晰明了了。
只需要传入的 值是数字。必须有。
构造
反射类: https://www.php.net/manual/zh/class.reflectionclass.php
反射类用法:
https://blog.csdn.net/miuzzx/article/details/109168454
解出来
有点小坑,仔细看才发现有好多
跟上道题差不多,过滤的严了一些。过滤掉了和反引号,单引号,括号。
只能用反射类了。
构造
同样结果注意flag格式
这里要求是数字,并且截取第三位后的字符作为的第二个参数。
作为 的第一个参数。
作为 的文件名。
返回结果作为的第二参数。
is_numeric 函数是又漏洞的,再 php5 版本下是可以识别十六进制的。也就是说,如果传入也是可以识别为数字的。
但此题是 php7 环境。不可以。
要让v2均为数字,首先我们考虑写入1.php时,利用伪协议写入
关键就是什么代码base64编码后再转为十六进制为全数字
同时因为经过substr处理,所以v2前面还要补两位数字。
构造
或者
相比上关过滤了.
用上关payload也可以打通。
sha1 — 计算字符串的 sha1 散列值. 返回 sha1 散列值字符串。
sha1()函数无法处理数组类型,将报错并返回false,
所以构造
这里没有判断两值是否相等,所以也可以传入两个相等的数。
还有几个弱比较相等的字符串
变量覆盖。
代码审计,直接传入
这里把和 都覆盖成了 ,所以不管die 哪个,都会输出flag.
数组绕过。
还有
MD5弱类型比较。
parse_str() 函数把查询字符串解析到变量中。
注释:如果未设置 array 参数,由该函数设置的变量将覆盖已存在的同名变量。
注释:php.ini 文件中的 magic_quotes_gpc 设置影响该函数的输出。如果已启用,那么在 parse_str() 解析之前,变量会被 addslashes() 转换。
数组绕过
md5加密数组会返回NULL,$v2['flag'] 也是NULL。
弱比较绕过
ereg — 正则表达式匹配
ereg()函数用指定的模式搜索一个字符串中指定的字符串,如果匹配成功返回true,否则,则返回false。搜索字母的字符是大小写敏感的。 ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配
是
所以构造
当通过和的时候,为 877
payload:
考察点:FilesystemIterator类的使用(作用就是获取当前目录文件)
payload:
http://phpff.com/filesystemiterator
php变量地址引用。可以利用全局变量来进行赋值给ctfshow这个变量
payload:
is_file() 函数检查指定的文件名是否是正常的文件。如果文件存在且为正常的文件,则返回 true。
苦苦不知道flag在哪里,原来就在falg.php
payload:
压缩过滤器绕过
在linux中/proc/self/root是指向根目录的,也就是如果在命令行中输入ls /proc/self/root,其实显示的内容是根目录下的内容
多次重复后绕过is_file.。
php的一个小 trick. 具体看这里
过滤了,上面的非预期也就不能用了。
但 没过滤。
payload :
trim函数的绕过+is_numeric绕过
测试代码:
输出了
再来看看 trim+is_numeric
输出
而 、、 被过滤。所以构造
php变量命名是不允许使用点号的,所以就很难搞。
本地暴破一下:
1.php
python脚本:
成功爆破出。
测试一下:
接下来看看的作用。
2、web网页模式下
设置register_argc_argv=On(默认是Off),重启服务,$_SERVER[‘argv’]才会有效果
这时候的$_SERVER[‘argv’][0]=$_SERVER[‘QUERY_STRING’]
$argv,$argc在web模式下不适用
因为我们是在网页模式下运行的,所以也就是
这时候我们只要通过 将$flag赋值flag_give_me就可以了。
我们传值(记得有分号,后边需要eval执行),然后此时 ,我们让 中的 $c 变为即可成功使 fl0g 变量成功赋值。
paylaod:
非预期解:
这个题本来的的预期解是:
但是按理说这样也可以的呀:
https://blog.csdn.net/miuzzx/article/details/109181768
应该又是环境问题。
被过滤了其他方法,
payload
还有:
payload:
fuzz:
1.php
python:
得到
这里其他被ban了,只能使用 空格
gettext拓展的使用.
https://www.cnblogs.com/lost-1987/articles/3309693.html
https://www.php.net/manual/zh/book.gettext.php
所以 返回的就是phpinfo
get_defined_vars — 返回由所有已定义变量所组成的数组 这样可以获得 $flag
因为我们要得到的flag就在flag.php中,所以可以直接用get_defined_vars
payload:
stripos() 函数查找字符串在另一字符串中第一次出现的位置(不区分大小写)。
PHP 版本: | 5+ |
目录穿越:
还可以php伪协议
payload:
还可以远程文件包含。在自己服务器上写一个命名 .
直接 post ,正则匹配到 与匹配规则不符 ,同时 在第0 匹配, 而0===FALSE为假绕过。
利用正则最大回溯次数绕过
https://www.laruence.com/2010/06/08/1579.html
在php中正则表达式进行匹配有一定的限制,超过限制直接返回false
写个py脚本:
得到Falg
打开是一个网站。
直接扫目录,扫到
if绕过
payload
分析一下代码发现仿佛是只能读取前面6个字符去执行命令,禁止了命令执行的函数,并且没有写入权限。可能利用就比较可能
但是,如果我们传递的参数就是本身,会不会发生变量覆盖?
那我们来一个简单的测试,
然后就是利用curl去带出flag.php
payload:
执行payload
之后就会在burp上收到 flag.php的内容,
其他方法:
利用网站 http://requestbin.net
参照:
https://blog.csdn.net/qq_46091464/article/details/109095382
parse_str() 函数把查询字符串解析到变量中。
extract() 函数从数组中将变量导入到当前的符号表。
POST数组的覆盖
可以看到以GET 传参相当于post传参 a 效果。
构造paylaod
在133的基础上增加了curl和其他一些字符的过滤,
可以写文件。
也可以
http://dnslog.cn/
申请一个域名。但是这种方法不行,可能域名前缀不行吧。
把重定向符、mv、cp禁用了。
linux中命令·。
tee命令主要被用来向standout(标准输出流,通常是命令执行窗口)输出的同时也将内容输出到文件
构造payload:
call_user_func — 把第一个参数作为回调函数调用
第一个参数 是被调用的回调函数,其余参数是回调函数的参数。
php中 ->与:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例
::可以调用一个静态的、不依赖于其他初始化的类方法.
也就是说双冒号可以不用实例化类就可以直接调用类中的方法
直接调用函数
这下子把 冒号给禁用了。
用call_user_func()来调用一个类里面的方法
payload:
试了,没有写权限没所以不能写入文件了。
也没有回显。
师傅们的脚本。
猜测文件名:
得到flag所在文件 f149_15_h3r3,接着盲注文件内容
弱比较,所以只需要将 $code 等于字母或者 0 即可。
作用是匹配非数字字母下划线的字符.
php中 可以执行phpinfo()命令的。
取反构造
payload:
取反脚本
直接
过滤了加减我们还可以用乘除,过滤了~我们可以用异或构造命令。
异或脚本:
payload:
\W 匹配非字母、数字、下划线。等价于 '[^A-Za-z0-9_]'。
直接构造 paylaod:
把
取反绕过。
取反脚本:
构造
但是不知道如何使它执行,那么fuzz一波。
结果
也就是
payload:
接着把 三目运算过滤了。
利用绕过。
payload:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。