#《隱形兵器 II:盲區手術》| Adversarial Machine Learning, Model Poisoning & Defensive Blind Spots | IDRI

《隱形兵器》

紅隊三部曲・中篇:盲區手術

——如果你無法遮住對方的眼睛,那就改變它所相信的世界


01|0.018

凌晨 03:07。

紅隊基地。

林祈安仍然坐在那張桌子前。

螢幕上的數字沒有變。

0.018

她已經看了三個小時。


程遠走進來。

「還沒睡?」

「沒有。」

「那個數字?」

「嗯。」

程遠把咖啡放在她旁邊。

「不就是 uncertainty?」

「不是。」

「那是什麼?」

林祈安沒有回答。

她把第一篇所有實驗重新跑了一遍。

不同 seed。

不同時間窗。

不同 sampling。

不同 baseline。

結果始終存在一個極小、但穩定的偏差。


P(unknown) ≈ 0.018


不是 noise。

不是 random artifact。

更不是模型偶然發瘋。

它像一根極細的針。

一直扎在模型的 latent space 裡。


林祈安終於說:

「我們的模型不知道自己不知道什麼。」

程遠皺眉。

「這不是很正常?」

「正常。」

她停了一下。

「但如果藍隊知道這件事呢?」


02|Aster

另一座城市。

顧青禾正在看同一個數字。

但她看到的不是:

0.018

而是一條曲線。


過去十七天。

未知行為的比例沒有增加。

甚至略微下降。

但 uncertainty 的分布開始產生結構。


不是:

Random Noise

而是:

Structured Uncertainty

顧青禾靠在椅背上。

「它開始知道我們在看。」

分析師問:

「你確定?」

「不。」

「那為什麼這樣判斷?」

她回答:

「因為真正隨機的東西,不會在我們改變觀測策略之後,跟著改變自己的形狀。」


她打開另一個視窗。

Model drift。

Data provenance。

Feature attribution。

全部正常。


只有一個東西不正常。

模型開始學會防禦模型。


03|第二層戰場

Richard在白板上寫下:

Network
   ↓
Behavior
   ↓
Model

然後把最後一個圈起來。


「第一篇。」

他說。

「我們在跟網路行為玩。」

「現在呢?」

程遠問。

Richard回答:

「我們開始跟相信網路行為的東西玩。」


周野抬頭。

「AI。」

「對。」

林祈安沒有說話。

她知道Richard真正想說的是:

Detection Model 本身就是 attack surface。


04|XDR

藍隊的新系統代號:

ASTER-X

不是單一模型。

是一個多模型協作框架。


Endpoint Telemetry
        ↓
Feature Extraction
        ↓
Behavior Encoder
        ↓
┌─────────────────────┐
│                     │
│  Network Model      │
│  Process Model      │
│  Identity Model     │
│  Graph Model        │
│  Temporal Model     │
│                     │
└──────────┬──────────┘
           ↓
     Risk Aggregator
           ↓
     Analyst Context

它最大的改變不是模型更深。

而是:

模型開始互相驗證。

一個模型說:

「可疑。」

另一個模型會問:

「證據?」

第三個模型再問:

「這個 evidence 是否與 historical behavior 一致?」


顧青禾把這套架構看了很久。

她知道:

這東西比第一代 XDR 強很多。

但她也知道。

越複雜的系統,越容易形成新的盲區。


05|Quill 的問題

林祈安在白板上寫:

Where does the model look?

下面又寫:

Where does the model refuse to look?


Richard看著她。

「妳想做什麼?」

「找 decision boundary。」

「太直接。」

「所以我要從 uncertainty 開始。」

周野問:

「妳想知道模型在哪裡不確定?」

「不。」

林祈安說:

「我想知道它在哪裡自信地錯。」


房間安靜了。

Richard笑了一下。

「這就開始有意思了。」


06|錯誤的形狀

任何分類模型都有錯誤。

問題不在於:

模型會不會錯。

而在於:

錯誤是不是有結構。

林祈安把模型輸出的 embedding 降維。

螢幕上出現一大片點。

正常行為形成幾個 cluster。

已知威脅形成另一側。

未知行為散落在邊界。


但其中有一小群。

非常奇怪。

它們不在正常區域。

也不在威脅區域。

而是在兩者之間。


林祈安放大。

