不少技術研發不瞭解安全,也不重視安全,只有在本身的服務器被黑掉、被掛馬、被脫褲纔想起關注安全,可是這個時候,技術架構已經成型、代碼已經在線上穩定運行,再亡羊補牢,改代碼、改策略,每每成本巨大、確收效很低。因此,開發安全,從娃娃抓起。。。
什麼是信息安全?信息安全是一個龐大的概念,包含大量不一樣方向的分支技術,可是都涉及幾個概念:javascript
以上是信息安全的基本屬性,即CIA屬性。此外,後期還衍生出其餘的屬性,如可控性、不能否認性等,總之都是對信息安全概念的補充。
而安全人員的工做,尤爲是作企業安全建設的工做,就是圍繞保護數據安全的過程,在事前、事中、過後三個階段,技術上創建掃描、發現、監控、防護、應急、加固等一系列措施,在管理上完善流程、制度、規範,從而使以上幾個安全屬性獲得保障。
概念說了不少,落地到實際是什麼樣子呢,簡單總結了一個安全架構圖,比較全的涵蓋了企業安全建設的要點。css
以上是宏觀層面,那具體到每一個技術研發同窗的身上,最多見的就是對各類安全漏洞、安全風險的處理修復。下面介紹開發過程當中常見的安全風險點。html
sql注入危害很大,也很常見,能夠致使企業數據直接被泄漏出去。典型的sql注入漏洞是這樣產生的:前端
void doPost(HttpServletRequest request, HttpServletResponse response){ JdbcConnection conn = new JdbcConnection(); final String sql = "select * from product where pname like '%」 + request.getParameter("name") + "%'"; conn.execqueryResultSet(sql); }
在sql中直接拼接了字符串,致使用戶能夠經過插入惡意代碼來控制sql執行。好比這樣:java
select * from product where pname like ‘%name%’;
qudian’;drop database;//
就變成了web
那麼怎麼防護sql注入呢?最簡單正確的方式就是預編譯。爲何用預編譯,首先要了解sql注入的原理:sql注入產生在數據庫的編譯階段,拼接字符串時,sql和用戶可控的數據部分拼接到一塊兒,一次發送到數據庫,數據庫編譯時就會把sql指令和數據編譯到一塊兒,若是用戶可控的數據部分有非法的命令,也會被數據庫編譯執行,這樣就產生了sql注入。而預編譯的方式,sql和用戶可控的部分是分兩次發給數據庫的,第一次發sql指令,也就是上個例子的select * from product where pname like ‘%name%’;
,數據庫收到後先進行編譯,第二次再發送數據qudian’;drop database;//
,此時數據庫不會從新編譯第一次收到的指令,而是把指令和數據區分開,這樣不論用戶輸入的是什麼非法數據,數據庫都會認爲是數據部分,也就不會產生sql注入了。上面的過程經過抓包能夠看到。算法
預編譯的簡單寫法:sql
正常查詢 conn = createConnection(); String sql = 「select name,password from manager where name=? and password=?"; stat = conn.prepareStatement(sql); stat.setString(1, name); stat.setString(2, password); stat.executeQuery(sql); 模糊查詢 conn = createConnection(); String sql = "select * from table where url like ?"; stat = con.prepareStatement(sql); String data="data"; stat.setString(1, "%"+data+"%"); stat.executeQuery(sql);
不少人不重視XSS,以爲XSS沒有大危害,「只是能彈個窗有什麼用?」但實際XSS的危害甚至不弱於遠程代碼執行等。平時常見的XSS的危害場景:數據庫
XSS是怎麼插的?舉個簡單的例子。
一般正常的表單是這樣的:json
`<input class='txtValue' type='text' name='name' value=''/>` www.qufenqi.com/1.html?name=abc
可是現實老是和理想有差距。黑客一般會這樣填充表單:
www.qufenqi.com/1.html?name=abc」/><script>alert(‘hehe’)</script>//
這樣就形成了XSS,能夠彈出一個窗口。
這種現象是產生的緣由是因爲服務端對用戶的輸入沒有作任何處理,所以在瀏覽器渲染時,用戶輸入的js代碼就會執行。既然知道了緣由,就不難修復,只要讓瀏覽器渲染時js代碼不會執行就能夠了。最完美的解決XSS的方案:
因爲富文本中有須要用戶提交一些html、js、css標籤,所以不能直接處理,建議除可能必需保留的標籤外,過濾其餘危險標籤。
解決XSS一般有兩種誤區:
第一個,喜歡用過濾的方式。可是過濾不能徹底避免XSS,經過轉義等不少方式能夠繞過過濾的方法。好比這是正常的XSS語句,能夠經過過濾關鍵字來解決。
<script> … alert(1); … </script> ``` 可是我把它變換一種形式,依然可以達到效果,好比這樣:
<script> … u0061u006cu0065u0072u0074(1); … </script> `
第二個,不論XSS輸出在哪,都用一種方式轉義。有時候開發會寫一個全局的轉義方法,以後不論何時在哪出現XSS,都調用這個方法,雖然暫時可行,但時間長了容易引入dom xss,不是一個完美的方案。
首先一個圖簡單明瞭的展示了CSRF的過程
簡單的說就是在用戶的某個網站cookie有效時,誘使用戶去請求黑客構造好的惡意請求,就能在神不知鬼不覺的狀況下進行攻擊。一個發生過的經典例子,某網站後臺管理員更改密碼的功能,沒有校驗目前使用的密碼,能夠直接設置新的管理員密碼。操做請求的參數只有一個新的密碼,因此構造連接http://xxx.com/updatepass?new...,誘使管理員去請求,就能夠默默的改變管理員密碼。
下一個問題就是如何誘使受害者去主動請求惡意的連接,方式多種多樣,好比在本身的網站上插入這個連接,讓用戶訪問你的網站;在論壇裏插入外鏈圖片,圖片連接是惡意的連接,這些均可以。除此以外,CSRF結合其餘漏洞更能達到驚喜的效果,前幾年知名的新浪微博蠕蟲刷粉絲,能夠短期增加大量的粉絲,就是CSRF和XSS在一塊兒的功效。
那麼防護CSRF的方案呼之欲出,目前主流的兩種方案:1.讓黑客不能僞造惡意的請求;2.校驗來源的請求是否是用戶正常觸發的。第一點,一般使用token校驗。第一步,用戶登陸時,服務端生成token,保存在session中。第二步,token能夠放在表單中或者http請求頭中。 第三步,客戶端帶着token發請求給服務端,服務端校驗token。這樣經過客戶端和session中的token比較,就能夠得知請求是否合法。因爲token是隨機字符串,黑客沒法獲取,也就沒法構造請求了。第二點,校驗referer,這是一個比較簡單的實現方式,經過校驗referer白名單也能夠起到防護CSRF攻擊的做用。可是這裏有個坑,不少開發寫正則來取referer,有時候就會形成各類繞過的姿式,好比www.qufenqi.com.baidu.com這樣。所以在寫正則的時候必定要注意。
登陸註冊的風險點主要有四個:暴力破解、撞庫、遍歷註冊用戶、批量註冊。
首先登陸,三個必備的要素:用戶名、密碼、驗證碼。驗證碼是手機短信驗證碼或者圖形驗證碼。經過手機短信驗證碼既能夠識別用戶身份,爲風控提供基礎,又能夠防禦暴力破解、撞庫等批量的攻擊行爲。圖像驗證碼則能夠人機識別,防禦暴力破解、撞庫。引入了驗證碼機制一樣引入了額外的安全風險,好比短信驗證碼的短信炸彈風險、圖形驗證碼的可繞過、可識別等。此外,也能夠加入一些高級的安全策略,輔助分析防禦安全風險,如異地登陸提醒、記錄很是用設備登陸、校驗用戶歷史行爲。
這裏簡單說下校驗用戶歷史行爲。不少產品在設計須要校驗身份的場景時,沒有徹底的考慮各種安全風險,一個常見的例子就是經過短信驗證碼來找回密碼,產品理想中的場景是短信驗證碼只能用戶本身收到,因此能夠確認用戶身份,但實際有不少不可控的因素,好比,用戶手機丟失的狀況。所以,在註冊登陸點須要綜合考慮各類狀況。
剛纔提到圖形驗證碼,圖形驗證碼若是設計開發的不當就會形同虛設。一個完善的圖形驗證碼流程是這樣的:
1.客戶端發起一個請求。
2.服務端響應並建立一個新的SessionID同時生成一個隨機驗證碼。
3.服務端將驗證碼和SessionID一併返回給客戶端。
4.客戶端提交驗證碼連同SessionID給服務端。 5.服務端驗證驗證碼同時銷燬當前會話,返回給客戶端結果。
若是整個流程中的某個環節處理不當,則會產生各類問題:
1.驗證碼不過時,可重複使用。這是比例最大的驗證碼安全風險,產生這種現象的主要緣由是驗證碼的刷新是在前端進行,服務端的功能只有接收驗證碼判斷對錯,並無sessionid的機制,這樣只要攔截請求每次使用這個驗證碼從新發包,就能夠繞過驗證碼的策略作各類攻擊嘗試。正確的作法是每次校驗驗證碼以後,服務端要從新生成驗證碼。
2.驗證碼輸出到客戶端。這種問題也很常見,不少驗證碼的邏輯是在請求驗證碼時,服務端不僅返回驗證碼圖片,還返回圖片裏的內容,這樣經過抓取返回中的驗證碼內容字段就能夠繞過驗證碼的人機識別過程。爭取的作法是服務端返回時,不要返回驗證碼內容,直接返回一張圖片便可。
3.驗證碼前端生成,前端校驗。這裏涉及安全的一個原則:永遠不要信任用戶端的輸入。全部前端的代碼都是能夠被用戶修改的,所以若是在前端作驗證碼處理,黑客則能夠經過修改前端代碼本身生成,本身校驗,徹底繞過驗證碼的邏輯。
4.驗證碼能夠被識別。這是目前驗證碼的一個難題。如今圖像識別的技術很是成熟,前端的數字字符驗證碼,即便增長了背景、干擾、粘連等措施,也能夠被輕鬆識別。所以驗證碼技術如今逐漸發展成經過用戶行爲識別和找不一樣來作人機識別。好比滑動驗證碼、12306那類的驗證碼。
不少產品避免不了和第三方產品的互相調用,可是在調用過程當中若是不注意安全控制,很容易由於第三方系統的安全問題,致使本身的安全風險。之前遇到過一個例子,某電商網站擴展二手回收業務,和某二手回收網站合做,會將本身的一些用戶信息傳給二手回收的系統,結果由於對方的安全作的不夠完善,致使本身的大量用戶信息被泄漏。形成了很嚴重的影響。可是第三方的系統安全咱們是控制不了的,所以咱們只能互相調用的接口傳輸過程當中加入安全策略。一般有如下幾種作法:
1.IP訪問控制(白名單):這個是必需的,一般此類接口調用都不涉及不少的範圍,都是雙方之間的調用,須要作訪問控制來限制惡意來源的訪問掃描。
2.接口簽名:簽名也是如今廣泛的作法,經過簽名能夠肯定接口傳輸的信息沒有被惡意篡改。簽名的簡單邏輯是:簽名串=MD5(明文參數&密鑰),而後將簽名串做爲參數與原來的參數一塊兒發給服務端。服務端收到明文參數後,一樣進行一次MD5(明文參數&密鑰),並於收到的簽名串作比較,便可校驗是否被篡改。如今的簽名技術已經相對完善。
3.敏感數據加密:敏感數據必定不要直接明文在互聯網傳輸,要經過加密。加密算法能夠選擇對稱加密和非對很加密,加密算法能夠選用對稱加密的AES或者非對稱加密的RSA,或者兩者綜合使用。
簡單的介紹了線上常見的幾種安全風險,接下來講說幾點安全基本的原則,也是各類安全方案的思想。經過這幾個原則能夠擴展出不少成熟的安全方案。
1.不要信任用戶的輸入:從用戶端傳過來的任何數據都是不可信的不管是請求頭仍是請求體,都是能夠隨便更改的。所以,這裏邊可能包含大量的惡意代碼。用戶傳過來的數據必定要作一些關鍵的過濾、校驗。對參數的類型、長度等必定要有預期,不符合預期的要作處理。此外,關鍵的算法、邏輯操做和數據不要在js中處理。js是能夠隨意更改的。一個典型的例子,大轉盤抽獎通常是經過js實現,因而中獎的規則也在js中一塊兒實現,js判斷以後直接將中獎結果通知服務端,這樣黑客就能夠經過js隨意控制抽獎的過程和結果了。
2.合理利用加密、簽名:加密和簽名是安全策略中不可或缺的一部分。關鍵敏感的數據和接口必定要作加密和簽名,加密和簽名算法的選擇又是一個龐大的話題,之後能夠單獨細說。
3.關鍵操做的身份認證:關鍵操做不作身份認證就好像不問別人是誰就讓他進你家門。在作身份認證時注意的幾個要點:第一不要直接經過傳參數來判斷身份,好比userid,這是能夠隨意更改的;第二不要經過cookie中的某個字段判斷身份,cookie中的信息也是能夠隨意更改的。正確的作法是經過session來獲取用戶身份。
4.邏輯步驟:有時候有些邏輯步驟本能夠一個步驟完成,卻分紅兩個步驟,這種狀況就有可能繞過第一個步驟直接判斷第二個。舉個簡單的例子,登陸時候輸入用戶名、密碼、短信驗證碼,有的開發會先經過一個請求判斷短信驗證碼是否正確,以後根據結果再發送請求。這時若是直接發送第二個請求就能夠繞太短信驗證碼的校驗,產生安全風險。所以,不管須要檢驗的參數數量有多少,都須要在一個步驟中作好全部的校驗,以後再返回最終結果。
5.策略一致性:如今的產品大多有多個平臺,好比web端和app端。此時這兩個平臺的安全策略須要徹底一致,纔不會有疏漏。舉一個之前遇到的例子,XSS的處理,在web端作輸入過濾,在app端作輸出轉義,此時單獨在兩個平臺都沒法XSS,可是若是在app端輸入,在web端輸出,就剛好繞過兩個平臺的安全策略,最終成功XSS。所以,多個平臺的產品,須要多個平臺保持一致的安全策略才行。