我在開發中常忽視的安全問題

前言

  前不久,開發的任務告一段落。後來得知項目中bug比較多,須要去逐一檢查修復,苦於沒有專業的測試工程師,只好硬着頭皮上(以爲能學到不少東西),也學會了一些安全測試經常使用軟件基本操做,好比Burpsuite、sqlmap等。今天作一些總結吧,以此提醒往後的開發過程當中不只要考慮代碼的質量規範等問題,還要注意儘可能減小安全問題的出現,以往只是埋頭開發,並不太關注安全問題。因此此次對我來講收穫不小!html

 


 

1、SQL注入

  Sql注入(SQL injection)是指攻擊者在服務器端構造數據庫執行代碼能夠在服務器中數據庫獲得執行。因爲攻擊代碼在數據庫中執行,根據鏈接用戶的權限,能夠讀、修改數據庫資料甚至執行數據庫外部命令,典型的攻擊方法爲竊取數據庫資料、控制操做系統等。前端

  使用sqlmap可對url進行SQL注入掃描,進而能攻破DB,獲取表信息等,是十分須要咱們開發者關注的問題,可是已經有不少手段能防止SQL注入,最簡單的就是使用Mybatis持久框架,同時摒棄聲明式註解SQL拼接:好比@Select等註解中的SQL語句可能須要拼接,推薦使用XML編寫SQL,儘可能使用#{}參數傳入,而不是${}傳入nginx

解決辦法:

  一、增長全局防注入功能,從客戶端獲取到的參數都必須經過安全校驗,防範如下常見攻擊字符:web

 

  '|"|>|..|and|exec|insert|select|delete|update|count|*|%|chr|mid|master|truncate|char|declare|script|frame|;|or|-|+|,|)|etc|style|expressionsql

 

  注:對獲取的參數進行安全檢測以前應首先統一字符編碼和大小寫,避免攻擊者經過編碼和大小寫混用繞過安全檢查。數據庫

  二、摒棄SQL動態拼接的查詢方式,使用參數化查詢express

  三、採用Mybatis等持久化框架官方推薦的SQL方式進行SQL編寫查詢後端

 

2、XSS漏洞

  與SQL注入相似,SQL注入是注入可執行的SQL代碼到數據庫服務端,而XSS簡單來講就是注入可執行的具備危害的腳本代碼,具體來講:跨站腳本(Cross-site Scripting簡稱XSS)是指攻擊者輸入攻擊代碼到服務器端,代碼在其它用戶的瀏覽器中獲得執行。因爲攻擊代碼在受害者的瀏覽器中執行,能夠讀、修改和傳輸任何瀏覽器能夠讀取的資料,典型的攻擊方法爲竊取Cookie、網頁重定向等。跨域

  每每在頁面的一些輸入框:瀏覽器

  

  或者Url中增長後綴或者改寫參數爲xss腳本代碼,如:xxx/name=Lijian&id=123"()%26%25<acx><ScRiPt%20>alert('xss')</ScRiPt>

  

 

  xxx/serviceid=1%22%3e%3cscript%3ealert(1)%3c%2fscript%3e

  

  採起措施:

  一、增長全局防禦功能,從客戶端獲取到的參數都必須經過安全校驗,防範常見攻擊字符:注:對獲取的參數進行安全檢測以前應首先統一字符編碼和大小寫,避免攻擊者經過編碼和大小寫混用繞過安全檢查。

  二、將獲取到的數據進行HTML轉碼再存入數據庫或輸出。

  三、經過提升Seesion、Cookie等安全(設置HttpOnly,Secure等屬性)

3、傳輸安全

一、關於Cookie安全:

  1) 加密會話(SSL)缺乏HttpOnly屬性

  有效防止客戶端腳本,好比JS腳本獲取Cookie信息而且發送到指定站點提供黑客使用。準確來講是防止非HTTP協議程序接口獲取Cookie(Java後端能夠獲取Cookies,前端經過Ajax獲取)

  Java語言設置httpOnly

response.setHeader("Set-Cookie", "cookiename=value;Path=/;Domain=domainvalue;Max-Age=seconds;HTTPOnly");

  2) 加密會話(SSL)缺乏Secure屬性

  若是設置了Secure=true,那麼這個cookie只能依靠https協議發送,不能使用http協議。即此時的Cookie是在https時被建立的,若是改成http頁面則沒法使用Cookie,一般結合httpOnly一塊兒配置使用提升Cookie安全

  3) 防Cookie僞造

  傳統的Cookie(name, value)形式,網上流傳的是將value值加上保存時間savaTime、自定義密鑰、簽名等方式

  4) 儘可能不要存放敏感信息

  不要在Cookie中放userInf等信息,好比手機號碼,郵箱等,即便放也要加密!

