题目要你去玩这个乐透,虽然没接触过,但不影响
进去先要写脚本爆破一下这个MD5
import hashlib
from string import ascii_letters, digits
from itertools import product
table = ascii_letters + digits
def crash():
hash = "xxxxxx"
#product()函数可用于生成笛卡尔积(就是排列组合),参数repeat为组几位
for i in product(table, repeat=5):
t = hashlib.md5(('').join(i).encode()).hexdigest()
#print(t[:6])
if t[:6] == hash:
print(''.join(i))
break
if __name__ == '__main__':
crash()
题目还给了带Docker的源码,可以自己本地搭建环境测试。重点代码:
app目录下的
from flask import Flask,render_template, request
import os
app = Flask(__name__, static_url_path='')
def safe_check(s):
if 'LD' in s or 'HTTP' in s or 'BASH' in s or 'ENV' in s or 'PROXY' in s or 'PS' in s:
return False
return True
@app.route("/", methods=['GET', 'POST'])
def index():
return render_template('index.html')
@app.route("/lotto", methods=['GET', 'POST'])
def lotto():
message = ''
if request.method == 'GET':
return render_template('lotto.html')
elif request.method == 'POST':
flag = os.getenv('flag')
lotto_key = request.form.get('lotto_key') or ''
lotto_value = request.form.get('lotto_value') or ''
try:
lotto_key = lotto_key.upper()
except Exception as e:
print(e)
message = 'Lotto Error!'
return render_template('lotto.html', message=message)
if safe_check(lotto_key):
os.environ[lotto_key] = lotto_value
try:
os.system('wget --content-disposition -N lotto')
if os.path.exists("/app/lotto_result.txt"):
lotto_result = open("/app/lotto_result.txt", 'rb').read()
else:
lotto_result = 'result'
if os.path.exists("/app/guess/forecast.txt"):
forecast = open("/app/guess/forecast.txt", 'rb').read()
else:
forecast = 'forecast'
if forecast == lotto_result:
return flag
else:
message = 'Sorry forecast fxxxxxxxxxxxx!' + result
return render_template('lotto.html', message=message)
except Exception as e:
message = 'Lotto Error!'
return render_template('lotto.html', message=message)
else:
message = 'NO NO NO, JUST LOTTO!'
return render_template('lotto.html', message=message)
@app.route("/forecast", methods=['GET', 'POST'])
def forecast():
message = ''
if request.method == 'GET':
return render_template('forecast.html')
elif request.method == 'POST':
if 'file' not in request.files:
message = 'Where is your forecast?'
file = request.files['file']
file.save('/app/guess/forecast.txt')
message = "OK, I get your forecast. Let's Lotto!"
return render_template('forecast.html', message=message)
@app.route("/result", methods=['GET'])
def result():
if os.path.exists("/app/lotto_result.txt"):
lotto_result = open("/app/lotto_result.txt", 'rb').read().decode()
else:
lotto_result = ''
return render_template('result.html', message=lotto_result)
if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0', port=8080)
lotto目录下的
from flask import Flask, make_response
import secrets
app = Flask(__name__)
@app.route("/")
def index():
lotto = []
for i in range(1, 20):
n = str(secrets.randbelow(40))
lotto.append(n)
r = '\n'.join(lotto)
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)
乐透这个游戏是要我们去猜彩票的号码,要求我们去上传一个forecast.txt
的文件,文件里是我们预测的数字,同时其使用 wget 这个命令去下载生成随机数的文件 lotoo_result.txt
(20个0-40的随机数)。题目说我们可以作弊,就是可以上传key,vale来更改环境变量
可以改变环境变量,那么可以让 PATH
这个环境变量为空,就会导致当前这个 os 的shell的 wget 失效(测试过也不会报错),从而使生成的随机数不会再改变,再去上传这个随机数就可以了,说到这个那就讲讲这个Linux环境变量
系统中有环境变量 PATH ,看看这个PATH是什么
是几个含有各种系统命令的路径,每次在bash中输入各种命令就会在这些路径去寻找
现在使 PATH=
看看
ls
命令直接没了(这里export可以省略)echo命令可以正常使用
echo一下,PATH为空了,看看wget命令也没了
当然,这些改变都是临时的,退出终端在进去一切正常,同一设备的不同的终端也不会相互影响
好了,回到正题,在本地用docker搭建下环境
打开docker,直接在vscode的终端输入 docker-compose up
或 docker-compose up -d
( -d 代表在后台运行)
随便输点拿到随机数
在KEY中输入 PATH 配置环境变量为空使wget失效
这下 随机数是个定值了
上传文件使用 bp 抓包(这里由于是在本地搭建的环境,不好设置代理让 bp抓包,就直接用bp自带的浏览器了)其实bp自带的浏览器还是可以的
这里注意要将 \r 给去掉,应为题目给的随机数之间是以\n
分割的,而两者之间又是比较的它们的 二进制值 是否相同,所以要完全一致才行,改完保存好发送
回到lotto页面点击lotto按钮就可以拿到flag了
这里的方法应该是非预期解,后面又给了个revenge版,是预期解,这个lotto2 以后再说………….