「這裡。」

程遠問:

「什麼?」

「Decision boundary。」


Richard看著那片區域。

「所以?」

她回答:

「這裡不是漏洞。」

「這是什麼?」

「是模型對世界的理解方式。」


07|顧青禾的答案

藍隊也看到了那個區域。

但顧青禾沒有直接調整 threshold。

她先做了一件很少人願意做的事情:

承認模型不知道。

她把那一區標記:

Human Review Required

分析師問:

「這樣不是增加 workload?」

「會。」

「很多?」

「很多。」

「那為什麼?」

顧青禾看著他。

「因為我們如果只接受模型舒服的答案。」

「最後就會得到一個非常漂亮的錯誤世界。」


她把 threshold 暫時放低。

False Positive 上升。

SOC 開始抱怨。

但顧青禾沒有改。


她知道。

安全不是讓模型永遠正確。

而是讓錯誤發生時,有人知道它可能錯了。


08|Red Team 的第二階段

紅隊開始做 model-oriented evaluation。

不是修改 payload。

不是改變 exploit。

甚至沒有碰藍隊系統。

他們建立一個 shadow environment。

用來觀察:

模型如何做決策。


輸入。

輸出。

再輸入。

再輸出。


林祈安把每次結果記錄下來。

她觀察:

  • feature sensitivity
  • confidence calibration
  • decision stability
  • representation drift
  • attribution consistency

她沒有追求:

「怎麼讓惡意樣本被判成正常。」

那太低階。

她真正想知道的是:

模型在哪些情境下會改變自己的判斷?


09|FGSM

程遠看到 notebook 裡的一行字。

FGSM

他問:

「要真的做?」

林祈安搖頭。

「研究環境。」

「我知道。」

她補充:

「我們不碰 production。」


她在白板寫下概念:

x' = x + ε · sign(∇_x J(θ, x, y))


周野看了一眼。

「很漂亮。」

「數學很漂亮。」

「實際呢?」

林祈安說:

「實際世界沒那麼乾淨。」


因為真實系統不是一個簡單 image classifier。

Endpoint telemetry 有:

  • 離散特徵
  • 時間特徵
  • categorical feature
  • process relationship
  • graph topology
  • system constraints

所以紙上的 gradient:

不能直接等價於真實世界的可操作變化。


Richard點頭。

「很好。」

程遠問:

「哪裡好?」

「她開始討厭漂亮公式了。」


10|模型的錯覺

林祈安做了一組實驗。

她沒有尋找某個特定 payload。

而是觀察模型對微小 feature perturbation 的敏感度。

結果令人不舒服。


某些 feature 改變非常小。

模型 confidence 卻出現明顯變化。


Δx → small

但:

Δconfidence → large


林祈安盯著結果。

「這不是 robust model。」

Richard問:

「那是什麼?」

「一個很會回答問題。」

她停了一下。

「但不一定知道答案的模型。」


11|Poison

第二階段真正開始。

不是:

Attack the Model。

而是:

Attack What the Model Learns From。


顧青禾收到一份新的 data provenance report。

某些歷史資料出現微小異常。

來源沒有斷。

格式沒有壞。

timestamp 沒有明顯問題。

甚至 checksum 都正常。


但 metadata lineage:

不完整。


她皺眉。

「誰碰過 training corpus?」

沒有人回答。


她再次問:

「我要完整 provenance。」


資料工程師說:

「目前只能追到 ingestion layer。」

顧青禾看著他。

「再往前。」

「可能需要時間。」

她回答:

「時間就是現在最貴的東西。」


12|Richard的警告

紅隊內部。

程遠提出:

「如果能污染資料,模型就會自己替我們放大錯誤。」

周野冷冷地說:

「所以你開始覺得很興奮?」

「不是。」

「你臉上就是。」


Richard打斷兩人。

「Data poisoning 最麻煩的地方。」

所有人看向他。

「不是把資料改掉。」

「而是讓別人不知道資料被改過。」


他在白板上寫:

Data
  ↓
Training
  ↓
Model
  ↓
Decision

然後在 Data 與 Training 中間畫了一條線。


「真正的攻擊面,是 trust boundary。」


13|顧青禾開始逆向

顧青禾沒有直接追攻擊者。

她追資料。


她要求所有 training data 重新建立 lineage graph。

