Security

Chrome:帶有隨機 DNS 名稱的 DNS 請求:惡意軟體?

  • February 7, 2021

多年來(自 2005 年以來),我在我維護的多個 DNS / BIND 伺服器上看到了奇怪的隨機 DNS 請求的日誌。

May  7 12:13:50 1.1.1.1 named[63742]: client 1.1.1.2#24123 (verxkgiicjmcnxg): view internal: query: verxkgiicjmcnxg IN A + (1.1.1.1)
May  7 12:13:50 1.1.1.1 named[63742]: client 1.1.1.2#29159 (epqoaqsayo): view internal: query: epqoaqsayo IN A + (1.1.1.1)
May  7 12:13:50 1.1.1.1 named[63742]: client 1.1.1.2#27411 (qlllglwcjglu): view internal: query: qlllglwcjglu IN A + (1.1.1.1)

我通常將其歸結為一些 Windows 惡意軟體。但是,我最近開始注意到它也來自 Linux 和 Mac 客戶端。我再次認為這可能是由於某些惡意瀏覽器外掛造成的。

但是,在調試 Google Chrome 瀏覽器問題時,在我新安裝的 Macbook Pro/Chrome 中,使用 URL chrome://net-internals/#dns,我在 Chrome DNS 統計頁面中發現了類似的請求。

我的 Chrome 瀏覽器安裝了相當無害的外掛*,並且沒有明顯的惡意軟體跡象*。

我誠實地懷疑它是否應該是惡意活動。怎麼了?

(如圖所示, Chrome 發出的pnxcygqqemwwryzypwbheguutkdsnplueo DNS 名稱請求)。

dns

在 Chrome 瀏覽器打開時嗅探 DNS 活動,使用:

sudo tcpdump -n port 53

我可以看到以下 DNS 請求,以及 10:20:34 的隨機請求:

打開鉻:

tcpdump: data link type PKTAP
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on pktap, link-type PKTAP (Apple DLT_PKTAP), capture size 262144 bytes
10:20:27.119736 IP 1.1.1.2.12568 > 1.1.1.1.53: 10990+ A? apis.google.com. (33)
10:20:27.119962 IP 1.1.1.2.34930 > 1.1.1.1.53: 13828+ A? disconnect.me. (31)
10:20:27.120078 IP 1.1.1.2.17860 > 1.1.1.1.53: 37420+ A? mxr.mozilla.org. (33)
10:20:27.120314 IP 1.1.1.1.53 > 1.1.1.2.12568: 10990 2/4/4 CNAME plus.l.google.com., A 216.58.214.174 (206)
10:20:27.120479 IP 1.1.1.1.53 > 1.1.1.2.34930: 13828 3/4/8 A 54.197.255.152, A 54.225.94.202, A 204.236.239.134 (339)
10:20:27.120666 IP 1.1.1.1.53 > 1.1.1.2.17860: 37420 1/4/5 A 63.245.215.42 (234)
10:20:27.123394 IP 1.1.1.2.51642 > 1.1.1.1.53: 58375+ A? ssl.gstatic.com. (33)
10:20:27.123658 IP 1.1.1.2.17933 > 1.1.1.1.53: 48570+ A? www.google.pt. (31)
10:20:27.123726 IP 1.1.1.1.53 > 1.1.1.2.51642: 58375 1/4/4 A 216.58.214.163 (192)
10:20:27.123897 IP 1.1.1.2.57779 > 1.1.1.1.53: 7559+ A? www.gstatic.com. (33)
10:20:27.123946 IP 1.1.1.1.53 > 1.1.1.2.17933: 48570 1/4/4 A 216.58.207.163 (193)
10:20:27.124192 IP 1.1.1.1.53 > 1.1.1.2.57779: 7559 16/4/4 A 194.210.238.166, A 194.210.238.170, A 194.210.238.174, A 194.210.238.176, A 194.210.238.177, A 194.210.238.181, A 194.210.238.185, A 194.210.238.187, A 194.210.238.144, A 194.210.238.148, A 194.210.238.152, A 194.210.238.154, A 194.210.238.155, A 194.210.238.159, A 194.210.238.163, A 194.210.238.165 (432)
10:20:27.432926 IP 1.1.1.2.29865 > 1.1.1.1.53: 62300+ A? clients4.google.com. (37)
10:20:27.433219 IP 1.1.1.2.28193 > 1.1.1.1.53: 23734+ A? translate.googleapis.com. (42)
10:20:27.433703 IP 1.1.1.1.53 > 1.1.1.2.29865: 62300 2/4/4 CNAME clients.l.google.com., A 216.58.211.238 (213)
10:20:27.464772 IP 1.1.1.1.53 > 1.1.1.2.28193: 23734 1/4/4 A 216.58.198.202 (201)
10:20:28.430622 IP 1.1.1.2.46792 > 1.1.1.1.53: 1963+ A? accounts.google.com. (37)
10:20:28.431046 IP 1.1.1.1.53 > 1.1.1.2.46792: 1963 1/4/4 A 216.58.201.141 (189)
10:20:32.348765 IP 1.1.1.2.16654 > 1.1.1.1.53: 39847+ A? www.google.com. (32)
10:20:32.349362 IP 1.1.1.1.53 > 1.1.1.2.16654: 39847 1/4/4 A 216.58.213.164 (184)

