作為一名安全愛好者,在安全路上不斷探索的過程中,每次拜讀安全大牛的作品時,都有不同的收獲,證明你看待安全的角度和高度上了新臺階,第一次接觸過《白帽子講web安全》,小白的我既懵懂又敬佩,時隔多年,再次拜讀,雖說一些技術(shù)已過時,但思想是不老的,特此分享閱讀筆記。
作者格言
吳翰清領(lǐng)導(dǎo)的團隊每天幫助阿里云抵御16億次的黑客攻擊。吳翰清現(xiàn)在年薪五百多萬,甚至阿里的創(chuàng)始人馬云都說阿里離不了吳翰清。
互聯(lián)網(wǎng)本來是安全的,自從有了研究安全的人,就變得不安全了;
安全是一門樸素的學(xué)問,也是一種平衡的藝術(shù);
一個優(yōu)秀的安全方案,應(yīng)該是:在正確的地方,做正確的事。
安全工程師的核心競爭力不在于他能擁有多少個0day,掌握多少種安全技術(shù),而是在于他對安全理解的深度,以及由此引申的看待安全問題的角度和高度。
“破壞永遠比建設(shè)容易” “最大的漏洞就是人!”
如果新技術(shù)不在一開始就考慮安全設(shè)計的話,防御技術(shù)必然會落后于攻擊技術(shù);
安全問題的本質(zhì)是信任的問題。(將文件鎖在抽屜中);安全三要素:機密性、完整性、可用性。
不可預(yù)測性,能有效地對抗篡改、偽造的攻擊;(加密算法、隨機數(shù)、哈希算法)
白帽子與黑帽子
白帽子一般為企業(yè)或安全公司服務(wù),工作的出發(fā)點就是解決所有的安全問題,因此所看到的必然要求更加全面、宏觀;
黑帽子主要目的是入侵系統(tǒng),找到他們有價值的數(shù)據(jù),因此黑帽子只需要以點突破,找到對他們最有用的一點,以此滲透,因此思考問題的出發(fā)點必然是有選擇性的、微觀的。
客戶端腳本安全
HttpOnly不等于絕對安全
使用HtppOnly有助于緩解XSS攻擊,但還有竊取用戶信息、模擬用戶身份等嚴重后果,曾經(jīng)Apache支持的一個header是TRACE,TRACE一般用于調(diào)試,它會將請求頭作為HTTP的Response Body返回,利用這個特性可以把HtppOnly Cookie讀出來。目前各產(chǎn)商已經(jīng)修補這些漏洞,但未來也許會出現(xiàn)新的漏洞,現(xiàn)業(yè)界給關(guān)鍵業(yè)務(wù)添加HttpOnly Cookie已成為標準做法。
P3P(?Platform for Privacy Preferences,隱私設(shè)定平臺規(guī)范)
P3P頭的介入改變a.com的隱私策略,從而使<iframe>、<script>等標簽在IE中不再攔截第三方cookie的發(fā)送。P3P頭只需要由網(wǎng)站設(shè)置一次即可,之后每次請求都會遵循此策略,不需要重復(fù)設(shè)置。
P3P頭現(xiàn)在網(wǎng)站的應(yīng)用中被廣泛應(yīng)用,因此CSRF的防御不能依賴瀏覽器對的第三方Cookie的攔截策略,如果測試CSRF時發(fā)現(xiàn)<iframe>等標簽在IE中居然能發(fā)送cookie,可能是P3P在作怪。
Token
CSRF的Token僅僅用于對抗CSRF攻擊,當網(wǎng)站還同時存在XSS漏洞時,這個方案會無效,因為XSS可以模擬客戶端瀏覽器執(zhí)行任意操作,在XSS攻擊下,攻擊者完全可以請求頁面后,讀取出頁面內(nèi)容的Token值,然后再構(gòu)造一個合法的請求,這個過程稱之為XSRF,和CSRF以示區(qū)分。
注意Token的保密性和隨機性。
點擊劫持
點擊劫持與CSRF有異曲同工之妙,都是在用戶不知情的情況下誘使用戶完成操作,但在CSRF攻擊的過程中,如果出現(xiàn)用戶交互的頁面,功能可能無法順利完成。與之相反,點擊劫持利用的就是與用戶交互的界面。
利用圖片的style,或者能夠控制CSS,如果應(yīng)用沒有設(shè)置style的position為absolute的話,圖片就可以覆蓋到頁面的任意位置,形成點擊劫持。
X-Frame-Options是為了解決點擊劫持而生的,當值為DENY時,瀏覽器會拒絕當前頁面加載任何frame頁面;當值為SAMEORIGIN,frame頁面的地址只能為同域名下的頁面;若值為ALLOW-FROM,則可以定義允許frame加載的頁面地址。
Firefox的Content Security Policy以及Firefox的NoScript擴展可以有效防御點擊劫持;
HTML5安全
Canvas是H5最大創(chuàng)新之一,<canvas>標簽讓js可以在頁面直接操作圖片對象,也可直接操作像素,構(gòu)造圖片區(qū)域。
通過Canvas自動破譯驗證碼,最大的好處是可以在瀏覽器環(huán)境中實現(xiàn),降低攻擊門檻。H5使過去難以做到的事情變?yōu)榭赡堋?/b>
postMessage允許每一個window(包括當前窗口、彈出窗口、IFRAMES等)對象往其他窗口發(fā)送消息,從而實現(xiàn)跨窗口的消息傳遞。這個功能不受同源策略的限制。所以使用時需要注意:
1.必要時驗證窗口的Domain,甚至URL,實際是在代碼中實現(xiàn)一次同源策略的驗證過程。
2.在接收窗口不應(yīng)該信任接收到的消息,需要對消息進行安全檢查。
服務(wù)端應(yīng)用安全
注入攻擊的本質(zhì),是把用戶和輸入的數(shù)據(jù)當做代碼執(zhí)行。兩個關(guān)鍵條件:1是用戶能夠控制輸入;2是原本程序要執(zhí)行的代碼,拼接了用戶輸入的數(shù)據(jù)。
注入攻擊
INTO DUMPFILE適用于二進制文件,他會將目標文件寫入同一行內(nèi);而OUTFILE則更適用于文本文件。
寫入文件的技巧,經(jīng)常被用于導(dǎo)入一個webshell,因此在設(shè)計數(shù)據(jù)庫安全方案時,可以禁止普通數(shù)據(jù)庫用戶具備操作文件的權(quán)限。
一般來說,在數(shù)據(jù)庫中執(zhí)行系統(tǒng)命令,要求具有較高的權(quán)限。在建立數(shù)據(jù)庫賬戶時應(yīng)遵循“最小權(quán)限原則”,盡量避免給Web應(yīng)用使用數(shù)據(jù)庫管理員的權(quán)限。
UDF(用戶自定義函數(shù))
在攻擊過程中,將lib_mysqludf_sys.so上傳到數(shù)據(jù)庫可訪問的路徑。在創(chuàng)建UDF后,就可以使用sys_eval()和sys_exec()等函數(shù)執(zhí)行系統(tǒng)命令;

攻擊存儲過程
存儲過程為數(shù)據(jù)庫提供了強大的功能,跟UDF很像,但存儲過程必須使用CALL或EXECUTE執(zhí)行(臭名昭著的“xp_cmdshell”)。在MS SQL Server和Oracle數(shù)據(jù)庫中,都有大量的存儲過程,很多存儲過程存在SQL注入問題。
寬字節(jié)注入(基于字符集注入)
當php的addslashes()函數(shù)或者當magic_quotes_gpc開啟時,會在特殊字符前加轉(zhuǎn)義字符"\"
當mysql使用GBK編碼時,如: 0xbf27 or 1=1’
0x27被轉(zhuǎn)義為0x5c27,0x5c跟0xbf拼湊成一個字符,因此轉(zhuǎn)義符號0x5c(\)被吃掉。
要解決這個問題,需要統(tǒng)一數(shù)據(jù)庫、操作系統(tǒng)、web應(yīng)用所使用的的字符集,避免各層對字符理解存在差異。統(tǒng)一設(shè)置為UTF-8是個很好方法。
正確防御SQL注入
1.防御sql注入的最佳方式,就是使用預(yù)編譯語句,綁定變量。
2.使用安全的存儲過程對抗sql注入;需要將sql語句定義在數(shù)據(jù)庫中,存儲過程也可能存在注入,要避免使用動態(tài)SQL語句;如無法避免,則應(yīng)該使用嚴格的輸入過濾或者編碼函數(shù)來處理用戶的輸入數(shù)據(jù);
3.檢查數(shù)據(jù)類型,如限制輸入數(shù)據(jù)只能為integer;
4.使用安全函數(shù),如OWASP ESAPI;
5.為每個應(yīng)用分配不同的賬戶,web應(yīng)用使用的數(shù)據(jù)庫賬戶,不應(yīng)該創(chuàng)建自定義函數(shù)、操作本地文件的權(quán)限;
CRLF注入
CR是“\r”, 十六進制為0x0d
LF是“\n”,十六進制為0x0a;
\r\n這兩個字符用于表示換行。
CRLF注入并非僅能用于log注入,凡是使用CRLF作為分隔符的地方都有可能存在注入,如“注入HTTP頭”
對抗CRLF非常簡單,只要處理好“\r”"\n"這兩個字符即可,尤其是那些使用“換行符”作為分隔符的應(yīng)用。
設(shè)計安全的文件上傳功能
1.文件上傳的目錄設(shè)置為不可執(zhí)行;(文件上傳后放到獨立的存儲上,做靜態(tài)文件處理)
2.判斷文件類型,結(jié)合mime type、后綴檢查,推薦使用白名單;對于圖片處理,使用壓縮函數(shù)或relize函數(shù),在處理圖片的同時破壞可能包含的HTML代碼。
3.使用隨機數(shù)改寫文件名和文件路徑。
4.單獨設(shè)置文件服務(wù)器的域名;(瀏覽器同源策略)
Apache文件解析問題:在1.x,2.x中,對文件名從后往前解析,知道遇見認識的文件類型為止定義在(mime.types),將a.php.rar解析成a.php;
IIS文件解析問題:當文件名為abc.asp;xx.jpg時,IIS6將文件解析為abc.asp;
加密算法與隨機數(shù)
ECB模式的缺陷
對于ECB模式來說,改變分組密文的順序,將改變解密后的明文順序;替換某個分組密文,解密后該對應(yīng)分組的明文也會被替換,而其他分組不受影響;黨需要加密的明文大于一個分組長度時,應(yīng)變使用ECB模式;
PKCS#5填充
Padding Oracle Attack,對CBC模式,在不知道密鑰的情況下,對padding bytes進行嘗試,還原出明文,或者構(gòu)造出任意明文的密文;
類似于差分故障注入,原理為:假iv? ^ 假明文 =真iv ^ 真明文=中間值
密鑰管理
密碼系統(tǒng)的安全性應(yīng)該依賴于密鑰的復(fù)雜性,而不是算法的復(fù)雜性;
密鑰管理最常見的錯誤,就是將密鑰硬編碼在代碼中;一是可能導(dǎo)致代碼被廣泛傳播,二是軟件開發(fā)團隊的成員都能查看代碼;
對web應(yīng)用,常見的做法是將密鑰(包括密碼)保存在配置文件或者數(shù)據(jù)庫中,每個web應(yīng)用需要使用密鑰時,通過帶認證信息的API請求密鑰管理系統(tǒng),動態(tài)獲取密鑰,保護密鑰私密性。
在應(yīng)用發(fā)布到生產(chǎn)環(huán)境中,需要重新生成新的密鑰或密碼,以免與測試環(huán)境中使用的密鑰相同。
密鑰集中管理,降低系統(tǒng)對于密鑰的耦合性,也有利于定期更換密鑰;密鑰管理的主要目的,防止密鑰從非正常的渠道泄露。
時間真的隨機嗎
切記:不要把時間函數(shù)當成隨機數(shù)使用;
種子一旦確定,在通過同一偽隨機數(shù)算法計算出來的隨機數(shù),其值是固定的,多次計算所得之也是固定的;
一定要使用足夠強大的隨機數(shù)生成算法,在java中,可以使用java.security.SecureRandom
web框架安全
xss防御
通過自定義的方法,使xss防御的功能得到完善;甚至在代碼檢測工具中,可以自動判斷使用哪種安全的編碼方法;依據(jù)“是否有細分場景使用不同的編碼方式”來判斷XSS的安全方案是否完整;不可盲從指導(dǎo)文檔。
CSRF防御
使用security token得私密性(不可預(yù)測原則)解決CSRF攻擊問題;
“讀數(shù)據(jù)”不是CSRF的攻擊目標,對“讀數(shù)據(jù)”“寫數(shù)據(jù)”予以區(qū)分,比如要求所有的寫操作都是用HTTP POST;

在spring mvc以及一些其他流行的web框架,并沒有直接針對CSRF的保護,需要自己實現(xiàn);
HTTP headers管理
框架會提供一個統(tǒng)一的設(shè)置cookie函數(shù),HttpOnly的功能可以在此函數(shù)實現(xiàn);就不用擔(dān)心有遺漏;
對框架來說,管理好跳轉(zhuǎn)的目的地址是必要的
(1)如果提供統(tǒng)一的跳轉(zhuǎn)函數(shù),可以實現(xiàn)一個白名單,制定跳轉(zhuǎn)地址只能在白名單內(nèi);
(2)控制HTTP的Location字段,限制只能哪些地址,本質(zhì)還是白名單;
文件包含漏洞
本地文件包含漏洞(LFI)
php的include()、require()、include_once()、require_once()包含一個新的文件時,該文件作為PHP代碼執(zhí)行,PHP內(nèi)核不在意被包含的文件是什么類型;
fopen()、fread()能夠讀取敏感文件帶來的后果也比較嚴重;
php的open_basedir作用是限制在某個特定目錄下PHP能打開的文件,避免目錄遍歷漏洞;
要解決文件包含漏洞,應(yīng)該避免包含動態(tài)的變量,使用枚舉:

遠程文件包含(RFI)
如果PHP的配置選項allow_url_include為ON的話,include/require是可以加載遠程文件的。
遠程代碼執(zhí)行
PHP中有不少可以直接執(zhí)行代碼的函數(shù),如:eval()、assert()、system()、exec()、shell_exec()、passthru()、pcntl_exec()等。
一般來說,最好在PHP中禁用這些函數(shù);

unserialize()導(dǎo)致代碼執(zhí)行
unserialize()它能將序列化的數(shù)據(jù)重新映射為PHP變量。如果定義了_destruct()函數(shù),或者是_wakeup()函數(shù),這兩個函數(shù)將執(zhí)行。

定制安全的PHP環(huán)境
register_globals:為ON時,php不知道變量從何而來,容易出現(xiàn)變量覆蓋,強烈建議設(shè)置為OFF;
為了對抗遠程文件包含,請關(guān)閉allow_url_include和allow_url_fopen;
display_errors,錯誤回顯,一般用于開發(fā)模式,推薦關(guān)閉;
magic_quotes_gpc
推薦關(guān)閉,還能提高性能,不值得依賴;
session.cookie_httponly=1:開啟;
session.cookie_secure:若是全站https則開啟;
cgi.fix_pathinfo:若php以cgi安裝,則需關(guān)閉,避免文件解析問題;(訪問/test.jpg/noexit.php將jpg解析成php)
safe_mode:會影響很多函數(shù),如實共享環(huán)境,建議開啟,與disable_functions配合使用;如是單獨的應(yīng)用環(huán)境,考慮關(guān)閉,更多依賴disable_functions控制環(huán)境安全;
disable_functions:在php中禁用函數(shù),禁用函數(shù)可能為開發(fā)帶來不便,禁用太少增加寫出不安全代碼的幾率;
對于PHP6來說,magic_guotes_gpc、safe_mode已經(jīng)取消;
Web Server配置安全
檢查module安裝情況,根據(jù)"最小權(quán)限原則"運行web進程,盡可能減少不必要的module,檢查使用的module對應(yīng)版本是否存在已知漏洞;
一些參數(shù)可以優(yōu)化性能,緩解DDOS攻擊;
最后,補充一句,如果我們的產(chǎn)品能夠潛移默化地培養(yǎng)用戶的安全習(xí)慣,將用戶往更安全的行為上引導(dǎo),這樣的安全是最理想的產(chǎn)品安全;