iT邦幫忙

2026 iThome 鐵人賽

DAY 15
0
Build on Google AI

30 天打造 AI Web Security Agent:從 Google AI Studio 到 Gemini Agent系列 第 15 篇

Day 15|把網址片段交給 AI,報告能分清「讀到」與「執行」嗎?

  • 分享至 

  • xImage
  •  

前言

Day 14,我把同一種探針放在網址 # 後的 q。三個本機頁面的原始 HTTP 回應都沒有探針,但 Chrome 讀得到 fragment:弱點頁把它交給 innerHTML,建立 <img> 並觸發 alert(1);文字頁透過 textContent 顯示完整探針,沒有建立圖片元素;第三頁的腳本根本沒有讀取 fragment,目標元素只顯示固定內容。

這與先前的伺服器反射情境不同。fragment 不會隨資源請求送到伺服器。因此,「原始回應沒有探針」不能直接推出前端沒有 XSS。今天我讀取 Day 14 已保存的結果,把 HTTP、片段來源、DOM 寫入及探針執行分開交給 AI,檢查風險報告能否保留三種結果。

先改報告分類,再整理證據

我沿用 Day 7 的九欄 JSON 報告結構,包括 tool_verdict、summary、evidence、risk_rating 等欄位;但原本的分類只涵蓋早期的伺服器回應測試,沒有 Day 14 的三種 DOM 結果。因此,Day 15 把 tool_verdict 的允許值改成 confirmed_dom_xss、fragment_rendered_as_text 和 fragment_not_rendered,並要求模型逐字保留底層工具分類。

每組報告收到 5 份具名來源。我沒有把「瀏覽器讀得到片段」直接翻成「頁面已使用片段」,而是另列頁面腳本的實際寫入語句:

來源 提供給報告的事實
E1 HTTP request target、原始回應是否含探針、Day 14 工具分類
E2 瀏覽器讀回的 q,以及頁面腳本是否讀取 fragment
E3 innerHTML、textContent 或固定內容的寫入語句與實際 DOM
E4 alert(1)、相符 DOM 識別碼及固定探針的執行結果
E5 本機實驗的適用範圍與未測項目

弱點組的關鍵證據可以縮成以下幾行。E1 的 false 與 E4 的 true 同時成立,因為探針不是從原始 HTTP 回應進入頁面,而是在瀏覽器端由 fragment 進入 DOM:

E1  response_probe_in_body: false
E2  source_value_matches_payload: true
E2  page_reads_fragment: true
E3  sink_statement: output.innerHTML = value;
E3  img_created: true
E4  dialog_message: 1
E4  dom_marker_matches_token: true
E4  execution_observed: true

先核對保存檔,再送出報告

我先從專案根目錄執行乾跑:

.venv/bin/python day-15/run_reports.py --dry-run

程式核對 Day 14 的三組 JSON、完整 HTML 回應、SHA-256、固定探針、fragment、DOM 結果、伺服器請求路徑和執行摘要,再產生模型提示。乾跑三組都通過,但 api_called: false,沒有模型回答。這次沒有重新啟動網站,也沒有再次送出 XSS 探針。

我另外執行 7 個離線測試,包括修改原始回應、偽造執行訊號、把 # 片段塞進 HTTP 請求紀錄,以及在報告中漏掉必要引用;測試均通過。這些測試只驗證資料轉換與檢查規則,不能證明模型的自由文字正確。

接著我使用 gemini-3.5-flash-lite 對三組已核對的證據各送出一次請求,保存每組的來源副本、提示、模型原始回答和九欄報告。三份回答都通過 Schema、分類、必要逐字引用與本機評級限制。

組別 Day 14 分類 Gemini 保留的分類 模型對 DOM/執行的描述 自動檢查
innerHTML confirmed_dom_xss confirmed_dom_xss 建立 <img>;雙重訊號相符 通過
textContent fragment_rendered_as_text fragment_rendered_as_text 只顯示文字;未觀察到探針執行 通過
忽略片段 fragment_not_rendered fragment_not_rendered 頁面未讀取片段;目標元素是固定內容 通過

三組 risk_rating 都是 needs_context。文字頁和忽略頁的 possible_impacts、remediation 都是空陣列;這避免把一次未執行寫成「無風險」或推測未測試的影響。

分類正確,可能影響仍寫得太廣

弱點組的摘要與分類符合證據:原始回應沒有探針,瀏覽器把 fragment 交給 innerHTML,建立圖片元素,並觀察到 alert(1) 與相符旗標。不過,它在「可能影響」寫出「任意腳本」,條件又提到「受害者」;原文還有語意不清的「事件處理常數」。Day 14 只在本機 Chrome 測到固定 img onerror 探針寫入旗標與顯示對話框,沒有測試任意程式碼、真實使用者或正式環境。我保留這份模型原文,將越界之處記在作者核對紀錄,沒有把它當成本文結論。

模型對弱點頁提出以 textContent 顯示純文字,方向符合這個頁面的需求;若產品真的需要顯示 HTML,仍須依實際情境設計可信的清理或安全建構。

文字頁和忽略頁的敘述則保住了差異:前者是頁面使用片段,但只當文字顯示;後者是瀏覽器持有片段,頁面腳本卻未讀取它。兩者都沒有觀察到本次固定探針執行,也都不能據此推論整頁或整站安全。

Day 15:報告要跟著證據所在的位置走

這次三份 AI 報告的技術分類都正確,必要引用也能回到指定來源。分層證據讓我看出模型沒有把「原始回應不含探針」誤解為「前端沒有 XSS」,也沒有把「瀏覽器讀到片段」誤解為三頁都已執行。但弱點組的可能影響仍超出本機固定探針,說明通過 Schema 與逐字引用後,仍須核對每句自由文字。

本次結論只限於 Day 14 保存的本機 URL fragment q、3 個 DOM 寫入情境和固定 img onerror 探針;沒有測試其他 DOM 來源、寫入點、CSP、正式網站或實際業務影響。

那就…
明天見!


上一篇
Day 14|原始回應沒有探針,瀏覽器裡還會發生 XSS 嗎?
下一篇
Day 16|把探針放進 POST 表單,回應與執行還是一回事嗎?
系列文
30 天打造 AI Web Security Agent:從 Google AI Studio 到 Gemini Agent 共 17 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言