結果出現:

Source
 ↓
Collector
 ↓
Normalizer
 ↓
Feature Pipeline
 ↓
Dataset
 ↓
Training Job
 ↓
Model

其中有一條路徑:

沒有完整 provenance。


只有一個名字。

legacy-ingest


顧青禾盯著那個名稱。

她問:

「誰寫的?」

工程師說:

「很久以前的 pipeline。」

「多久?」

「三年左右。」


她沒有再問。

只說:

「先隔離。」


遠方。

周野正在看同一個名字。


14|Legacy

他盯著 terminal。

legacy-ingest

又看了一眼Richard。

「這名字。」

Richard說:

「我看過。」

「在哪?」

「以前。」

周野皺眉。

「你知道?」

「知道。」

「為什麼不說?」

Richard沉默了兩秒。

「因為我希望它已經不存在。」


這是第一次。

林祈安看到Richard真正的不安。


15|三年前

畫面切換。

三年前。

同一家公司。

另一批工程師。

另一間機房。

凌晨 02:43。


一個年輕工程師盯著 pipeline。

Build fail。

Retry。

再 fail。

他已經連續工作十六個小時。

同事問:

「還不走?」

「再五分鐘。」


他打開一段舊程式。

看到:

TODO

又看到:

temporary workaround

他嘆了一口氣。

「明天再改。」


他沒有想到:

三年後,這五分鐘會成為別人的問題。


16|回到現在

周野把視窗關掉。

「所以你早就知道?」

Richard回答:

「我知道那套系統。」

「知道它有問題?」

「知道它可能有問題。」

周野看著他。

「差很多。」

Richard點頭。

「對。」


林祈安問:

「為什麼沒有修?」

Richard沒有立即回答。

最後只說:

「因為當時還有更重要的事情。」


林祈安第一次沒有反駁。

因為她突然明白:

這才是真實世界。

不是:

Bug → Fix

而是:

Bug → Priority → Deadline → Risk Acceptance


17|模型開始偏移

藍隊的模型重新訓練。

結果變好。

Validation metrics 幾乎全部改善。


顧青禾卻皺眉。

「太好了。」

工程師說:

「不是好事嗎?」

「好得不自然。」


她看著 calibration curve。

某些區域的 confidence 提升得太漂亮。


她問:

「我們的 validation set 有沒有完全獨立?」

「有。」

「真的?」

「是。」

「Temporal split?」

「有。」

「Source split?」

「……沒有。」


顧青禾閉上眼睛。

「重新做。」


18|資料不是記憶

林祈安也得到了同樣的答案。

她對Richard說:

「Model 可以忘記。」

Richard看她。

「什麼?」

「如果 training data 被污染。」

「模型可能把錯誤當成記憶。」

Richard說:

「模型沒有記憶。」

林祈安搖頭。

「所以才危險。」


她看著螢幕。

「它不記得事情。」

「它只記得事情留下來的統計痕跡。」


這句話讓周野安靜了很久。


19|Blind Spot

紅隊重新分析藍隊模型。

這次不是找:

怎麼騙過模型。

而是:

模型最不可靠的地方在哪裡。


結果出現三種區域:

High Confidence / Correct
High Confidence / Wrong
Low Confidence / Unknown

真正危險的是第二個。


High Confidence + Wrong


Richard看著它。

「這就是盲區。」

林祈安點頭。

「不是模型看不到。」

「而是它看到了。」

「然後非常有自信地解釋錯。」


20|Aster 的反擊

顧青禾開始改變策略。

不再只看:

Confidence

她加入:

Uncertainty

Provenance

Cross-Model Agreement

Temporal Stability


最後形成新的 decision layer:

Model Confidence
       +
Uncertainty
       +
Data Provenance
       +
Cross-Model Agreement
       +
Temporal Consistency
       ↓
Human Review

林祈安看到這套架構時,沉默了很久。

「她在做什麼?」

Richard回答:

「她正在把模型的自信拆掉。」


21|真正的手術

這次紅隊沒有進一步追求更好的 deception。

Richard下了一個命令:

停止優化。

程遠愣住。

「什麼?」

「停止。」

「為什麼?」

Richard看著他。

「因為我們已經知道模型會錯。」

「接下來要做的是。」

他看向林祈安。

「找出它為什麼相信自己錯得對。」


