本文由湖北警官学院19网安贺世洲编写,转载请注明。
PHP作为一种在服务器端执行的脚本语言,广泛应用于Web开发领域,但是作为一种开发语言,同样存在着不少的漏洞与威胁。本人结合近期学习,总结了在CTFShow网站中遇到的一部分题目。
一.数组绕过表达式
此段代码中最关键的函数为preg_match,根据官方文档其作用为匹配正则表达式。
(1)检测num变量是否已经被设置,如果已经设置则进入代码块;
(2)通过preg_match函数来检测num变量中是否存在数字0-9;
(3)intval函数用于获取变量num的整数值。
preg_match的返回值是完整的匹配次数,发生错误则返回FALSE。与此同时,preg_match在接受传参时,如果没有接受字符串而是接受到一个数组的话,就会返回FALSE,由此可得PayLoad。
传入此参数满足:
(1)满足isset检测条件;
(2)在进入第一个if语句结构时,不满足preg_match要求,于是可不进入第一个if语句结构中。
二.intval函数的使用
PHP官方文档中intval函数运行实例如下:
PHP中===与==的含义不尽相同:
此段代码中最关键的函数是intval. num变量被传入函数后:
(1)想要绕过第一个if判断,则需要使得num变量的值和类型都与4476不同;
(2)想要绕过第二个if判断:
A、注意到此处的intval函数中第二个参数为0,表示通过检测value的格式来决定使用的进制:如果字符串包括了 "0x" (或 "0X") 的前缀,使用16进制 (hex);如果字符串以 "0" 开始,使用8进制(octal);否则将使用10进制 (decimal)。
B、结合上述特性,可以使用其他进制进行绕过intval限制进而输出flag。
选择使用十六进制进行绕过:
三.正则表达式修饰符
(1)i:不区分(ignore)大小写;
(2)g:全局(global)全局匹配;
(3)m:多行(more)匹配,若存在换行\n并且有开始^或结束^符的情况下,将以换行为分隔符,逐行进行匹配;
(4)s:默认情况下的圆点.是 匹配除换行符\n之外的任何字符,加上s之后,.中包含换行符\n;
(5)A:强制从目标字符串开头匹配;
(6)D:如果使用$限制结尾字符,则不允许结尾有换行;
(7)e:配合函数preg_replace()使用, 可以把匹配来的字符串当作正则表达式执行。
(1)经过第一个匹配时,以换行符为分割也就是%0a. 前面因为为空,所以只匹配换行符后面的,所以可以通过;
(2)此参数经过第二个匹配时,因不符合以php开头以php结尾,所以无法通过,最后输出flag。
四.路径相关
不直接访问flag.php,使用其他路径访问此文件即可:
五.hash比较缺陷
6. else
7. print 'Wrong.';
8. }
(1)传入的参数二者值不能相等;
(2)但是两个参数的md5值必须相等。
六.三目运算符和变量覆盖
最后一句代码的意思是:如果使用GET方法传入了一个HTTP_FLAG=flag就输出flag。
1. GET:
2. 任意数据都可以
3. POST:
4. HTTP_FLAG=flag
七.PHP弱类型比较
(1)array_push的作用类似于入栈操作;
(2)in_array用来检查数组中是否存在某个值:沿用了PHP中的==。
(1)传入n=1.php
因为PHP在使用in_array()函数判断时,会将1.php强制转换成数字1,而数字1在range(1,24)数组中,当随机生成的数字正好是1时绕过in_array()函数判断,导致任意文件上传漏洞;
(2)使用POST方法上传数据:
A、多次上传直至不报错,此时不报错说明成功传入一句话;
B、访问https://xxx/1.php,再使用POST:
八.hex2bin函数的使用
(1)is_numeric用于检测变量是否为数字或数字字符串,如果参数是数字和数字字符串则返回TRUE,否则返回FALSE.
(2)is_numeric在PHP5与PHP7两种环境中效果不尽相同,在PHP5环境中可以识别十六进制。
(1)将一句话木马编码为十六进制然后作为参数传给v2;
(2)构造并上传;
(3)PHP7版本的PayLoad为:
九.hash比较缺陷
使用数组绕过即可。
十.PHP函数覆盖
(1)第一个GET请求中,当传如suces=flag时,实际执行的语句是$suces=$flag:即把flag赋值给了suces变量;
(2)POST中,传入rror=suces得到$error=$suces=$flag:即成功把flag的值赋给了error变量。在这个过程中,sucec只是作为了中间人,起到了传递值的作用。
十一.parse_str函数的使用
关键函数为parse_str,parse_str的作用是将字符串解析为多个变量:
(1)parse_str存在变量覆盖漏洞;
(2)parse_str函数用于把查询字符串解析到变量中,如果没有array参数,则由该函数设置的变量将覆盖已存在的同名变量。极度不建议在没有array参数的情况下使用此函数,并且在PHP7.2中将废弃不设置参数的行为。此函数没有返回值;
(3)要想获取最终的flag,需要使得v2中flag的值与传入v3的md5值相同。
1. get:?v3=1
十二.ereg%00 正则截断
(1)strrev():字符串反转;
(2)intval():获取变量的整数值。
题目要求c反转后与0x36d相等,利用%00截断构造PayLoad
1. ?c=a%00778
(1)正则表达式只会匹配%00之前的内容,后面的被截断,可以通过正则表达式检测;
(2)经过反转后得到877%00a;
(3)intval处理后得到877;
(4)877为0x36d的10进制。
刷了CTFShow网站的PHP特性的一部分题目,将其所涉及的知识点结如上。