二、關於密碼加密:

  除了規定高強度的複雜性外,還不能只是簡單的MD5加密,網上有不少的MD5解密網站可進行破解

4、敏感信息傳輸

一、Html或者JS代碼不要存在敏感重要的信息

  衆所周知,前端代碼不存在加密,大部分都是可見的,因此在前端開發過程當中儘可能不要留一些隱私敏感信息,好比測試時候用來測試預留的銀行卡號等信息應該刪除

  至少在前端展現的時候用「●●●●」或者「****」代替,而不是直接顯示在前端!

  如敏感信息App Secret Key

  

  前端中:

  

  而不是:

  

二、除了密碼不要明文傳輸,用戶名視狀況而進行加密

  固然像一些手機號碼也須要加解密,好比替換中間的幾位數,對中間幾位數進行加密隱藏等!

三、敏感信息儘可能不要放在session中,即便放也要加密

  對Session的key值儘可能不要使用簡單的userId等,能夠再加UUID,或者SessionId

5、暴力破解

一、用戶名的枚舉

常見登陸頁面,當輸入用戶名以後(還未輸入密碼進行登陸)可能會返回「用戶名不存在」的提示,這樣的提示可能會讓黑客進行大量的用戶枚舉破解用戶名。咱們應該統一返回「用戶名或密碼錯誤」的提示,混淆防止黑客對用戶名進行暴力破解。

二、關鍵信息輸入未設置錯誤次數可能會被暴力破解

如常見的密碼輸入,用戶輸入的次數超過必定數量後對用戶進行暫時鎖定或者強制修改密碼等;手機驗證碼輸入次數達到上限後,一樣進行鎖定(時間鎖定/操做鎖定)

三、篡改返回數據包,可繞過驗證碼

固然登陸頁面還會密碼還有驗證碼等的校驗,好比註冊/登陸頁面中每每最後有個輸入(手機)驗證碼的文本框,

   

 

  像我這樣的新手每次都會行雲流水,忘情地寫代碼,自我感受棒棒噠:嗯…..用戶輸入驗證碼以後咱們後端要驗證驗證碼是否正確,我要開發一個checkVeriCode驗證驗證碼是否正確的接口,emmmm……..正確就返回true,錯誤就返回false。而後返回true以後,就能夠繼續調咱們的/login登陸接口,或者註冊/register接口,So easy!超簡單(無比膨脹)。

  面對本身的ignorance,我只想說:千萬不要單獨開發驗證驗證碼是否正確的接口,進行調用!千萬不要單獨開發驗證驗證碼是否正確的接口,進行調用!千萬不要單獨開發驗證驗證碼是否正確的接口,進行調用!最好就使用一個接口(login接口或者register接口中)將驗證驗證碼環節放到其中,點擊註冊/登陸按鈕以後調用登陸/註冊接口,先進行驗證碼的校驗,正確則直接進入登陸/註冊保存,錯誤則提示驗證碼失敗。簡單來講咱們打開F12開發者模式,只能看到一個接口,而不會出現checkVeriCode接口與/login(/register)兩個接口,前一個接口影響後一個接口。

  總結起來就是咱們在開發埋頭苦幹忘我地編寫代碼的時候,量減小「多接口強耦合」開發,即後一個接口會受前一個接口返回包影響(這種影響每每是比較重要的),而前一個接口返回包每每很容易被篡改(你說還有比true/fasle更容易被篡改的嘛?)

  Request:輸入錯誤的驗證碼----->調用checkVeriCode--------請求我不攔截你放你走

  Response:checkVeriCode接口返回false----->站住你別走,我要攔截你,把你打(改)成true---->好了,你能夠走了--->驗證碼輸入正確---->成功破解登陸/註冊

  咱們使用Burpsuite中咱們截取校驗驗證碼接口,輸入錯誤的驗證碼123456

  

  返回false數據包,沒有任何問題。這是正確的

  

  下面咱們篡改false爲true以後返回到客戶端,便可繞過驗證碼環節

  