幾秒鐘後,確實出現了提到的隨機 DNS 請求:

10:20:34.159229 IP 1.1.1.2.5042 > 1.1.1.1.53: 47676+ A? kblxfid.xxx.xxx.xxx. (44)
10:20:34.159829 IP 1.1.1.2.63360 > 1.1.1.1.53: 55094+ A? weefjmw.xxx.xxx.xxx. (44)
10:20:34.159893 IP 1.1.1.1.53 > 1.1.1.2.5042: 47676 NXDomain* 0/1/0 (104)
10:20:34.160230 IP 1.1.1.1.53 > 1.1.1.2.63360: 55094 NXDomain* 0/1/0 (104)
10:20:34.160872 IP 1.1.1.2.29339 > 1.1.1.1.53: 22434+ A? luebcanqpumlaj.xxx.xxx.xxx. (51)
10:20:34.161290 IP 1.1.1.1.53 > 1.1.1.2.29339: 22434 NXDomain* 0/1/0 (111)
10:20:34.162489 IP 1.1.1.2.64592 > 1.1.1.1.53: 49055+ A? kblxfid.xxx.xxx.xxx. (44)
10:20:34.162859 IP 1.1.1.1.53 > 1.1.1.2.64592: 49055 NXDomain* 0/1/0 (104)
10:20:34.164105 IP 1.1.1.2.50225 > 1.1.1.1.53: 1276+ A? weefjmw.xxx.xxx.xxx. (44)
10:20:34.164386 IP 1.1.1.2.52389 > 1.1.1.1.53: 59022+ A? luebcanqpumlaj.xxx.xxx.xxx. (51)
10:20:34.164472 IP 1.1.1.1.53 > 1.1.1.2.50225: 1276 NXDomain* 0/1/0 (104)
10:20:34.164751 IP 1.1.1.1.53 > 1.1.1.2.52389: 59022 NXDomain* 0/1/0 (111)

在 Chrome 中打開一個新標籤頁:

10:20:44.106915 IP 1.1.1.2.26171 > 1.1.1.1.53: 14460+ A? clients2.google.com. (37)
10:20:44.139387 IP 1.1.1.1.53 > 1.1.1.2.26171: 14460 2/4/4 CNAME clients.l.google.com., A 216.58.211.238 (213)

此外,根據@Gilles 連結,在 Chrome 中使用代理(Squid)時,您可以access.log在 Chrome 啟動時在相應的 Squid 日誌文件中看到隨機 DNS 名稱:

1494276554.709    216 127.0.0.1 TCP_MISS/504 277 HEAD http://vgifrooogs/ - DIRECT/vgifrooogs text/html
1494276554.731    238 127.0.0.1 TCP_MISS/504 277 HEAD http://cbwknhka/ - DIRECT/cbwknhka text/html  
1494276554.875    382 127.0.0.1 TCP_MISS/504 277 HEAD http://vtjhiag/ - DIRECT/vtjhiag text/html

我發現了一系列關於 Chrome 發出的隨機 DNS 請求的文章/錯誤報告。結論是隨機 DNS 請求既不是由惡意軟體生成的,也不是由外掛或附加組件生成的。