這一刻。

紅隊的目標改變。

從:

Evade Detection

變成:

Understand Detection


而這才是真正的:

Blind Spot Surgery。


22|兩個世界

藍隊。

顧青禾正在修正自己的模型。

紅隊。

林祈安正在研究它。


兩邊都在做同一件事情:

尋找 uncertainty。


不同的是:

藍隊想消除它。

紅隊想利用它。


Richard卻知道。

這兩個答案都不完整。


他走到窗前。

夜色很深。

他忽然想起多年前的自己。

也是這樣。

以為只要把所有變數控制住。

事情就不會失控。

後來才知道:

真正讓系統失控的,往往不是變數。

而是:

人以為自己已經理解了變數。


23|最後一個樣本

凌晨 05:18。

林祈安跑最後一輪測試。

螢幕出現:

Confidence: 0.997

她沒有笑。


下面:

Provenance Confidence: 0.61

再下面:

Cross-Model Agreement: 0.48

最後:

Human Review: REQUIRED


她盯著那四行。

第一篇那個 0.018 又浮現在她腦中。


這一次。

她終於理解:

不確定性不是弱點。

它是系統誠實面對世界的最後一塊地方。


24|顧青禾的選擇

藍隊可以選擇直接提高 threshold。

也可以選擇降低 false positive。

甚至可以把所有 anomaly 強行分類。

但顧青禾沒有。

她按下:

RETAIN UNKNOWN


螢幕顯示:

Unknown states will remain unresolved.


工程師問:

「這樣不會很麻煩?」

她回答:

「會。」

「那為什麼?」

顧青禾看著他。

「因為安全系統最可怕的錯誤,不是說不知道。」

「是把不知道寫成知道。」


25|最後的裂痕

紅隊基地。

林祈安關掉 notebook。

程遠問:

「我們成功了嗎?」

她搖頭。

「沒有。」

「那我們失敗?」

「也沒有。」

程遠開始不耐煩。

「到底是什麼?」

林祈安看向Richard。

Richard沒有回答。


她說:

「我們只是證明了一件事。」

「什麼?」

「模型可以被影響。」


她停了一下。

「但模型也可以知道自己被影響。」


Richard看著她。

第一次沒有糾正。


26|The Blind Spot

顧青禾收到最後一份報告。

其中有一行:

Legacy ingestion path isolated.

她準備關掉畫面。

忽然。

另一個 alert 出現。


不是 malware。

不是 anomaly。

不是 C2。


只有:

Model disagreement detected.


她看了三秒。

然後笑了。

很輕。


「終於。」


同一時間。

紅隊模型也收到一個新的 signal。


Defensive Adaptation Detected.


林祈安看著螢幕。

「她開始改了。」

Richard說:

「嗯。」

「現在呢?」

Richard站起來。

拿起外套。


「現在,才算真正開始。」


《盲區手術》・完


Story Background|本篇故事背景

第一篇的戰場是:

Behavior。

第二篇則正式進入:

Model。

紅隊發現,藍隊的 AI 威脅偵測系統本身存在 representation、confidence、uncertainty 與 data provenance 等問題。

但藍隊並沒有停留在傳統的:

「提高模型準確率。」

而是開始意識到:

模型的錯誤本身就是攻擊面。

因此雙方的戰場從:

Network
   ↓
Traffic
   ↓
Behavior

進一步變成:

Behavior
   ↓
Representation
   ↓
Model
   ↓
Training Data
   ↓
Decision

Technical Architecture|本篇技術架構

紅隊

Behavior Dataset
       ↓
Representation Analysis
       ↓
Model Evaluation
       ↓
Decision Boundary Analysis
       ↓
Robustness Testing
       ↓
Blind-Spot Discovery

藍隊

Telemetry
    ↓
Feature Pipeline
    ↓
Multiple Models
    ↓
Confidence
    +
Uncertainty
    +
Provenance
    +
Cross-Model Agreement
    ↓
Human Review

本篇特別重要的概念:

  • Adversarial Machine Learning
  • FGSM / gradient-based robustness evaluation
  • Decision Boundary
  • Confidence Calibration
  • Model Uncertainty
  • Distribution Shift
  • Data Provenance
  • Data Lineage
  • Training-Serving Skew
  • Cross-Model Agreement
  • Model Drift
  • Representation Space
  • High-Confidence Error
  • Human-in-the-Loop

