本节课主要对php这个语言上出现的安全隐患以及一些ctf题进行学习。
#知识点:
1、过滤函数缺陷绕过
2、CTF考点与代码审计
首先是php中过滤函数的绕过缺陷。在php中,有一些函数就是为了过滤来阻隔一些攻击,比如对类型做控制什么的。那么咱先说一下过滤函数的绕过。
第一个
==与===
首先说一下双等和三等的区别,php中全等(===)和相等(==)的用法区别_写程序的赵童鞋的博客-CSDN博客。便于后续知识的理解。在双等里面,我们输入1.0或则+a又或则1a都是可以输出结果的。这就是双等,它不比对数据的类型,并且执行关系运算”==“时要求运算符两边的数据 类型必须一致,所以就算输入的是1a,他也会转化为1,从而输出flag。而如果是三等的话,他会把数据类型也比对。随意这个就相对严谨一些,当你输入1.0之类的统统不行,只能是1,并且数据类型要相同。
第二个
Md5
md5是加密方式,这上面也牵涉一些绕过问题。首先第一行保证name和password输入的值不相同,然后就是双等,代码第一行是他俩输入的值不一样,下面又要保证他俩的md5值一样,这显然是有点矛盾的,这里解释一下。因为处理hash字符串时,PHP会将每一个以 0E开头的哈希值解释为0,那么只要传入的不同字符串经过哈希以后是以 0E开头的,那么PHP会认为它们相同,所以我们怎么绕过呢,直接找名字和密码不一样的,然后md5值前两位是0e就可以了,就像图中的两个,就可以实现绕过了。就算使用三等也是有缺陷的,我们可以使用数组,因为在第一行的时候,1不等于2,然后第二行,md5没法处理数组,那就会变成null,两边都是null就相等,进而实现绕过。下面的链接讲解比较详细,
PHP md5 相等绕过 - Ainsliaea - 博客园 (cnblogs.com)
在实际场景中,如果它采用的是下文的代码进行验证,那么就有缺陷,因为如果说他的密码是qnkcdzo,那么你输入240610708也是可以进去的。
第三个
Intval
PHP intval() 函数 | 菜鸟教程 (runoob.com)这个是这个函数的讲解,先看一下。在第一个里面我们不输入base的值,那这个函数就会把输入的数据转换为默认的十进制了。Base的值是0,那就转换为8进制,为0x,就转换为16进制。那他的作用就是在正常的访问的时候就是?a=1,那么攻击者就会在后面加上and之类的。这个函数就可以避免一定的攻击。
那他的缺陷就是当我们输入666.0或则+666也是一样可以输出flag的。把base的值换成零,也就是八进制,这是我们输入1232(666的八进制)是可以的,也可以输入0x29a。因为666的16进制是29a,前面加上0x就可以变成16进制了。
第四个
Strops
PHP strpos() 函数 (w3school.com.cn)
小迪之说前面加上换行符可以绕过,没细讲
第五个
in_array
PHP in_array() 函数 | 菜鸟教程 (runoob.com)
这个函数的绕过就在于strict的值有没有设置为true,如果该参数设置为 TRUE,则 in_array() 函数检查搜索的数据与数组的值的类型是否相同。如果没有设置,那么就类似双等的绕过了,
那么在下图中,我们输入1ex,它就会转换为1.因此相等
第六个
preg_match
PHP preg_match() 函数 | 菜鸟教程 (runoob.com)
preg_match 函数用于执行一个正则表达式匹配。图中的代码意思就是如果num是从0到9的就输出no,no,no。这时候我们利用数组绕过,因为preg_match无法匹配数组,他只能匹配字符串。那么就相当于这一行代码失效了。到下面之后,数组的值为1,就输出flag了。
这种的正则匹配,默认只匹配第一行,也可以使用%0a进行换行绕过。
第七个
str_replace
直接看源代码,这个是用空把select替代了,相当于是把select过滤了,但它只能过滤一次不能迭代过滤,所以我们输入sselectelect还是可以得到我们想要的select。
我们讲这些东西,一方面是为了应对ctf,一方面是为了一看看代码找漏洞。
下面说一下ctf的相关考题。
因为基本都是和上面讲的差不多,我这里就不解释了,看图就完了。
这里输入4476.0也是可以的,补充:代码第八行把x过滤了,十一行把0过滤了。
这里因为是post方法接受的变量,所以要用到火狐。
基本考题就这么多,都是和我们刚才讲过的息息相关。
然后说一下实际案例:
网站源码在资源库中,放到www下面之后配置好环境就好了。我们直接在源码中全局搜索str_replace,就是我们刚才讲过的一个过滤函数。看下图的代码是把../和./过滤了但他的缺陷就是只能过滤一次。因此我们如果想利用下面的代码实现任意文件打开,第一步就是把dir的值写出来,由于他把那两个过滤了,所以如果我们想要数据包中的请求出现../。那就在url上面写“.....///”。然后下面的if判断是双等,我们要满足它,在url中只要有http就行了。
至于为什么把dir的值写成那样,是因为http后面还有个条件。不能有./
具体看链接:MetInfo 任意文件读取漏洞的修复与绕过 - 知道创宇 (knownsec.com)
补充:/和\是一样的作用,当过滤/的时候,我们可以使用\
还有就是in_array的相关问题,我们可以直接在源码中搜。具体过程看链接piwigo2-7-1sql注入分析 - LionTree (liotree.github.io),迪总和这个讲的一样。
补充一个红日安全关于这方面的讲解 hongriSec/PHP-Audit-Labs: 一个关于PHP的代码审计项目 (github.com)