跳转至

女娲补胎⚓︎

604 个字 43 行代码 预计阅读时间 3 分钟

解题过程⚓︎

首先看到其给出的提示,说此题是简单题,只需要仔细阅读代码便可以完成。在浏览了整个项目的结构和内容后,着重看了看 service/start.shsrc/app.js 这两个文件。我大概已经了解了这个题目的大致思路。

成功登录⚓︎

一眼看过去,我们要做到成功登录,就是要拿到正确的 admin_key,用户名和密码。app.js 中的相关函数如下:

//归墟哈希
function Gui_Xu(str) {
  const hash = Tong_Que.createHash('md5');
  hash.update(str);
  return hash.digest('hex');
}

//神兽「玄武」以甲壳御侮、以鳞角擅战
function Xuan_Wu(req) { 
  if (req.header['admin_key'] != undefined)
  if (Gui_Xu(req.header['admin_key']) == "81cb271f0e52999ba6a0fb11fa6dd9fd")
  return "pass"; return "fail";
}
zhu_Rong.post('/', (req, res) => {
  const { username, password } = req.body;
  if (username === 'admin' && password === He_Tu) {
    res.cookie('role', 'user', {
      httpOnly: true,
      maxAge: 3600000,
      sameSite: 'strict'
    });

    req.session.user = username;
    req.session.logined = "true";
    return res.redirect('/flag');
  }

  req.session.error = '登录失败';
  res.redirect('/');
});
# 咳咳咳
# 河图密码好像不够安全
# 还是换一个吧
sed -i "s/12345678910/$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 16)/" /app/app.js

chmod 740 /app/*

node app.js

admin_key⚓︎

这玩意确实让我迷糊了一下,在没仔细阅读代码的情形下,我先去找了 cmd5 去反解这个 md5 值,结果发现查不出来。于是再仔细一看,发现玄武函数中当前的 return 语句存在逻辑错误。由于 return "pass"; 后面没有使用大括号 {} 包裹的代码块,return "fail" 总是会被执行,无论前面的条件是否成立。因此,无论条件如何判断,函数总会返回 fail。而且事实上,这一项和后面的验证也没什么关系,因此我们可以直接忽略掉。

用户名⚓︎

用户名就比较清晰了,就是 admin

密码⚓︎

对于密码的获取,我则绕了一圈弯路,表面是它是固定常量 12345678910,但是 start.sh 中的 sed 命令会将 12345678910 替换为一个随机密码,并且这个随机密码会被存储在 app.js 中的 He_Tu 变量中,而我们现在就是要拿到这个随机密码。作为小白,本着什么工具都试试的精神,用 burpsuite 一顿分析,结果帮助为 0。最终想起了提示中提到的仔细阅读代码,于是我又回到了 app.js 中去仔细看了一圈,结果就在开头我便看到了关键之处。

zhu_Rong.use(Zhu_Rong.static(Ying_Zhou.join(__dirname)));

!这就是关键所在了!这行代码的意思是将 static 中的文件暴露在 / 路径下。也就是说,我们可以直接通过 /app.js 来访问这个文件,从而获取到其中被替换的密码。

至此,我们已经可以成功登录了。

替换 cookie⚓︎

在源码中,我们可以看到的一个比较大的洞是:

//独脚神兽「夔」借雷声震慑天下
function Kui_Dragon(req) { 
  return req.cookies['role'] == "admin";
}

在之前我们已经知道了成功登录后 role 的值是 user,而我们只需要将其替换为 admin ,然后直接访问 /flag,即可拿到 flag 0ops{x66ZTwpe5fbrJuD69SrAuA}

评论区

有什么意见和想法,欢迎在评论区提出,也欢迎聊天哦~