這裡刻意沒有把攻擊寫成「輸入一段神奇字串 → 模型立刻變瞎」。

那種寫法很爽。

也很假。

真正困難的地方是:

模型是一個複雜系統。

攻擊者要找的通常不是某個神奇 input。

而是:

哪些條件組合會讓模型產生穩定、可重現、而且人類不容易察覺的錯誤?


Character Development|人物變化

林祈安

第一篇:

「模型只要夠好,就能描述世界。」

第二篇:

「模型會犯錯。」

到了本篇結尾,她第一次理解:

「模型知道自己可能錯」比「模型永遠正確」更重要。

這會直接影響第三篇。


Richard

他開始看到一件自己不喜歡的事情:

自動化攻防正在逐漸脫離人的直覺。

他開始從「如何攻擊」轉向「何時停止」。

這會成為第三篇最大的道德衝突。


周野

他第一次碰到一個自己不熟悉的問題:

漏洞不一定存在於 code。

它可能存在於:

Dataset

Pipeline

Assumption

甚至:

Priority

他仍然相信 machine state。

但開始理解:

machine state 是人類決策累積出來的結果。


顧青禾

她從第一篇的:

找異常

進化到:

管理未知。

她沒有試圖消滅 uncertainty。

而是選擇保留它。

這個決定在第三篇會付出代價。


Hidden Foreshadowing|下一篇伏筆

① `legacy-ingest`

三年前的舊 pipeline 已經正式登場。

但它還不是答案。

它只是入口。


② 「Temporary workaround」

三年前那個工程師留下的東西,會再次出現。

而第三篇才會揭露:

真正危險的漏洞,往往不是沒人知道。

而是:

所有人都知道,但沒有人覺得今天需要處理。


③ `Model disagreement`

這不是普通 alert。

它代表:

藍隊的防禦系統開始產生內部認知分裂。

而紅隊也開始擁有足夠的自動化能力,去理解這種分裂。


④ Human Review

顧青禾選擇保留人工判斷。

這看似成熟。

但第三篇會提出一個殘酷問題:

當攻防速度進入機器時間尺度時,人類還來得及 review 嗎?


Leo's Note|技術後記

第一篇寫的是:

「如何看起來正常。」

第二篇寫的是:

「誰決定什麼叫正常。」

這兩個問題看起來只差幾個字。

實際上差了一整個世界。

很多 AI Security 報告喜歡寫:

Accuracy 99.7%

看起來很漂亮。

漂亮到像新車交車。

但真正做過系統的人知道,真正應該問的是:

那剩下的 0.3% 是什麼?

更討厭的是:

它是不是剛好發生在最重要的地方?

一個模型可以有極高 accuracy。

同時在某個極窄的 decision region 裡,非常有自信地錯。

這不是 bug。

這就是 machine learning。

模型不是世界。

模型只是:

對世界的一種壓縮。

而所有壓縮都有遺失。


四十五歲之後,我反而越來越不相信「完美系統」。

不是悲觀。

是看過太多 production。

真正成熟的工程師,不會跟你說:

「這套系統不會出問題。」

他會告訴你:

「這套系統出了問題,我知道它大概會從哪裡壞。」

這兩句話的價值,差得非常遠。

所以顧青禾選擇保留:

Unknown

而不是假裝世界已經被模型解完。

這是她目前最大的優勢。

也是她下一篇最大的弱點。

因為到了第三篇。

當兩邊的模型開始自動化迭代。

當 fuzzing、symbolic execution、reinforcement learning 與 automated response 開始進入 machine-speed。

「等人類來判斷」本身,可能就變成最大的 latency。

而那個三年前被寫成:

temporary workaround

的東西。

還在。

安靜地躺在某個不起眼的 memory lifecycle 裡。

沒有人每天看它。

沒有人覺得它重要。

直到有一天。

兩台機器都開始尋找漏洞。

卻只有一個老工程師曾經知道:

為什麼那段 code 當初會寫成那樣。

下一篇。

**《代碼的宿命》**

到那裡,這場戰爭才真正開始從「攻防」變成「速度」。

而速度一旦快過人類。

問題就不再是:

誰比較聰明。

而是:

誰留下的那個小錯誤,還活著。