四、郵箱/短信轟炸

  這種郵件/短信轟炸是比較好理解的,黑客獲取到相關的接口以後進行返回調用,進而對指定手機號碼/郵箱進行轟炸,嚴重的話郵箱服務器等困難會崩潰。

  那麼此時咱們簡單的就認爲那還不簡單,對同一個手機號碼/郵件進行次數限定不就完了?真的是這樣就能夠了嗎?當時我一開始的時候也是這麼想的!當時我想的最簡單的作法就是:在規定T時間內每次對同一個手機號碼發送驗證碼後,存入Redis中的次數(有效期T)加1,達到必定數目後,進行「操做頻繁提示」。

  但其實咱們還忽略了另一個問題,若是攻擊者使用同一IP不一樣手機號碼進行攻擊,他的目標再也不是轟炸手機,而是讓服務器崩潰,那麼咱們仍然要對同一個IP進行次數限制。須要注意的是對方可能使用的是代理IP,咱們還須要檢測真實IP,網上有不少檢測是不是代理IP,獲取真實IP的方法,簡單的判斷:HTTP頭部X-Forward-For第一個IP就是咱們的真實IP。

6、服務器泄露

一、 服務器版本泄露

  這個咱們一般負載均衡使用Nginx服務器,有時候錯誤輸入URL可能會跳轉到Nginx的錯誤頁面顯示404,此時會顯示一個Nginx的版本號,或者歡迎頁面

解決辦法:

  1)去除歡迎頁面

  找到index.html歡迎頁面,註釋html代碼便可。

[open@dcspap01 ~]$ cd /usr/local/nginx/html

 

  2)去除版本號:

  第一步:修改nginx.conf,http中增長:server_tokens off

[open@dcspap01 ~]$ cd /home/open [open@dcspap01 ~]$ vi nginx.conf

  第二步:編輯fastcgi.conf文件,找到fastcgi_param SERVER SOFTWARE 去掉後面的參數$nginx_version,即隱藏nginx版本號

[open@dcspap01 ~]$ cd /usr/local/nginx [open@dcspap01 ~]$ vi fastcgi.conf

 

  第三步:重啓nginx,須要root用戶登陸

[open@dcspap01 ~]$ cd /usr/local/nginx/ [open@dcspap01 ~]$ ./nginx -s reload

二、點擊劫持漏洞

  HTTP 響應頭信息中的X-Frame-Options,能夠指示瀏覽器是否應該加載一個 iframe 中的頁面若是服務器響應頭信息中沒有X-Frame-Options,則該網站存在點擊劫持攻擊風險。

修改web服務器配置,添加X-Frame-Options響應頭。賦值有以下三種:

  • DENY:不能被嵌入到任何iframe或者frame中。
  • SAMEORIGIN:頁面只能被本站頁面嵌入到iframe或者frame中。
  • ALLOW-FROM url:只能被嵌入到指定域名url的框架中。

解決辦法

  Java代碼:

  response.addHeader("x-frame-options","SAMEORIGIN");

  Nginx配置:(添加到 'http', 'server' 或者 'location' 的配置中:)

  add_header X-Frame-Options SAMEORIGIN

  Apache配置:

  Header always append X-Frame-Options SAMEORIGIN

三、 謹慎啓用OPTIONS

  OPTIONS方法請求web服務器告知其支持的各類功能。能夠詢問服務器一般支持哪些方法,或者對某些特殊資源支持哪些方法。若是單獨再詳細瞭解OPTIONS的話估計又得一大篇了,搜因此這麼簡單的總結下:

  OPTIONS一般存在於先後端分離的跨域請求中:瀏覽器自發起一次preflight request(預檢請求),以檢測實際請求是否安全,這也是黑客一般針對的點,那麼咱們後端須要作什麼呢,就須要作一些簡單的跨域設置,容許部分的HTTP METHOD

response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, OPTIONS");
response.setHeader("Access-Control-Allow-Headers", "x-requested-with");
response.addHeader("Access-Control-Max-Age", "1800");

  啓用OPTIONS請求後,返回Allow頭,代表後端服務器支持的HTTP方法,有些方法DELETE、HEAD等方法是不必或者不安全的,須要禁止,同時若是服務器不須要支持WebDAV,請務必禁用它,或禁止沒必要要的HTTP方法!

  

 


 

總結

  1)我不是專業的安全測試,因此提到的問題可能不是很完善,解決辦法也可能不是很好,我相信確定有不少的更好的解決辦法;

  2)在這裏我只是想提醒做爲菜鳥開發的話不只要關注代碼質量,對代碼負責。還要對安全問題負責,我認爲這纔是好的(禿頭)程序猿應該全方位考慮到的;

  3)「不光還要懂開發懂代碼,還要全局掌握一些知識」這是我對本身的要求,這些問題看似簡單但據我經從來看,不少開發者都會忽視(我爲何還要懂安全問題,我又不是測試)。

相關文章
相關標籤/搜索