PHP代码审计要点
随着代码安全的普及,越来越多的开发人员知道了如何防御sqli、xss等与语言无关的漏洞,但是对于和开发语言本身相关的一些漏洞和缺陷却知之甚少PHP字符串变量,于是这些点也就是我们在
前言 随着代码安全的普及,越来越多的开发人员知道了如何防御sqli、xss等与语言无关的漏洞,但是对于和开发语言本身相关的一些漏洞和缺陷却知之甚少PHP字符串变量,于是这些点也就是我们在Code audit的时候的重点关注点。本文旨在总结一些在PHP代码中经常造成问题的点,也是我们在审计的时候的关注重点。(PS:本文也只是简单的列出问题,至于造成问题的底层原因未做详细解释,有兴趣的看官可以自行GOOGLE或者看看底层C代码。知其然,且知其所以然) 本文若有写错的地方,还请各位大佬斧正 : 1、代码审计定义 代码审计 是指对源代码进行检查,寻找代码中的bug,这里主要寻到可导致安全问题的bug。 这是一项需要多方面技能的技术,包括对编程的掌握(能看懂代码的逻辑)、漏洞形成原理的理解、系统和中间件等的熟悉。 2、代码审计思路 1)逆向追踪 检查敏感函数的参数,然后回溯变量,判断变量是否可控并且没有经过严格过滤。 2)正向追踪 先找出哪些文件在接受外部传输的函数,然后跟踪变量传递的过程,观察是否有变量传入到高危函数里边,或者传递过程中是否有代码逻辑漏洞。这种正向追踪的方式,比逆向追踪挖掘得更全。 3)经验判断直接挖掘功能点漏洞 根据自身的经验判断该类应用通常在哪些功能中会出现漏洞,直接全篇阅读该功能代码。 3、PHP代码审计需要掌握好以下(其他语言类似) 1)PHP编程语言的特性和基础 2)Web前端编程基础 3)漏洞形成原理 4)代码审计思路 5)不同系统、中间件之间的特性差异。 漏洞实例 TODO: 继续丰富并增加各个点的实际漏洞事例 file_put_contents、copy、file_get_contents等读取写入操作与unlink、file_exists等删除判断文件函数之间对于路径处理的差异导致的删除绕过 例如如下代码
这里引用小密圈中P牛的解读
于是乎linux可以通过 xxxxx/../test.php、test.php/.windows 可以通过test.php:test test.ph 0;如果两者相等,返回 0。 但是如果传入的两个变量是数组的话,函数会报错返回NULL,如果只是用strcmp()==0来判断的话就可以绕过 sha1()、md5() 函数传入数组比较绕过 sha1() MD5()函数默认接收的参数是字符串类型,但是如果如果传入的参数是数组的话,函数就会报错返回NULL。类似sha1($_GET[‘name’]) === sha1($_GET[‘password’])的比较就可以绕过 弱类型==比较绕过 这方面问题普及的很多,不作过多的解释
当转换为boolean时,以下只被认为是FALSE:FALSE、0、0.0、“”、“0”、array()、NULL PHP 7 以前的版本里,如果向八进制数传递了一个非法数字(即 8 或 9),则后面其余数字会被忽略。var_dump(0123)=var_dump(01239)=83 PHP 7 以后,会产生 Parse Error。 字符串转换为数值时,若字符串开头有数字,则转为数字并省略后面的非数字字符。若一开头没有数字则转换为0
eregi()匹配绕过 eregi()默认接收字符串参数,如果传入数组,函数会报错并返回NULL。同时还可以 截断进行绕过 PHP变量名不能带有点[.] 和空格,否则在会被转化为下划线[_]
in_arrary()函数默认进行松散比较(进行类型转换)
printf()和sprintf()函数中可以通过使用%接一个字符来进行padding功能 例如s 字符串会默认在左侧填充空格至长度为10,还可以 0s 会使用字符0进行填充,但是如果我们想要使用别的字符进行填充,需要使用 ‘ 单引号进行标识,例如 %’#10s 这个就是使用#进行填充(百分号不仅会吃掉’单引号,还会吃掉\ 斜杠) 同时sprintf()可以使用指定参数位置的写法 %后面的数字代表第几个参数,$后代表格式化类型 于是当我们输入的特殊字符被放到引号中进行转义时,但是又使用了sprintf函数进行拼接时 例如%1$’%s’ 中的 ‘%被当成使用%进行padding,导致后一个’逃逸了 还有一种情况就是’被转义成了\’,例如输入%’ and 1=1#进入,存在SQL过滤,’被转成了\’ 于是sql语句变成了 select * from user where username = ‘%\’ and 1=1#’; 如果这个语句被使用sprintf函数进行了拼接,%后的\被吃掉了,导致了’逃逸
不过这样容易遇到 PHP Warning: sprintf(): Too few arguments的报错 这个时候我们可以使用%1$来吃掉转移添加的\
php中 = 赋值运算的优先级高于and $c = is_numeric($a) and is_numeric($b) 程序本意是要a、b都为数字才会继续,但是当$a为数字时,会先赋值给$c,所以可能导致$b绕过检测 parse_url与libcurl对与url的解析差异可能导致ssrf
url标准的灵活性导致绕过filter_var与parse_url进行ssrf filter_var()函数对于 ;google.com 会返回false也就是认为url格式错误,但是对于 0://evil.com:80;google.com:80/ 0://evil.com:80,google.com:80/ 0://evil.com:80\google.com:80/却返回true。 通过file_get_contents获取网页内容并返回到客户端有可能造成xss 例如如下代码
虽然通过filter_var函数对url的格式进行检查,并且使用正则对url的host进行限定 但是可以通过 data://baidu.com/plain;base64,PHNjcmlwdD5hbGVydCgxKTwvc2NyaXB0Pgo= 页面会将代码返回给客户端,就有可能造成XSS “如侵权请私聊公众号删文” (编辑:海南站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |