作者:Gilberto Najera-Gutierrez
譯者:飛龍
協(xié)議:CC BY-NC-SA 4.0
簡(jiǎn)介
每個(gè)滲透測(cè)試的目標(biāo)都是識(shí)別應(yīng)用、服務(wù)器或網(wǎng)絡(luò)中的可能缺陷绣檬,它們能夠讓攻擊者有機(jī)會(huì)獲得敏感系統(tǒng)的信息或訪問(wèn)權(quán)限窝趣。檢測(cè)這類漏洞的原因不僅僅是了解它們的存在以及推斷出其中的漏洞鸽嫂,也是為了努力預(yù)防它們或者將它們降至最小。
這一章我們经柴,我們會(huì)觀察一些如何預(yù)防多數(shù) Web 應(yīng)用漏洞的例子和推薦挟憔,根據(jù) OWASP:
https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project
10.1 預(yù)防注入攻擊
根據(jù) OWASP憎妙,Web 應(yīng)用中發(fā)現(xiàn)的最關(guān)鍵的漏洞類型就是一些代碼的注入攻擊,例如 SQL 注入曲楚、OS 命令注入、HTML 注入(XSS)褥符。
這些漏洞通常由應(yīng)用的弱輸入校驗(yàn)導(dǎo)致龙誊。這個(gè)秘籍中,我們會(huì)設(shè)計(jì)一些處理用戶輸入和構(gòu)造所使用的請(qǐng)求的最佳實(shí)踐喷楣。
操作步驟
- 為了防止注入攻擊趟大,首先需要合理校驗(yàn)輸入。在服務(wù)端铣焊,這可以由編寫我們自己的校驗(yàn)流程來(lái)實(shí)現(xiàn)逊朽,但是最佳選擇是使用語(yǔ)言自己的校驗(yàn)流程,因?yàn)樗鼈兏訌V泛使用并測(cè)試過(guò)曲伊。一個(gè)極好的激勵(lì)就是 PHP 中的
filter_var
叽讳,或者 ASP.NET 中的 校驗(yàn)助手。例如坟募,PHP 中的郵箱校驗(yàn)類似于:
1 function isValidEmail($email){
2 return filter_var($email, FILTER_VALIDATE_EMAIL);
3 }
- 在客戶端岛蚤,檢驗(yàn)可以由創(chuàng)建 JavaScript 校驗(yàn)函數(shù)來(lái)完成,使用正則表達(dá)式懈糯。例如涤妒,郵箱檢驗(yàn)流程是:
1 function isValidEmail (input) {
2 var result=false;
3 var email_regex = /^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+\.)+[azA-Z0-9.-]{2,4}$/;
4 if ( email_regex.test(input) ) {
5 result = true;
6 }
7 return result;
8 }
- 對(duì)于 SQL 注入,避免拼接輸入值為查詢十分關(guān)鍵赚哗。反之她紫,使用參數(shù)化查詢硅堆。每個(gè)編程語(yǔ)言都有其自己的版本:
PHP MySQLLi:
1 $query = $dbConnection->prepare('SELECT * FROM table WHERE name = ?');
2 $query->bind_param('s', $name);
3 $query->execute();
C#:
1 string sql = "SELECT * FROM Customers WHERE CustomerId = @ CustomerId";
2 SqlCommand command = new SqlCommand(sql); command.Parameters.Add(new SqlParameter("@CustomerId", System. Data.SqlDbType.Int));
3 command.Parameters["@CustomerId"].Value = 1;
Java:
1 String custname = request.getParameter("customerName");
2 String query = "SELECT account_balance FROM user_data WHERE user_ name =? ";
3 PreparedStatement pstmt = connection.prepareStatement( query );
4 pstmt.setString( 1, custname);
5 ResultSet results = pstmt.executeQuery( );
考慮注入出現(xiàn)的時(shí)機(jī),對(duì)減少可能的損失總量也有幫助贿讹。所以渐逃,使用低權(quán)限的系統(tǒng)用戶來(lái)運(yùn)行數(shù)據(jù)庫(kù)和 Web 服務(wù)器。
確保輸入用于連接數(shù)據(jù)庫(kù)服務(wù)器的用戶不是數(shù)據(jù)庫(kù)管理員围详。
禁用甚至刪除允許攻擊者執(zhí)行系統(tǒng)命令或提權(quán)的儲(chǔ)存過(guò)程朴乖,例如 MSSQL 服務(wù)器中的
xp_cmdshell
。
工作原理
預(yù)防任何類型代碼注入攻擊的主要部分永遠(yuǎn)是合理的輸入校驗(yàn)助赞,位于服務(wù)端也位于客戶端买羞。
對(duì)于 SQL 注入,始終使用參數(shù)化或者預(yù)編譯查詢雹食。而不是拼接 SQL 語(yǔ)句和輸入畜普。參數(shù)化查詢將函數(shù)參數(shù)插入到 SQL 語(yǔ)句特定的位置,消除了程序員通過(guò)拼接構(gòu)造查詢的需求群叶。
這個(gè)秘籍中吃挑,我們使用了語(yǔ)言內(nèi)建的校驗(yàn)函數(shù),但是如果你需要校驗(yàn)一些特殊類型的參數(shù)街立,你可以通過(guò)使用正則表達(dá)式創(chuàng)建自己的版本舶衬。
除了執(zhí)行正確校驗(yàn),我們也需要在一些人蓄意注入一些代碼的情況下赎离,降低淪陷的影響逛犹。這可以通過(guò)在操作系統(tǒng)的上下文中為 Web 服務(wù)器合理配置用戶權(quán)限,以及在數(shù)據(jù)庫(kù)服務(wù)器上下文中配置數(shù)據(jù)庫(kù)和 OS 來(lái)實(shí)現(xiàn)梁剔。
另見(jiàn)
對(duì)于數(shù)據(jù)校驗(yàn)來(lái)講虽画,最有用的工具就是正則表達(dá)式。在處理和過(guò)濾大量信息的時(shí)候荣病,它們也能夠讓滲透測(cè)試變得更容易码撰。所以好好了解它們很有必要。我推薦你查看一些站點(diǎn):
http://www.regexr.com/ 一個(gè)很好的站點(diǎn)个盆,其中我們可以獲得示例和參數(shù)并測(cè)試我們自己的表達(dá)式來(lái)查看是否有字符串匹配脖岛。
http://www.regular-expressions.info 它包含教程和實(shí)例來(lái)了解如何使用正則表達(dá)式。它也有一份實(shí)用的參考颊亮,關(guān)于主流語(yǔ)言和工具的特定實(shí)現(xiàn)鸡岗。
http://www.princeton.edu/~mlovett/reference/Regular-Expressions.pdf (Jan Goyvaerts 編寫的《Regular Expressions, The Complete Tutorial》)就像它的標(biāo)題所說(shuō),它是個(gè)正則表達(dá)式的非常完備的腳本编兄,包含許多語(yǔ)言的示例轩性。
10.2 構(gòu)建合理的身份驗(yàn)證和會(huì)話管理
帶有缺陷的身份驗(yàn)證和會(huì)話管理是當(dāng)今 Web 應(yīng)用中的第二大關(guān)鍵的漏洞。
身份驗(yàn)證是用戶證明它們是它們所說(shuō)的人的過(guò)程。這通常通過(guò)用戶名和密碼來(lái)完成揣苏。一些該領(lǐng)域的常見(jiàn)缺陷是寬松的密碼策略悯嗓,以及隱藏式的安全(隱藏資源缺乏身份驗(yàn)證)。
會(huì)話管理是登錄用戶的會(huì)話標(biāo)識(shí)符的處理卸察。在 Web 服務(wù)器中脯厨,這可以通過(guò)實(shí)現(xiàn)會(huì)話 Cookie 和標(biāo)識(shí)來(lái)完成。這些標(biāo)識(shí)符可以植入坑质、盜取合武,或者由攻擊者使用社會(huì)工程、XSS 或 CSRF 來(lái)“劫持”涡扼。所以稼跳,開(kāi)發(fā)者必須特別注意如何管理這些信息。
這個(gè)秘籍中吃沪,我們會(huì)設(shè)計(jì)到一些實(shí)現(xiàn)用戶名/密碼身份驗(yàn)證汤善,以及管理登錄用戶的會(huì)話標(biāo)識(shí)符的最佳實(shí)踐。
操作步驟
如果應(yīng)用中存在只能由授權(quán)用戶查看的頁(yè)面票彪、表單或者任何信息片段红淡,確保在展示它們之前存在合理的身份驗(yàn)證。
確保用戶名降铸、ID在旱、密碼和所有其它身份驗(yàn)證數(shù)據(jù)是大小寫敏感的,并且對(duì)每個(gè)用戶唯一推掸。
建立強(qiáng)密碼策略桶蝎,強(qiáng)迫用戶創(chuàng)建至少滿足下列條件的密碼:
- 對(duì)于 8 個(gè)字符,推薦 10 個(gè)终佛。
- 使用大寫和小寫字母。
- 至少使用一個(gè)數(shù)字雾家。
- 至少使用一個(gè)特殊字符(空格铃彰、
!
、&
芯咧、#
牙捉、%
,以及其它)敬飒。 - 禁止用戶名邪铲、站點(diǎn)名稱、公司名稱或者它們的變體(大小寫轉(zhuǎn)換无拗、l33t带到、它們的片段)用于密碼。
- 禁止使用“常見(jiàn)密碼”列表中的密碼:https://www.teamsid.com/worst-passwords-2015/ 英染。
- 永遠(yuǎn)不要顯示用戶是否存在或者信息格式是否正確的錯(cuò)誤信息揽惹。對(duì)不正確的登錄請(qǐng)求被饿、不存在的用戶、名稱或密碼不匹配模式搪搏、以及所有可能的登錄錯(cuò)誤使用相同的泛化信息狭握。這種信息類似于:
- 登錄數(shù)據(jù)不正確。
- 用戶名或密碼無(wú)效疯溺。
- 訪問(wèn)禁止论颅。
密碼不能以純文本格式儲(chǔ)存在數(shù)據(jù)庫(kù)中。使用強(qiáng)哈希算法囱嫩,例如 SHA-2恃疯、scrypt、或者 bcrypt挠说,它們特別為難以使用 GPU 破解而設(shè)計(jì)澡谭。
在對(duì)比用戶輸入和密碼時(shí),計(jì)算輸入的哈希之后比較哈希之后的字符串损俭。永遠(yuǎn)不要解密密碼來(lái)使用純文本用戶輸入來(lái)比較蛙奖。
避免基本的 HTML 身份驗(yàn)證。
-
可能的話杆兵,使用多因素驗(yàn)證(MFA)雁仲,這意味著使用不止一個(gè)身份驗(yàn)證因素來(lái)登錄:
- 一些你知道的(賬戶信息或密碼)
- 一些你擁有的(標(biāo)識(shí)或手機(jī)號(hào))
- 一些你的特征(生物計(jì)量)
如果可能的話,實(shí)現(xiàn)證書(shū)琐脏、預(yù)共享密鑰攒砖、或其它無(wú)需密碼的身份校驗(yàn)協(xié)議(OAuth2、OpenID日裙、SAML吹艇、或者 FIDO)。
對(duì)于會(huì)話管理昂拂,推薦使用語(yǔ)言內(nèi)建的會(huì)話管理系統(tǒng)受神,Java、ASP.NET和 PHP格侯。它們并不完美鼻听,但是能夠確保提供設(shè)計(jì)良好和廣泛測(cè)試的機(jī)制,而且比起開(kāi)發(fā)團(tuán)隊(duì)在時(shí)間緊迫情況下的自制版本联四,它們更易于實(shí)現(xiàn)撑碴。
始終為登錄和登錄后的頁(yè)面使用 HTTPS – 顯然,要防止只接受 SSL 和 TLS v1.1 連接朝墩。
為了確保 HTTPS 能夠生效醉拓,可以使用 HSTS。它是由 Web 應(yīng)用指定的雙向選擇的特性。通過(guò) Strict-Transport-Security 協(xié)議頭廉嚼,它在 http://
存在于 URL 的情況下會(huì)重定向到安全的選項(xiàng)玫镐,并防止“無(wú)效證書(shū)”信息的覆寫。例如使用 Burp Suite 的時(shí)候會(huì)出現(xiàn)的情況怠噪。更多信息請(qǐng)見(jiàn):https://www.owasp.org/index.php/HTTP_Strict_Transport_Security 恐似。始終設(shè)置 HTTPOnly 和安全的 Cookie 屬性。
設(shè)置最少但實(shí)際的會(huì)話過(guò)期時(shí)間傍念。確保正常用戶離開(kāi)之后矫夷,攻擊者不能復(fù)用會(huì)話,并且用戶能夠執(zhí)行應(yīng)用打算執(zhí)行的操作憋槐。
工作原理
身份校驗(yàn)機(jī)制通常在 Web 應(yīng)用中簡(jiǎn)化為用戶名/密碼登錄頁(yè)面双藕。雖然并不是最安全的選擇,但它對(duì)于用戶和開(kāi)發(fā)者最簡(jiǎn)單阳仔,以及當(dāng)密碼被盜取時(shí)忧陪,最重要的層面就是它們的強(qiáng)度。
我們可以從這本書(shū)看到近范,密碼強(qiáng)度由破解難度決定嘶摊,通過(guò)爆破、字典或猜測(cè)评矩。這個(gè)秘籍的第一個(gè)提示是為了使密碼更難以通過(guò)建立最小長(zhǎng)度的混合字符集來(lái)破解叶堆,難以通過(guò)排除更直覺(jué)的方案(用戶名、常見(jiàn)密碼斥杜、公司名稱)來(lái)猜測(cè)虱颗,并且通過(guò)使用強(qiáng)哈希或加密儲(chǔ)存蔗喂,難以在泄露之后破解忘渔。
對(duì)于會(huì)話管理來(lái)說(shuō),過(guò)期時(shí)間缰儿、唯一性和會(huì)話 ID 的強(qiáng)度(已經(jīng)在語(yǔ)言內(nèi)建機(jī)制中實(shí)現(xiàn))畦粮,以及 Cookie 設(shè)置中的安全都是關(guān)鍵的考慮因素。
談?wù)撋矸菪r?yàn)安全的最重要的層面是返弹,如果消息可以通過(guò)中間人攻擊攔截或者服務(wù)锈玉,沒(méi)有任何安全配置爪飘、控制或強(qiáng)密碼是足夠安全的义起。所以,合理配置的加密通信頻道的使用师崎,例如 TLS默终,對(duì)保護(hù)我們的用戶身份數(shù)據(jù)來(lái)說(shuō)極其重要。
另見(jiàn)
OWASP 擁有一些非常好的頁(yè)面,關(guān)于身份校驗(yàn)和會(huì)話管理齐蔽。我們推薦你在構(gòu)建和配置 Web 應(yīng)用時(shí)閱讀并仔細(xì)考慮它們两疚。
- https://www.owasp.org/index.php/Authentication_Cheat_Sheet
- https://www.owasp.org/index.php/Session_Management_Cheat_Sheet
10.3 預(yù)防跨站腳本
我們之前看到,跨站腳本含滴,在展示給用戶的數(shù)據(jù)沒(méi)有正確編碼诱渤,并且瀏覽器將其解釋并執(zhí)行為腳本代碼時(shí)發(fā)生。這也存在輸入校驗(yàn)因素谈况,因?yàn)閻阂獯a通常由輸入變量插入勺美。
這個(gè)秘籍中,我們會(huì)涉及開(kāi)發(fā)者所需的輸入校驗(yàn)和輸出編碼碑韵,來(lái)防止應(yīng)用中的 XSS 漏洞赡茸。
工作原理
應(yīng)用存在 XSS 漏洞的第一個(gè)標(biāo)志是,頁(yè)面準(zhǔn)確反映了用戶提供的輸入祝闻。所以占卧,嘗試不要使用用戶提供的信息來(lái)構(gòu)建輸出文本。
當(dāng)你需要將用戶提供的信息放在輸出頁(yè)面上時(shí)联喘,校驗(yàn)這些數(shù)據(jù)來(lái)防止任何類型代碼的插入华蜒。我們已經(jīng)在 A1 中看到如何實(shí)現(xiàn)它。
出于一些原因耸袜,如果用戶被允許輸入特殊字符或者代碼段友多,在它插入到輸出之前,過(guò)濾或合理編碼文本堤框。
對(duì)于過(guò)濾域滥,在 PHP 中,可以使用
filter_var
蜈抓。例如启绰,如果你想讓字符串為郵件地址:
1 $email = "john(.doe)@exa//mple.com";
2 $email = filter_var($email, FILTER_SANITIZE_EMAIL);
3 echo $email;
對(duì)于編碼,你可以在 PHP 中使用htmlspecialchars
:
1 $str = "The JavaScript HTML tags are <script> for opening, and </ script> for closing.";
2 echo htmlspecialchars($str);
在 .NET 中沟使,對(duì)于 4.5 及更高版本委可,System.Web.Security.AntiXss
命名空間提供了必要的工具。對(duì)于 .NET 框架 4 及之前的版本腊嗡,你可以使用 Web 保護(hù)庫(kù):http://wpl.codeplex.com/
着倾。同樣,為了防止儲(chǔ)存型 XSS燕少,在儲(chǔ)存進(jìn)數(shù)據(jù)庫(kù)或從數(shù)據(jù)庫(kù)獲取之前卡者,編碼或過(guò)濾每個(gè)信息片段。
不要忽略頭部客们、標(biāo)題崇决、CSS和頁(yè)面的腳本區(qū)域材诽,因?yàn)樗鼈円部梢员焕谩?/p>
工作原理
除了合理的輸入校驗(yàn),以及不要將用戶輸入用作輸出信息恒傻,過(guò)濾和編碼也是防止 XSS 的關(guān)鍵層面脸侥。
過(guò)濾意味著從字符串移除不允許的字符。這在輸入字符串中存在特殊字符時(shí)很實(shí)用盈厘。
編碼將特殊字符轉(zhuǎn)換為 HTML 代碼表示睁枕。例如,&
變?yōu)?code>&沸手、<
變?yōu)?code><譬重。一些應(yīng)用允許在輸入字符串中使用特殊字符,對(duì)它們來(lái)說(shuō)過(guò)濾不是個(gè)選擇罐氨。所以應(yīng)該在將輸入插入頁(yè)面臀规,或者儲(chǔ)存進(jìn)數(shù)據(jù)庫(kù)之前編碼輸入。
另見(jiàn)
OWASP 擁有值得閱讀的 XSS 預(yù)防速查表:
10.4 避免直接引用不安全對(duì)象
當(dāng)應(yīng)用允許攻擊者(也是校驗(yàn)過(guò)的用戶)僅僅修改請(qǐng)求中的栅隐,直接指向系統(tǒng)對(duì)象的參數(shù)值塔嬉,來(lái)訪問(wèn)另一個(gè)未授權(quán)的對(duì)象時(shí),就存在不安全對(duì)象的直接引用(IDOR)租悄。我們已經(jīng)在本地文件包含和目錄遍歷漏洞中看到了一些例子谨究。
根據(jù) OWASP,IDOR 是 Web 應(yīng)用中第四大關(guān)鍵漏洞泣棋。這些漏洞通常由不良的訪問(wèn)控制實(shí)現(xiàn)胶哲,或者“隱藏式安全”策略(如果用戶不能看到它锥咸,他們就不能知道它的存在)導(dǎo)致淮腾。這些在沒(méi)有經(jīng)驗(yàn)的開(kāi)發(fā)者之中是個(gè)常見(jiàn)的做法。
這個(gè)秘籍中凶掰,我們會(huì)涉及在設(shè)計(jì)訪問(wèn)控制機(jī)制時(shí)應(yīng)該考慮的關(guān)鍵層面把敢,以便預(yù)防 IDOR 漏洞寄摆。
操作步驟
使用非直接引用優(yōu)于直接引用。例如修赞,不要通過(guò)參數(shù)中的名稱來(lái)引用頁(yè)面(
URL?page="restricted_page"
)婶恼,而是要?jiǎng)?chuàng)建索引,并在內(nèi)部處理它(URL?page=2
)柏副。將非直接引用映射到用戶(會(huì)話)層面勾邦,于是用戶僅僅能夠訪問(wèn)授權(quán)的對(duì)象,即使它們修改了下標(biāo)割择。
在傳遞相應(yīng)對(duì)象之前校驗(yàn)引用眷篇,如果請(qǐng)求的用戶沒(méi)有權(quán)限來(lái)訪問(wèn),展示通用錯(cuò)誤頁(yè)面锨推。
輸入校驗(yàn)也是很重要的铅歼,尤其是目錄遍歷和文件包含的情況下。
永遠(yuǎn)不要采取“隱藏式安全”的策略换可。如果有些文件包含受限的信息椎椰,即使它沒(méi)有引用,有些人也會(huì)把它翻出來(lái)沾鳄。
工作原理
不安全對(duì)象的直接引用在 Web 應(yīng)用中的表現(xiàn)形式有所不同慨飘,從目錄遍歷到敏感的 PDF 文檔的引用。但是它們的大多數(shù)都依賴于一個(gè)假設(shè)译荞,即用戶永遠(yuǎn)不會(huì)找到方法來(lái)訪問(wèn)不能顯式訪問(wèn)的東西瓤的。
為了防止這種漏洞,需要在設(shè)計(jì)和開(kāi)發(fā)期間執(zhí)行一些積極操作吞歼。設(shè)計(jì)可靠授權(quán)機(jī)制圈膏,來(lái)驗(yàn)證嘗試訪問(wèn)一些信息的用戶的關(guān)鍵是,是否用戶真正允許訪問(wèn)它篙骡。
將引用對(duì)象映射為下標(biāo)來(lái)避免對(duì)象名稱直接用于參數(shù)值(就像 LFI 中的那樣)是第一步稽坤。攻擊者也可以修改下標(biāo),這很正常糯俗,就像對(duì)對(duì)象名稱所做的那樣尿褪。但是數(shù)據(jù)庫(kù)中存在下標(biāo)-對(duì)象的表的話,添加字段來(lái)規(guī)定訪問(wèn)所需的權(quán)限級(jí)別得湘,比起沒(méi)有任何表并且直接通過(guò)名稱來(lái)訪問(wèn)資源杖玲,要容易得多。
之前說(shuō)過(guò)淘正,下標(biāo)的表可能包含訪問(wèn)對(duì)象所需的權(quán)限級(jí)別摆马,更加嚴(yán)格的話還有擁有者的 ID。所以鸿吆,它只能夠在請(qǐng)求用戶是擁有者的情況下訪問(wèn)今膊。
最后,輸入校驗(yàn)必須存在于 Web 應(yīng)用安全的每個(gè)層面伞剑。
10.5 基本的安全配置指南
系統(tǒng)的默認(rèn)配置斑唬,包括操作系統(tǒng)和Web 服務(wù)器,多數(shù)用于演示和強(qiáng)調(diào)他們的基本或多數(shù)有關(guān)特性黎泣,并不能保護(hù)它們不被攻擊恕刘。
一些常見(jiàn)的可能使系統(tǒng)淪陷的默認(rèn)配置,是數(shù)據(jù)庫(kù)抒倚、Web 服務(wù)器或CMS 安裝時(shí)創(chuàng)建的默認(rèn)管理員賬戶褐着,以及默認(rèn)管理員頁(yè)面、默認(rèn)椡信唬回溯錯(cuò)誤信息含蓉,以及其它频敛。
這個(gè)秘籍中,我們會(huì)涉及 OWASP Top 10 中第五大關(guān)鍵漏洞馅扣,錯(cuò)誤的安全配置斟赚。
操作步驟
- 可能的話,刪除所有管理員應(yīng)用差油,例如 Joomla 的 admin拗军,WordPress 的 admin,PhpMyAdmin蓄喇,或者 Tomcat Manager发侵。如果不能這樣,使它們只能從本地網(wǎng)絡(luò)訪問(wèn)妆偏,例如刃鳄,在 Apache 服務(wù)器中禁止來(lái)自外部網(wǎng)絡(luò)的 PhpMyAdmin 訪問(wèn),修改
httd.conf
文件(或者相應(yīng)的站點(diǎn)配置文件)钱骂。
1 <Directory /var/www/phpmyadmin>
2
3 Order Deny,Allow
4 Deny from all
5 Allow from 127.0.0.1 ::1
6 Allow from localhost
7 Allow from 192.168
8 Satisfy Any
9
10 </Directory>
這會(huì)首先禁止所有地址到phpmyadmin
目錄的訪問(wèn)铲汪,之后它允許任何來(lái)自 locaohost 和以192.168
開(kāi)頭的地址的請(qǐng)求,這是本地網(wǎng)絡(luò)的地址罐柳。
- 修改所有 CMS掌腰、應(yīng)用、數(shù)據(jù)庫(kù)张吉、服務(wù)器和框架的所有管理員密碼齿梁,使其強(qiáng)度足夠。一些應(yīng)用的例子是:
- Cpanel
- Joomla
- WordPress
- PhpMyAdmin
- Tomcat manager
禁用所有不必要或未使用的服務(wù)器和應(yīng)用特性肮蛹。從日成自瘢或每周來(lái)看,新的漏洞都出現(xiàn)在 CMS 的可選模塊和插件中伦忠。如果你的應(yīng)用不需要它們省核,就不要激活它們。
始終執(zhí)行最新的安全補(bǔ)丁和更新昆码。在生成環(huán)境气忠,建立測(cè)試環(huán)境來(lái)預(yù)防使站點(diǎn)不工作的缺陷十分重要,因?yàn)樾掳姹敬嬖谝恍┘嫒菪约捌渌鼏?wèn)題赋咽。
建立不會(huì)泄露跟蹤信息旧噪、軟件版本、程序組件名稱脓匿,或任何其它調(diào)試信息的自定義的錯(cuò)誤頁(yè)面淘钟。如果開(kāi)發(fā)者需要跟蹤錯(cuò)誤記錄或者一些一些標(biāo)識(shí)符對(duì)于技術(shù)支持非常必要,創(chuàng)建帶有簡(jiǎn)單 ID 和錯(cuò)誤描述的索引陪毡,并只展示 ID 給用戶米母。所以當(dāng)錯(cuò)誤報(bào)告給相關(guān)人士的時(shí)候勾扭,它們會(huì)檢查下標(biāo)并且知道發(fā)生了什么錯(cuò)誤。
采取“最小權(quán)限原則”铁瞒。每個(gè)用戶在每個(gè)層面(操作系統(tǒng)妙色、數(shù)據(jù)庫(kù)、或應(yīng)用)上都應(yīng)該只能夠嚴(yán)格訪問(wèn)正確操作所需的信息精拟。
使用上一個(gè)要點(diǎn)來(lái)考慮賬戶,構(gòu)建安全配置的原則虱歪,并且將其應(yīng)用到每個(gè)新的實(shí)現(xiàn)蜂绎、更新或發(fā)布以及當(dāng)前系統(tǒng)中。
強(qiáng)制定期的安全測(cè)試或?qū)徲?jì)笋鄙,來(lái)幫助檢測(cè)錯(cuò)誤配置或遺漏的補(bǔ)丁师枣。
工作原理
談?wù)摪踩团渲脝?wèn)題時(shí),“細(xì)節(jié)決定成敗”十分恰當(dāng)萧落。web 服務(wù)器践美、數(shù)據(jù)庫(kù)服務(wù)器、CMS找岖、或者應(yīng)用配置應(yīng)該在完全可用和實(shí)用陨倡、以及保護(hù)用戶和擁有者之間取得平衡。
Web 應(yīng)用的一個(gè)常見(jiàn)錯(cuò)誤配置就是一些 Web 管理站點(diǎn)對(duì)整個(gè)互聯(lián)網(wǎng)都可見(jiàn)许布。這看起來(lái)并不是個(gè)大問(wèn)題兴革,但是我們應(yīng)該知道,管理員登錄頁(yè)面更容易吸引攻擊者蜜唾,因?yàn)樗梢杂糜讷@得高級(jí)權(quán)限等級(jí)杂曲,并且任何 CMS、數(shù)據(jù)或者站點(diǎn)管理工具都存在已知的常用默認(rèn)密碼列表袁余。所以擎勘,我們強(qiáng)烈推薦不要把這些管理站點(diǎn)暴露給外部,并且盡可能移除它們颖榜。
此外棚饵,強(qiáng)密碼的使用,以及修改默認(rèn)密碼(即使它們是強(qiáng)密碼)掩完,在發(fā)布應(yīng)用到公司內(nèi)部網(wǎng)絡(luò)蟹地,以及互聯(lián)網(wǎng)的時(shí)候需要強(qiáng)制執(zhí)行。當(dāng)今藤为,當(dāng)我們將服務(wù)器開(kāi)放給外部的時(shí)候怪与,它收到的第一個(gè)流量就是端口掃描,登錄頁(yè)面請(qǐng)求缅疟,以及登錄嘗試分别,甚至在第一個(gè)用戶知道該應(yīng)用之前遍愿。
自定義錯(cuò)誤頁(yè)面的使用有助于安全準(zhǔn)備,因?yàn)?Web 服務(wù)器和應(yīng)用中的默認(rèn)的錯(cuò)誤信息展示太多的信息(從攻擊者角度)耘斩,它們關(guān)于錯(cuò)誤沼填、所使用的編程語(yǔ)言、椑ㄊ冢回溯坞笙、所使用的數(shù)據(jù)庫(kù)、操作系統(tǒng)以及其它荚虚。這些信息不應(yīng)該暴露薛夜,因?yàn)樗鼤?huì)幫助我們理解應(yīng)用如何構(gòu)建,并且提供所使用軟件的版本和名稱版述。攻擊者通過(guò)這些信息就可以搜索已知漏洞梯澜,并構(gòu)造更加有效的攻擊過(guò)程。
一旦我們的服務(wù)器上的部署應(yīng)用和所有服務(wù)都正確配置渴析,我們就可以制訂安全原則并且將其應(yīng)用于所有要配置的新服務(wù)器或者已更新的服務(wù)器晚伙,或者當(dāng)前帶有合理規(guī)劃的生產(chǎn)服務(wù)器。
這個(gè)配置原則需要持續(xù)測(cè)試俭茧,以便改進(jìn)它以及持續(xù)保護(hù)新發(fā)現(xiàn)的漏洞咆疗。
10.6 保護(hù)敏感數(shù)據(jù)
當(dāng)應(yīng)用儲(chǔ)存或使用敏感信息(信用卡號(hào)碼、社會(huì)安全號(hào)碼母债、健康記錄民傻,以及其它)時(shí),必須采取特殊的手段來(lái)保護(hù)它們场斑,因?yàn)樗赡転樨?fù)責(zé)保護(hù)它們的組織帶來(lái)嚴(yán)重的信用漓踢、經(jīng)濟(jì)或者法律損失,以及被攻破漏隐。
OWASP Top 10 的第六名是敏感數(shù)據(jù)泄露喧半,它發(fā)生在應(yīng)該保護(hù)的數(shù)據(jù)以純文本泄露,或者帶有弱安全措施的時(shí)候青责。
這個(gè)秘籍中挺据,我們會(huì)涉及一些處理、傳遞和儲(chǔ)存這種數(shù)據(jù)類型的最佳實(shí)踐脖隶。
操作步驟
如果你使用的敏感數(shù)據(jù)可以在使用之后刪除扁耐,那么刪除它。最好每次使用信用卡的時(shí)候詢問(wèn)用戶产阱,避免被盜取婉称。
在處理支付的時(shí)候,始終使用支付網(wǎng)關(guān),而不是在你的服務(wù)器中儲(chǔ)存數(shù)據(jù)王暗。查看:
http://ecommerce-platforms.com/ ecommerce-selling-advice/choose-payment-gateway-ecommerce-store
悔据。如果我們需要儲(chǔ)存敏感數(shù)據(jù),我們要采取的第一個(gè)保護(hù)就是使用強(qiáng)密碼算法和相應(yīng)的強(qiáng)密鑰來(lái)加密俗壹。推薦 Twofish科汗、AES、RSA 和三重 DES绷雏。
密碼儲(chǔ)存在數(shù)據(jù)庫(kù)的時(shí)候头滔,應(yīng)該以單項(xiàng)哈希函數(shù)的哈希形式存儲(chǔ),例如涎显,bcypt坤检、scrypt 或 SHA-2。
確保所有敏感文檔只能被授權(quán)用戶訪問(wèn)棺禾。不要在 Web 服務(wù)器的文檔根目錄儲(chǔ)存它們缀蹄,而是在外部目錄儲(chǔ)存峭跳,并通過(guò)程序來(lái)訪問(wèn)膘婶。如果出于某種原因必須在服務(wù)器的文檔根目錄儲(chǔ)存敏感文件,使用
.htaccess
文件來(lái)防止直接訪問(wèn):
1 Order deny,allow
2 Deny from all
- 禁用包含敏感數(shù)據(jù)的頁(yè)面緩存蛀醉。例如悬襟,在 Apache 中我們可以禁用 PDF 和 PNG 的緩存,通過(guò)
httpd.conf
中的下列設(shè)置:
1 <FilesMatch "\.(pdf|png)>
2 FileETag None
2 Header unset ETag
4 Header set Cache-Control "max-age=0, no-cache, no-store, mustrevalidate"
5 Header set Pragma "no-cache"
6 Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT"
7 </FilesMatch>
- 如果你允許文件上傳拯刁,始終使用安全的通信頻道來(lái)傳輸敏感數(shù)據(jù)脊岳,也就是帶有 TLS 的 HTTPS,或者 FTPS(SSH 上的 FTP)垛玻。
工作原理
對(duì)于保護(hù)敏感數(shù)據(jù)割捅,我們需要最小化數(shù)據(jù)泄露或交易的風(fēng)險(xiǎn)。這就是正確加密儲(chǔ)存敏感數(shù)據(jù)帚桩,以及保護(hù)加密密鑰是所做的第一件事情的原因亿驾。如果可能不需要儲(chǔ)存這類數(shù)據(jù),這只是個(gè)理想選擇账嚎。
密碼應(yīng)該使用單向哈希算法莫瞬,在將它們儲(chǔ)存到數(shù)據(jù)之前計(jì)算哈希。所以郭蕉,即使它們被盜取疼邀,攻擊者也不能立即使用它們,并且如果密碼強(qiáng)度足夠召锈,哈希也是足夠強(qiáng)的算法旁振,它就不會(huì)在短時(shí)間內(nèi)被破解。
如果我們?cè)?Apache 服務(wù)器的文檔根目錄(/var/ www/html/
)儲(chǔ)存敏感文檔或數(shù)據(jù),我們就通過(guò) URL 將這些信息暴露用于下載规求。所以筐付,最好將它儲(chǔ)存到別的地方,并編寫特殊的服務(wù)端代碼來(lái)在必要時(shí)獲取它們阻肿,并帶有預(yù)先的授權(quán)檢查瓦戚。
此外,例如 Archive.org丛塌、WayBackMachine 或者 Google 緩存頁(yè)面较解,可能在緩存含有敏感信息的文件時(shí),以及我們沒(méi)能在應(yīng)用的上一個(gè)版本有效保護(hù)它們時(shí)產(chǎn)生安全問(wèn)題赴邻。所以印衔,不允許緩存此類文檔非常重要。
10.7 確保功能級(jí)別的訪問(wèn)控制
功能級(jí)別的訪問(wèn)控制是訪問(wèn)控制的一種姥敛,用于防止匿名者或未授權(quán)用戶的功能調(diào)用奸焙。根據(jù) OWASP,缺乏這種控制是 Web 應(yīng)用中第七大嚴(yán)重的安全問(wèn)題彤敛。
這個(gè)秘籍中与帆,我們會(huì)看到一些推薦來(lái)提升我們的應(yīng)用在功能級(jí)別上的訪問(wèn)控制。
操作步驟
確保每一步都正確檢查了工作流的權(quán)限墨榄。
禁止所有默認(rèn)訪問(wèn)玄糟,之后在顯示的授權(quán)校驗(yàn)之后允許訪問(wèn)。
用戶袄秩、角色和授權(quán)應(yīng)該在靈活的媒介中儲(chǔ)存阵翎,例如數(shù)據(jù)庫(kù)或者配置文件,不要硬編碼它們之剧。
同樣郭卫,“隱藏式安全”不是很好的策略。
工作原理
開(kāi)發(fā)者只在工作流的開(kāi)始檢查授權(quán)背稼,并假設(shè)下面的步驟都已經(jīng)對(duì)用戶授權(quán)贰军,這是常見(jiàn)的現(xiàn)象。攻擊者可能會(huì)嘗試調(diào)用某個(gè)功能雇庙,它是工作流的中間步驟谓形,并由于控制缺失而能夠訪問(wèn)它。
對(duì)于權(quán)限疆前,默認(rèn)禁止所有用戶是個(gè)最佳實(shí)踐寒跳。如果我們不知道一些用戶是否有權(quán)訪問(wèn)一些功能,那么它們就不應(yīng)該執(zhí)行竹椒。將你的權(quán)限表轉(zhuǎn)化為授權(quán)表童太。如果某些用戶在某些功能上沒(méi)有顯式的授權(quán),則禁止它們的訪問(wèn)。
在為你的應(yīng)用功能構(gòu)建或?qū)崿F(xiàn)訪問(wèn)控制機(jī)制的時(shí)候书释,將所有授權(quán)儲(chǔ)存在數(shù)據(jù)庫(kù)中翘贮,或者在配置文件中(數(shù)據(jù)庫(kù)是最好的選項(xiàng))。如果用戶角色和權(quán)限被硬編碼爆惧,它們就會(huì)難以維護(hù)狸页、修改或更新。
10.8 防止 CSRF
當(dāng) Web 應(yīng)用沒(méi)有使用會(huì)話層面或者操作層面的標(biāo)識(shí)扯再,或者標(biāo)識(shí)沒(méi)有正確實(shí)現(xiàn)的時(shí)候芍耘,它們就可能存在跨站請(qǐng)求偽造漏洞,并且攻擊者可以強(qiáng)迫授權(quán)用戶執(zhí)行非預(yù)期的操作熄阻。
CSRF 是當(dāng)今 Web 應(yīng)用的第八大嚴(yán)重漏洞斋竞,根據(jù) OWASP, 并且我們?cè)谶@個(gè)秘籍中會(huì)看到如何在應(yīng)用中防止它秃殉。
操作步驟
第一步也是最實(shí)際的 CSRF 解決方案就是實(shí)現(xiàn)唯一坝初、操作層面的標(biāo)識(shí)。所以每次用戶嘗試執(zhí)行某個(gè)操作的時(shí)候钾军,會(huì)生成新的標(biāo)識(shí)并在服務(wù)端校驗(yàn)鳄袍。
唯一標(biāo)識(shí)應(yīng)該不能被輕易由攻擊者猜測(cè),所以它們不能將其包含在 CSRF 頁(yè)面中巧颈。隨機(jī)生成是個(gè)好的選擇畦木。
在每個(gè)可能為 CSRF 目標(biāo)的表單中包含要發(fā)送的標(biāo)識(shí)袖扛≡曳海“添加到購(gòu)物車”請(qǐng)求、密碼修改表單蛆封、郵件唇礁、聯(lián)系方式或收貨信息管理,以及銀行的轉(zhuǎn)賬頁(yè)面都是很好的例子惨篱。
標(biāo)識(shí)應(yīng)該在每次請(qǐng)求中發(fā)送給服務(wù)器盏筐。這可以在 URL 中實(shí)現(xiàn),或者任何其它變量或者隱藏字段砸讳,都是推薦的琢融。
驗(yàn)證碼的使用也可以防止 CSRF。
同樣簿寂,在一些關(guān)鍵操作中詢問(wèn)重新授權(quán)也是個(gè)最佳實(shí)踐漾抬,例如,銀行應(yīng)用中的轉(zhuǎn)賬操作常遂。
工作原理
防止 CSRF 完全是確保驗(yàn)證過(guò)的用戶是請(qǐng)求操作的人纳令。由于瀏覽器和 Web 應(yīng)用的工作方式,最佳實(shí)踐是使用標(biāo)識(shí)來(lái)驗(yàn)證操作,或者可能的情況下使用驗(yàn)證碼來(lái)控制平绩。
由于攻擊者打算嘗試破解標(biāo)識(shí)的生成圈匆,或者驗(yàn)證系統(tǒng),以一種攻擊者不能猜測(cè)的方式捏雌,安全地生成它們非常重要跃赚。而且要使它們對(duì)每個(gè)用戶和每個(gè)操作都唯一,因?yàn)閺?fù)用它們會(huì)偏離它們的目的性湿。
驗(yàn)證碼控制和重新授權(quán)有時(shí)候會(huì)非常麻煩来累,使用戶反感。但是如果操作的重要性值得這么做窘奏,用戶可能愿意接受它們來(lái)?yè)Q取額外的安全級(jí)別嘹锁。
另見(jiàn)
有一些編程庫(kù)有助于實(shí)現(xiàn) CSRF 防護(hù),節(jié)省開(kāi)發(fā)者的大量工作着裹。例子之一就是 OWASP 的 CSRF Guard:https://www.owasp.org/index.php/CSRFGuard
领猾。
10.9 在哪里尋找三方組件的已知漏洞
現(xiàn)在的 Wbe 應(yīng)用不再是單個(gè)開(kāi)發(fā)者,也不是單個(gè)開(kāi)發(fā)團(tuán)隊(duì)的作品骇扇。開(kāi)發(fā)功能性摔竿、用戶友好、外觀吸引人的 Web 應(yīng)用涉及到三方組件的使用少孝,例如編程庫(kù)继低,外部服務(wù)的 API(Fackbook、Google稍走、Twitter)袁翁,開(kāi)發(fā)框架,以及許多其它的組件婿脸,其中編程粱胜、測(cè)試和打補(bǔ)丁的工作量很少,甚至沒(méi)有狐树。
有時(shí)候這些三方組件被發(fā)現(xiàn)存在漏洞焙压,并且它們將這些漏洞轉(zhuǎn)移到了我們的應(yīng)用中。許多帶有漏洞組件的應(yīng)用很長(zhǎng)時(shí)間都沒(méi)有打補(bǔ)丁抑钟,使整個(gè)組織的安全體系中出現(xiàn)缺陷涯曲。這就是 OWASP 將使用帶有已知漏洞的三方組件劃分為 Web 應(yīng)用安全的第九大威脅的原因。
這個(gè)秘籍中在塔,我們會(huì)了解幻件,如果一些我們所使用的組件擁有已知漏洞,應(yīng)該到哪里尋找心俗,以及我們會(huì)查看一些這種漏洞組件的例子傲武。
操作步驟
第一個(gè)建議是蓉驹,優(yōu)先選擇受支持和廣泛使用的知名軟件。
為你的應(yīng)用所使用的三方組件保持安全更新和補(bǔ)丁的更新揪利。
用于搜索一些特定組件的漏洞的好地方就是廠商的網(wǎng)站:它們通常擁有“發(fā)布說(shuō)明”部分态兴,其中它們會(huì)公布它們糾正了哪個(gè) bug 或漏洞。這里我們可以寸照我們所使用的(或更新的)版本疟位,并且插件是否有有已知的問(wèn)題沒(méi)有打補(bǔ)丁瞻润。
同樣,廠商通常擁有安全建議站點(diǎn)甜刻,例如 Microsoft:
https://technet.microsoft.com/library/security/
绍撞,Joomla:https:// developer.joomla.org/security-centre.html
,和Oracle:http://www. oracle.com/technetwork/topics/security/alerts-086861.html
得院。我們可以使用它們來(lái)保持我們用于應(yīng)用的軟件的更新傻铣。也有一些廠商無(wú)關(guān)的站點(diǎn),它們致力于通知我們漏洞和安全問(wèn)題祥绞。有個(gè)非常好的網(wǎng)站非洲,集中了多個(gè)來(lái)源的信息,是 CVE Details(
http://www.cvedetails.com/
)蜕径。這里我們可以搜索多數(shù)廠商或產(chǎn)品两踏,或者列出所有已知漏洞(至少是擁有 CVE 號(hào)碼的漏洞),并且按照年份兜喻、版本和 CVSS 分?jǐn)?shù)排列梦染。同時(shí),黑客發(fā)布利用和發(fā)現(xiàn)的站點(diǎn)也是個(gè)獲得漏洞和我們所使用的軟件的信息的好地方朴皆。最流行的是 Exploit DB(
https://www.exploit-db.com/
)帕识。 Full disclosure 郵件列表(http://seclists.org/fulldisclosure/
),以及 Packet Storm 的文件部分(https://packetstormsecurity.com/files/
)车荔。一旦我們發(fā)現(xiàn)了我們軟件組件中的漏洞渡冻,我們必須評(píng)估它是否對(duì)我們的應(yīng)用必要戚扳,或者需要移除忧便。如果不能這樣,我們需要盡快打補(bǔ)丁帽借。如果沒(méi)有可用的補(bǔ)丁或變通方案珠增,并且漏洞是高危的,我們必須開(kāi)始尋找組件的替代砍艾。
工作原理
考慮在我們的應(yīng)用中使用三方軟件組件之前蒂教,我們需要查看它的安全信息,并了解脆荷,我們所使用的組件是否有更穩(wěn)定更安全的版本或替代凝垛。
一旦我們選擇了某個(gè)懊悯,并且將其包含到我們的應(yīng)用中,我們需要使其保持更新梦皮。有時(shí)它可能涉及到版本改動(dòng)以及沒(méi)有后向兼容炭分,但是這是我們想要維持安全的代價(jià)。如果我們不能更新或?yàn)楦呶B┒创蜓a(bǔ)丁剑肯,我們還可以使用 WAF(Web 應(yīng)用防火墻)和IPS(入侵檢測(cè)系統(tǒng))來(lái)防止攻擊捧毛。
除了在執(zhí)行滲透測(cè)試的時(shí)候比較實(shí)用,下載和漏洞發(fā)布站點(diǎn)可以被系統(tǒng)管理員利用让网,用于了解可能出現(xiàn)什么攻擊呀忧,它們的原理,以及如何保護(hù)應(yīng)用避免它們溃睹。
10.10 重定向驗(yàn)證
根據(jù) OWASP而账,未驗(yàn)證的重定向和轉(zhuǎn)發(fā)是 Web 應(yīng)用的第十大嚴(yán)重安全問(wèn)題。它發(fā)生在應(yīng)用接受 URL 或內(nèi)部頁(yè)面作為參數(shù)來(lái)執(zhí)行重定向或轉(zhuǎn)發(fā)操作的時(shí)候因篇。如果參數(shù)沒(méi)有正確驗(yàn)證福扬,攻擊者就能夠?yàn)E用它來(lái)使其重定向到惡意網(wǎng)站。
這個(gè)秘籍中惜犀,我們會(huì)了解如何驗(yàn)證我們接受的用于重定向或轉(zhuǎn)發(fā)的參數(shù)铛碑,我們需要在開(kāi)發(fā)應(yīng)用的時(shí)候?qū)崿F(xiàn)它。
操作步驟
不希望存在漏洞嗎虽界?那就不要使用它汽烦。無(wú)論怎樣,都不要使用重定向和轉(zhuǎn)發(fā)莉御。
如果需要使用重定向撇吞,嘗試不要使用用戶提供的參數(shù)(請(qǐng)求變量)來(lái)計(jì)算出目標(biāo)。
如果需要使用參數(shù)礁叔,實(shí)現(xiàn)一個(gè)表牍颈,將其作為重定向的目錄,使用 ID 代替 URL 作為用戶應(yīng)該提供的參數(shù)琅关。
始終驗(yàn)證重定向和轉(zhuǎn)發(fā)操作涉及到的輸入煮岁。使用正則表達(dá)式或者白名單來(lái)檢查提供的值是否有效。
工作原理
重定向和轉(zhuǎn)發(fā)是釣魚(yú)者和其它社會(huì)工程師最喜歡用的工具涣易,并且有時(shí)候我們對(duì)目標(biāo)沒(méi)有任何安全控制画机。所以,即使它不是我們的應(yīng)用新症,它的安全問(wèn)題也會(huì)影響我們的信譽(yù)步氏。這就是最好不要使用它們的原因。
如果這種重定向的目標(biāo)是已知站點(diǎn)徒爹,例如 Fackbook 或 Google荚醒,我們就可以在配置文件或數(shù)據(jù)表中建立目標(biāo)目錄芋类,并且不需要使用客戶端提供的參數(shù)來(lái)實(shí)現(xiàn)。
如果我們構(gòu)建包含所有允許的重定向和轉(zhuǎn)發(fā) URL 的數(shù)據(jù)表界阁,每個(gè)都帶有 ID梗肝,我們可以將 ID 用于參數(shù),而不是目標(biāo)本身铺董。這是一種白名單的形式巫击,可以防止無(wú)效目標(biāo)的插入。
最后同樣是校驗(yàn)精续。我們始終要校驗(yàn)每個(gè)來(lái)自客戶端的輸入坝锰,這非常重要,因?yàn)槲覀儾恢烙脩粢斎胧裁粗馗丁H绻覀冃r?yàn)了重定向目標(biāo)的正確性顷级,除了惡意轉(zhuǎn)發(fā)或重定向之外,我們還可以防止可能的 SQL 注入确垫、XSS或者目錄遍歷弓颈。所以,它們都是相關(guān)的删掀。
版權(quán)聲明:本文轉(zhuǎn)載自wizardforcel的專欄翔冀,如有侵權(quán),請(qǐng)與本人聯(lián)系披泪。
專欄鏈接:http://blog.csdn.net/wizardforcel
原文鏈接:http://blog.csdn.net/wizardforcel/article/details/52829673