這些請求由 Chrome 完成,以了解它是否可以處理從其地址欄進行的搜尋。

下面引用了我找到的最佳解釋,來自此連結

如果您輸入單字搜尋查詢,chrome 需要發送 DNS 請求來檢查這是否可能是單字主機名:例如,“test”可能是搜尋“test”或導航到“ http://測試“。如果查詢最終成為主機,則 chrome 會顯示一個資訊欄,詢問“您是否打算改為轉到 ’test’”。出於性能原因,DNS 查詢需要是非同步的。

現在一些 ISP 開始為不存在的域名 ( http://en.wikipedia.org/wiki/DNS_hijacking ) 展示廣告,這意味著 Chrome 將始終為每個單字查詢顯示該資訊欄。由於這很煩人,chrome 現在會在啟動時發送三個隨機 DNS 請求,如果它們都解析(我認為是同一個 IP),它現在知道不為解析的單字查詢顯示“您的意思是”資訊欄到那個IP。

除了上面 Wikipedia 條目中提到的 ISP 級別或惡意軟體 DNS 劫持之外,一些付費無線接入點或強制門戶也會劫持 DNS。隨機請求是以看似隨機的時間間隔發出的,而不僅僅是在啟動 Chrome 時。至少,它們會在目前網路介面每次獲得新 IP 地址時發生。

這是來自@Gilles 的與主題相關的另一個連結:Unusual HEAD requests to nonsense URLs from Chrome。因此,將代理測試設置的主題添加到問題中。您最終會看到代理日誌,因為在配置代理時,請求是通過代理髮出的;並且,由代理來解析 DNS 請求。

由於線上上缺乏更多可靠的細節,我下載並閱讀了 Chromium 原始碼,使用以下命令。

git clone https://chromium.googlesource.com/chromium/src 

下面的引用是從 Chromium 原始碼註釋中複製的:

因為這個函式可以在啟動過程中被呼叫,當開始一個 URL fetch 會消耗 20 毫秒的時間,我們延遲了 7 秒,希望這個時間足夠長到啟動之後,但仍然可以快速返回結果。

該組件向三個隨機生成的主機名發送請求,因此可能不存在。如果至少有兩個重定向到相同的主機名,這表明 ISP 正在劫持 NXDOMAIN,並且多功能框在決定是否使用“您是否要導航”資訊欄提示使用者進行某些搜尋時應將類似的重定嚮導航視為“失敗”輸入。

觸發器:“在啟動時以及當電腦的 IP 地址發生變化時。”

我們生成一個包含 7 到 15 個字元的隨機主機名。

我的結論是,那些隨機的 DNS 請求名稱並不是惡意軟體行為的表現;它們是Chromium(和 Google Chrome)的探針,以了解它可以做什麼,至少涉及搜尋

由於網上缺乏更多可靠的細節,我在調查中下載了 Chromium 資源。處理此功能的邏輯可以在文件中找到,src/chrome/browser/intranet_redirect_detector.cc並且src/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc.

以下是以下內容的摘錄src/chrome/browser/intranet_redirect_detector.cc

void IntranetRedirectDetector::FinishSleep() {
 in_sleep_ = false;

 // If another fetch operation is still running, cancel it.
 fetchers_.clear();
 resulting_origins_.clear();

 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
 if (cmd_line->HasSwitch(switches::kDisableBackgroundNetworking))
   return;

 DCHECK(fetchers_.empty() && resulting_origins_.empty());

 // Create traffic annotation tag.
 net::NetworkTrafficAnnotationTag traffic_annotation =
     net::DefineNetworkTrafficAnnotation("intranet_redirect_detector", R"(
       semantics {
         sender: "Intranet Redirect Detector"
         description:
           "This component sends requests to three randomly generated, and "
           "thus likely nonexistent, hostnames.  If at least two redirect to "
           "the same hostname, this suggests the ISP is hijacking NXDOMAIN, "
           "and the omnibox should treat similar redirected navigations as "
           "'failed' when deciding whether to prompt the user with a 'did you "
           "mean to navigate' infobar for certain search inputs."
         trigger: "On startup and when IP address of the computer changes."
         data: "None, this is just an empty request."
         destination: OTHER
       }
       policy {
         cookies_allowed: false
         setting: "This feature cannot be disabled by settings."
         policy_exception_justification:
             "Not implemented, considered not useful."
       })");

 // Start three fetchers on random hostnames.
 for (size_t i = 0; i < 3; ++i) {
   std::string url_string("http://");
   // We generate a random hostname with between 7 and 15 characters.
   const int num_chars = base::RandInt(7, 15);
   for (int j = 0; j < num_chars; ++j)
     url_string += ('a' + base::RandInt(0, 'z' - 'a'));
   GURL random_url(url_string + '/');
   std::unique_ptr<net::URLFetcher> fetcher = net::URLFetcher::Create(
       random_url, net::URLFetcher::HEAD, this, traffic_annotation);
   // We don't want these fetches to affect existing state in the profile.
   fetcher->SetLoadFlags(net::LOAD_DISABLE_CACHE |
                         net::LOAD_DO_NOT_SAVE_COOKIES |
                         net::LOAD_DO_NOT_SEND_COOKIES |
                         net::LOAD_DO_NOT_SEND_AUTH_DATA);
   fetcher->SetRequestContext(g_browser_process->system_request_context());
   fetcher->Start();
   net::URLFetcher* fetcher_ptr = fetcher.get();
   fetchers_[fetcher_ptr] = std::move(fetcher);
 }
}

void IntranetRedirectDetector::OnURLFetchComplete(
   const net::URLFetcher* source) {
 // Delete the fetcher on this function's exit.
 auto it = fetchers_.find(const_cast<net::URLFetcher*>(source));
 DCHECK(it != fetchers_.end());
 std::unique_ptr<net::URLFetcher> fetcher = std::move(it->second);
 fetchers_.erase(it);

 // If any two fetches result in the same domain/host, we set the redirect
 // origin to that; otherwise we set it to nothing.
 if (!source->GetStatus().is_success() || (source->GetResponseCode() != 200)) {
   if ((resulting_origins_.empty()) ||
       ((resulting_origins_.size() == 1) &&
        resulting_origins_.front().is_valid())) {
     resulting_origins_.push_back(GURL());
     return;
   }
   redirect_origin_ = GURL();
 } 

….

以下是該文件的摘錄src/chrome/browser/ui/omnibox/chrome_omnibox_navigation_observer.cc

// Returns true if |final_url| doesn't represent an ISP hijack of
// |original_url|, based on the IntranetRedirectDetector's RedirectOrigin().
bool IsValidNavigation(const GURL& original_url, const GURL& final_url) {

….

void ChromeOmniboxNavigationObserver::NavigationEntryCommitted(
   const content::LoadCommittedDetails& load_details) {
 load_state_ = LOAD_COMMITTED;
 if (ResponseCodeIndicatesSuccess(load_details.http_status_code) &&
     IsValidNavigation(match_.destination_url,
                       load_details.entry->GetVirtualURL()))
   OnSuccessfulNavigation();
 if (!fetcher_ || (fetch_state_ != FETCH_NOT_COMPLETE))
   OnAllLoadingFinished();  // deletes |this|!
}

void ChromeOmniboxNavigationObserver::OnURLFetchComplete(
   const net::URLFetcher* source) {
 DCHECK_EQ(fetcher_.get(), source);
 const net::URLRequestStatus& status = source->GetStatus();
 int response_code = source->GetResponseCode();
 fetch_state_ =
     (status.is_success() && ResponseCodeIndicatesSuccess(response_code)) ||
             ((status.status() == net::URLRequestStatus::CANCELED) &&
              ((response_code / 100) == 3) &&
              IsValidNavigation(alternate_nav_match_.destination_url,
                                source->GetURL()))
         ? FETCH_SUCCEEDED
         : FETCH_FAILED;
 if (load_state_ == LOAD_COMMITTED)
   OnAllLoadingFinished();  // deletes |this|!
}

相關連結:混合大小寫 DNS 請求 - 我的網路中存在惡意軟體?.

略相關:為什麼 Chromium 記憶體 DNS 超過一分鐘?

引用自:https://unix.stackexchange.com/questions/363512