校驗跨信任邊界傳遞的不可信數據(策略檢查數據合法性,含白名單機制等)格式化字符串時,依然要檢驗用戶輸入的合法性,避免可形成系統信息泄露或者拒絕服務javascript
禁止向Java Runtime.exec()方法傳遞不可信、未淨化的數據(當參數中包含空格,雙引號,以-或者/符號開頭表示一個參數開關時,可能會致使參數注入漏洞),建議若是能夠禁止JVM執行外部命令,未知漏洞的危害性會大大下降,能夠大大提升JVM的安全性。php
驗證路徑以前應該先將其標準化爲實際路徑(特殊的文件名,好比「..」,symbolic links、hard links、shortcuts)css
從ZipInputStream提取文件,若是不在程序預期計劃的目錄以內時,應拒絕將其提取出來,或者將其提取到一個安全的位置html
從ZipInputStream提取文件,若解壓以後的文件大小超過必定的限制時,必須拒絕將其解壓前端
在處理之前,驗證全部來自客戶端的數據,包括:全部參數、URL、HTTP頭信息(好比:cookie名字和數據值),肯定包括了來自 JavaScript、Flash 或其餘嵌入代碼的post 返回信息java
若是任何潛在的危險字符必須被做爲輸入,請確保您執行了額外的安全控制,好比:輸入轉義、輸出編碼、特定的安全 API等。部分常見的危險字符,包含但不限於: < > " ' % ( ) & + \ \' \"node
若是您使用的標準驗證規則沒法驗證下面的輸入,那麼它們須要被單獨驗證,好比驗證空字節 (%00); 驗證換行符 (%0d, %0a, \r, \n); 驗證路徑替代字符「點-點-斜槓」(../或 ..\);若是支持 UTF-8 擴展字符集編碼,驗證替代字符: %c0%ae%c0%ae/ (使用規範化驗證雙編碼或其餘類型的編碼)python
嚴格驗證來自重定向輸入的數據(一個攻擊者可能向重定向的目標直接提交惡意代碼,從而避開應用程序邏輯以及在重定向前執行的任何驗證)mysql
驗證數據類型linux
驗證數據範圍
驗證數據長度
爲每一種輸出編碼方法採用一個標準的、已經過測試的規則
經過語義輸出編碼方式,對全部從服務端返回到客戶端的數據進行編碼。好比HTML編碼、URL編碼等,編碼形式需根據具體的應用場景選擇
除非對目標編譯器是安全的,不然請對全部字符進行編碼
針對 SQL、XML 和 LDAP 查詢,語義淨化全部不可信數據的輸出
對於操做系統命令,淨化全部不可信數據輸出
禁止在異常中泄露敏感信息(敏感數據的範圍應該基於應用場景以及產品威脅分析的結果來肯定。典型的敏感數據包括口令、銀行帳號、我的信息、通信記錄、密鑰等)
禁止在異常中泄露應用服務器的指紋信息(如版本,路徑,架構)
方法發生異常時要恢復到以前的對象狀態(業務操做失敗時,進行回滾業務;或者避免去修改對象狀態,維持對象狀態一致性)
I/O操做- 臨時文件使用完畢應及時刪除
不要將Buffer對象封裝的數據暴露給不可信代碼
在多用戶系統中建立文件時指定合適的訪問許可,以防止未受權的文件訪問
當一個外部進程經過其輸出流對外輸出信息或錯誤時,必須及時清空其輸出流,以防止輸出流中的緩衝區被耗盡而致使外部進程被阻塞。
白名單控制共享目錄操做文件權限,好比讀/寫/可執行權限
不要使用危險的許可與目標組合(好比不要將AllPermission許可賦予給不信任的代碼,不要將ReflectPermission許可和suppressAccessChecks目標組合使用,不要將java.lang.RuntimePermission許可與createClassLoader目標組合)
不要禁用JVM字節碼驗證,若是使用的字節碼,如class文件被惡意篡改過,將會存在安全風險
建議監控平臺不要對互聯網開放,僅限於內網環境訪問;若是監控平臺存在遠程執行漏洞,將會給所監控的應用帶來安全風險
建議將全部安全敏感代碼(例如進行權限控制或者用戶名密碼校驗的代碼)都放在一個jar包中
生產代碼不能包含任何調試代碼或接口
除了那些特定設爲「公開」的內容之外,對全部的網頁和資源都要求進行身份驗證,並正確設計身份驗證功能
全部的身份驗證過程必須在服務器後端上執行
在任何可能的狀況下,創建並使用標準的、已經過安全測試的身份驗證服務(好比 C4A)
全部的身份驗證控制應當安全的處理未成功的身份驗證,好比給出錯誤模糊提示,隱藏敏感信息
登陸入口應具備防止暴力猜解及撞庫猜解(利用已泄漏的密碼字典進行批量登陸嘗試)的措施,超過設定失敗次數須要啓用鎖定或圖片隨機碼進行訪問限制
採用https post請求方式傳輸身份驗證的憑據信息
身份驗證的失敗提示信息採用模糊處理,好比能夠使用「用戶名或密碼錯誤」,而不要使用「用戶名錯誤」或者「密碼錯誤」明確提示。
涉及敏感信息或功能的外部系統鏈接應配置身份驗證功能,並進行有效身份驗證控制
在執行關鍵操做(如我的信息密碼修改操做)時,應對用戶身份進行再次驗證
爲高度敏感或重要的交易帳戶使用多因子身份驗證機制,如支付密碼、短信驗證碼等
一次一用
發送頻率控制(建議60s獲取一次)
驗證碼有效期(建議60s內有效,發短信時進行友好提示)
複雜度(短信驗證碼建議6位數字)
安全提示:是不是我的本身操做等風險提示信息
在前端校驗(客戶端的校驗只能做爲輔助手段,很容易被繞過),必須使用服務端代碼對輸入數據進行最終校驗
短信驗證碼須要限制頻率使用,例如:天天一個手機號碼只容許發送5次,防止被黑客惡意消耗短信
不一樣場景的短信驗證碼不可通用
單個短信驗證碼限制有效驗證次數
驗證碼須要對應手機號不可通用
限制對短信接口的調用(1.推薦添加驗證碼保證須要人類交互才能夠發送短信2.根據本身的業務特色限制每一個IP天天的最大發送量)
一次一用
驗證碼有效期(10分鐘內有效,可根據場景兼容安全和體驗靈活設置)
複雜度(4位及以上數字、字母交替),根據須要也可採用當下流行的拖拽驗證碼或計算值的驗證方式
服務器端進行認證
從用戶體驗和安全角度出發,可設計爲當用戶輸3次錯誤密碼後自動彈出驗證碼輸入框進行驗證操做
禁止使用私有或者弱加密算法(好比禁止使用DES,SHA1等,推薦使用AES: 128位,RSA: 2048位,DSA: 2048位)
採用基於哈希算法和加入鹽值(salt)方式安全存儲口令信息
數據庫鏈接配置中的用戶密碼要以加密的形式存儲(建議全部涉及密碼存儲的功能點進行加密存儲)
保證密碼傳輸過程須要加密(建議使用https)
密碼輸入框,可設計爲顯示密碼和隱藏密碼切換功能
密碼重設和更改操做,須要進行二次合法身份驗證
密碼重設時,應對註冊手機號和郵箱進行有效驗證,連接只能發送到預先註冊的郵件地址或預先綁定的手機號
臨時密碼和連接應設計一個短暫的有效期(好比5分鐘),防止暴力破解
當密碼從新設置時,應短信通知用戶是不是本人在操做,告知安全風險
密碼複雜度設置:建議8個字符以上,包含字母、數字及特殊字符等
密碼設置場景中應具備密碼複雜度檢查功能(建議在後臺驗證密碼複雜度)
密碼不能輸出到日誌和控制檯
建議設計密碼按期修改提醒機制
用戶登出後應當即清理會話及其相關登陸信息
註銷功能應當徹底終止相關的會話或鏈接
增長Cookie 安全性,添加「HttpOnly」和「secure」屬性(當「secure」屬性設置爲true時表示建立的 Cookie 會被以安全的形式向服務器傳輸,也就是隻能在HTTPS 鏈接中被瀏覽器傳遞到服務器端進行會話驗證,在 HTTP 鏈接中不會傳遞該信息,也就不會存在Cookie被竊取的問題;設置了"HttpOnly"屬性,經過程序(JS腳本、Applet等)將沒法讀取到Cookie信息,這樣也能減小XSS跨站腳本攻擊風險)
會話cookie應設計有效期,超時後當即失效
當設計容許用戶在多渠道終端同時登陸時,建議應進行經常使用設備登陸限制
爲包含已驗證的會話標識符的 cookie 設置域和路徑,爲站點設置一個恰當的限制值。默認cookie的域是當前域名,默認cookie的路徑是當前頁面的目錄路徑。若是想要跨域或者在其餘的路徑下訪問cookie就必需要從新設置這兩個屬性,domain和path。
註銷功能應當可用於全部受身份驗證保護的網頁
在平衡風險和業務功能需求的基礎上,設置一個儘可能短的會話超時時間。一般狀況下,應當不超過幾個小時。
不要在URL、錯誤信息或日誌中暴露會話標識符,會話標識符應當只出如今http頭信息中,不要將會話標識符以 GET 參數進行傳遞
按期生成一個新的會話標識符並週期性地使上一個會話標識符失效(這能夠緩解那些原標識符被得到的特定會話劫持狀況)
在身份驗證的時候,若是鏈接從 HTTP 變爲 HTTPS,則會生成一個新的會話標識符。在應用程序中,推薦持續使用 HTTPS,不該在 HTTP 和 HTTPS 之間來回轉換,有效避免切換過程會話被劫持篡改。
爲服務器端的操做執行標準的安全會話管理,爲每一個會話執行合法的身份驗證和權限控制,防止存在CSRF跨站點請求僞造漏洞
將具備特權的邏輯從其餘應用程序代碼中隔離開
限制只有受權的用戶才能訪問文件資源
限制只有受權的用戶才能訪問受保護的URL
限制只有受權的用戶才能訪問受保護的功能或服務
建議只有受權的用戶才能訪問直接對象引用
限制只有受權的用戶才能訪問受保護的應用程序數據
限制只有受權的用戶才能訪問與安全相關的配置信息
限制只有受權的外部應用程序或接口才能訪問受保護的本地程序或資源
服務器端執行的訪問控制規則和前端實施的訪問控制規則必須匹配
服務器中建立文件時需指定合理的訪問權限(讀/寫/可執行)
當權限從新設置發生變動時,應記錄好日誌,並短信通知用戶是不是本人在操做,告知可能存在的安全風險
不要在日誌中保存敏感信息,包括系統指紋信息、會話標識符、帳號密碼、證件、ID等
確保日誌記錄包含了重要的日誌事件數據
記錄全部失敗和成功的輸入驗證
記錄全部失敗和成功的身份驗證記錄
記錄全部失敗和成功的訪問和操做記錄
記錄明顯的修改事件,包括對於狀態數據的修改
記錄鏈接無效或者已過時的會話令牌嘗試
記錄全部的管理功能操做行爲,包含但不限於安全配置設置的變動
記錄全部失敗和成功的後端鏈接
記錄加密模塊的錯誤信息
禁止將日誌直接保存在可被瀏覽器訪問到的WEB目錄中
臨時產生的敏感數據(寫入內存或文件),應具備及時清除和釋放機制
不要在 HTTP GET 請求參數中包含敏感信息,如用戶名、密碼、卡號、ID等
禁止表單中的自動填充功能,由於表單中可能包含敏感信息,包括身份驗證信息
不要在客戶端上以明文形式保存密碼或其餘敏感信息
爲全部敏感信息採用SSL加密傳輸
禁止將敏感信息(包含加密祕鑰等)硬編碼在程序中
禁止明文存儲用戶的密碼、身份證號、銀行卡號、持卡人姓名等敏感信息
不要在日誌中保存敏感信息,包含但不限於系統詳細信息、會話標識符、密碼等
禁止在異常中泄露應用服務器的指紋信息,如版本,路徑,組件版本等
禁止將源碼或sql上傳到開源平臺或社區,如github、開源中國等
請求中含有敏感參數(如訂單號、ID等),應進行混淆方式處理,防止產生參數遍歷獲取信息風險
敏感信息須要展現在web頁面上時,應在後臺進行敏感字段脫敏處理
請求返回數據不該包含請求以外的業務數據,特別是敏感信息數據
服務器端要作認證,避免繞過前端控制
增長二次認證因子,如驗證碼
涉及登陸驗證token之類的,不要直接將驗證內容直接返回給用戶
認證憑證加密,推薦強算法(推薦使用AES: 128位,RSA: 2048位,DSA: 2048位)
認證憑證中的參數應進行混淆處理
在多個驗證操做中,要對各驗證機制進行排序,以防出現跳過前面驗證機制直接到最後一步認證的安全風險
手機短信碼驗證,需同時校驗手機號和短信是否對應
輸入框中,應校驗輸入數據合法性,防止產生XSS跨站腳本攻擊
密碼找回連接限制有效訪問時間和複用次數(不可重複使用)
永遠不要信任用戶的輸入,要對用戶的全部輸入進行校驗,包含SQL語句的過濾和轉義
永遠不要使用動態拼裝SQL,能夠使用參數化的SQL或者使用存儲過程進行數據查詢存取
永遠不要使用管理員權限進行數據庫鏈接,爲每一個應用使用單獨的非特權權限,且配置有限的數據庫鏈接數
不要把敏感信息明文存放,採用加密或者哈希、混淆等方式對敏感信息進行脫敏存儲
應用的異常信息應不帶有敏感信息,給出儘量少的提示;建議使用自定義的錯誤信息對原始錯誤信息進行包裝,可把異常信息存放在獨立的數據庫表中
XML注入- 不要使用字符串/StringBuffer/StringBuilder/StringFormat組裝XML
建議對XML元素屬性或者內容進行轉義
對輸入的數據進行過濾和轉義,包含但不限於< >" ' % ( ) & + \ \' \"等危險特殊字符
數據添加到html元素屬性或者內容中時,對數據進行HTML轉義
數據添加到script腳本中時,對數據進行script轉義
數據添加到style中時,對數據進行css轉義
建議在每一個關鍵表單中引入了CSRF Token驗證(會話中生成的隨機串,提交後校驗)
在關鍵表單提交時要求用戶進行二次身份驗證(錄入密碼、插KEY、輸入圖片驗證碼、短信驗證碼)
對請求referer作驗證(好比跨域、系統內部應用)
上傳操做應設計身份驗證機制,並進行合法身份校驗
只容許上傳知足業務須要的相關文檔類型
經過檢查文件頭信息,好比JPEG (jpg)文件頭信息(十六進制):FFD8FF,驗證上傳文檔是不是所期待的類型
不要把文件保存在與應用程序相同的 Web 環境中,建議將文件保存在專用的文檔服務器中,單獨給文檔服務器配置域名訪問更好
限制上傳任意可能被 Web 服務器解析的文件 ,好比jsp、php等
上傳文件以二進制形式下載,建議不提供直接訪問(防止木馬文件直接執行)
禁止授予上傳文件存儲目錄的可執行權限
禁止客戶端自定義文件上傳/下載路徑(如:使用../../../../進行跳轉)
文件上傳後重命名(需根據業務實際需求制定命名規則)
在使用隨機數函數時,推薦使用強隨機數函數(例如java.security.SecureRandom類)
精簡組件中不須要的功能、方法,以避免帶來未知的安全風險
不可將系統內部使用的鎖對象暴露給不可信代碼
建議使用SSL Socket代替Socket來進行安全數據交互
封裝本地方法調用(全部的本地方法都應該被定義爲私有的,而後僅經過一個封裝方法來調用)
使用安全管理器(好比java.security或第三方安全組件)來保護敏感操做
編寫自定義類加載器必須覆蓋getPermissions()函數時,在爲代碼源分配任意權限前,應調用超類super.getPermissions()函數,實現除了自定義策略外,系統全局的默認安全策略也被應用。
避免徹底依賴URLClassLoader和java.util.jar提供的默認自動簽名認證機制,應從加載類的代碼源(Code-Source)中獲取證書鏈,而後檢查證書是否屬於本地密鑰庫(KeyStore)中的受信任簽名者
調用方來源IP控制,好比可經過防火牆、主機host deny、Nginx deny等技術措施進行實施
調用方身份認證,好比key、secret、證書等技術措施進行實施
調用參數認證,需設計參數容錯機制,避免出現參數可遍歷敏感數據安全問題
採用數字簽名保障接口身份來源可信,數據防篡改
調用方權限控制設置
調用頻率、有效期進行控制
調用行爲實時檢測,對異常阻攔
冪等性校驗,保持數據一致性
採用應用接入安全網關,實現APPID/KEY身份認證,加密傳輸,摘要簽名安全保障
採用token驗證訪問控制,防止消費者繞過註冊中心訪問提供者;在註冊中心控制權限以決定要不要下發令牌給消費者
採用filter IP白名單訪問控制,同時也可預防生產系統和測試系統之間Dubbo混亂調用問題
在必要狀況下(如敏感信息操做),鏈接註冊中心Dubbo時要進行用戶名和密碼校驗
應啓用客戶端IP訪問控制驗證功能
應啓用客戶端身份驗證功能
敏感信息不要明文存儲於Redis
爲了提高公司各業務線產品的安全質量,下降安全風險,進一步提高公司總體安全水平,結合公司現有產品設計、開發、測試及上線流程,特制定此《XX產品安全開發流程》。
此流程適用於 XX 全部業務線產品的安全設計、開發、測試及上線。
SDL 的全稱是 Security Development Lifecycle,即:安全開發生命週期。它是由微軟最先提出的,是一種幫助解決軟件安全問題的方法。SDL 中的方法,試圖從安全漏洞產生的根源上解決問題。SDL 是一個安全保證的過程,經過對軟件工程的控制,從而保證產品的安全性。它可以幫助企業以最小的成本提升產品的安全性,對企業安全的發展來講,能夠起到事半功倍的效果。
實施 SDL 的核心目的只有一個,那就是經過在開發過程當中加入安全控制的方法,提高各業務線項目、系統的安全性。避免因項目上線後存在安全漏洞被攻擊者惡意利用而形成沒必要要的安全風險和損失。
要求:須要保證全部項目在立項時都通知到安全團隊。 通知方式:郵件+企業微信、立項會議
要求:全部需求必須經過安全評審,由安全團隊來評估需求是否存在安全風險或是否須要設計安全功能;若是安全評審未經過,不容許進入下一步研發流程
安全評審流程:
安全評審成果:安全評審報告 安全評審溝通方式:郵件+企業微信、jira安全評審提交
在設計階段,由產品和研發團隊自查,確認是否有違反《XX開發安全紅線準則》的行爲。
在編碼實現階段,研發工程師應遵循 《XX安全開發手冊》。
在開發工做完成後,應與功能測試同步進行安全測試,安全測試過程當中發現的安全漏洞經過「jira XX安全團隊漏洞提交」管理。
安全測試需求提交方式:郵件+企業微信、項目安全提測系統
在業務驗收時,應同步進行安全驗收,完成後由安全團隊發佈《XX項目安全驗收報告》,如 果在安全驗收過程當中發現存在未修復的高危及嚴重級別安全漏洞,不容許進入上線發佈環節。
php.ini基本安全配置
cgi.force_redirect在php.ini中修改,默認是開啓的,它能夠防止當PHP運行的CGI腳本未經驗證的訪問。在IIS,OmniHTTPD和Xitami上是禁用的,但在全部其餘狀況下它應該打開。
; php.ini cgi.force_redirect=1 ;
該指令僅對Apache模塊版本的PHP有效。你能夠針對每一個虛擬機或每一個目錄開啓或關閉dl()動態加載PHP模塊。關閉動態加載的主要緣由是爲了安全。經過動態加載,有可能忽略全部open_basedir限制。默認容許動態加載,除了使用安全模式。在安全模式,老是沒法使用dl()。
; php.ini enable_dl=0 ;
file_uploads默認是開啓的,容許將文件上傳到您的站點。由於來自陌生人的文件本質上是不可信甚至危險的,除非您的網站絕對須要,不然應禁用此功能。若是開啓請進行相應的限制,參考upload_max_filesize, upload_tmp_dir,和post_max_size。
; php.ini file_uploads = 0 ;
open_basedir默認是打開全部文件,它將 PHP 所能打開的文件限制在指定的目錄樹,包括文件自己。本指令不受安全模式打開或者關閉的影響。當一個腳本試圖用例如 fopen() ,include或者 gzopen() 打開一個文件時,該文件的位置將被檢查。當文件在指定的目錄樹以外時 PHP 將拒絕打開它。全部的符號鏈接都會被解析,因此不可能經過符號鏈接來避開此限制。
open_basedir應該配置一個目錄,而後能夠遞歸訪問。可是,應該避免使用. (當前目錄)做爲open_basedir值,由於它在腳本執行期間動態解析特殊值 . 指明腳本的工做目錄將被做爲基準目錄,但這有些危險,由於腳本的工做目錄能夠輕易被 chdir() 而改變。
在 httpd.conf 文件中,open_basedir 能夠像其它任何配置選項同樣用「php_admin_value open_basedir none」的方法關閉(例如某些虛擬主機中)。在 Windows 中,用分號分隔目錄。在任何其它系統中用冒號分隔目錄。做爲 Apache 模塊時,父目錄中的 open_basedir 路徑自動被繼承。
用 open_basedir 指定的限制其實是前綴,不是目錄名。也就是說「open_basedir = /dir/incl」也會容許訪問「/dir/include」和「/dir/incls」,若是它們存在的話。若是要將訪問限制在僅爲指定的目錄,用斜線結束路徑名。例如:「open_basedir = /dir/incl/」。
; php.ini open_basedir="${USER}/scripts/data" ;
默認爲 0(禁用)。當禁用cookie時,若是它開啓,PHP會自動將用戶的會話ID附加到URL。基於 URL 的會話管理比基於 cookie 的會話管理有更多安全風險,從表面上看,這彷佛是讓那些禁用cookie的用戶正常使用您的網站的好方法。實際上,它使那些用戶容易被任何人劫持他們的會話。例如用戶有可能經過 email 將一個包含有效的會話 ID 的 URL 發給他的朋友,或者用戶老是有可能在收藏夾中存有一個包含會話 ID 的 URL 來以一樣的會話 ID 去訪問站點。也能夠從瀏覽器歷史記錄和服務器日誌中檢索URL獲取會話ID。
; php.ini session.use_trans_sid = 0 ;
沒有固定生命週期或到期日期的Cookie被稱爲非持久性或「會話」cookie,這意味着它們只會持續與瀏覽器會話同樣長,而且在瀏覽器關閉時會消失。具備到期日期的Cookie叫作「持久性」Cookie,他們將被存儲/保留到這些生存日期。
管理網站上的登陸會話應用非持久性cookie。要使cookie非持久化,只需省略該 expires屬性便可。也能夠使用session.cookie_lifetime實現。
allow_url_fopen和allow_url_include默認是開啓的,他們容許代碼從URL中讀入腳本。從站點外部吸入可執行代碼的能力,加上不完美的輸入清理可能會使站點裸露給攻擊者。即便該站點的輸入過濾在今天是完美的,但不能保證之後也是。
; php.ini allow_url_fopen = 0 allow_url_include = 0
php安全編碼建議
sleep()有時用於經過限制響應率來防止拒絕服務(DoS)攻擊。可是由於它佔用了一個線程,每一個請求須要更長的時間來服務,這會使應用程序更容易受到DoS攻擊,而不是減小風險。
if (is_bad_ip($requester)) { sleep(5); // 不合規的用法 }
eval()函數是一種在運行時運行任意代碼的方法。 函數eval()語言結構是很是危險的,由於它容許執行任意 PHP 代碼。所以不鼓勵使用它。若是您仔細的確認過,除了使用此結構之外別無方法,請多加註意,不要容許傳入任何由用戶提供的、未經完整驗證過的數據。
eval($code_to_be_dynamically_executed) // 不合規的用法
由於從編譯的應用程序中提取字符串很容易,因此永遠不該對憑證進行硬編碼。對於分發的應用程序尤爲如此。 憑據應存儲在受強保護的加密配置文件或數據庫中的代碼以外。
// 合規的用法 $uname = getEncryptedUser(); $password = getEncryptedPass(); connect($uname, $password);
// 不合規的用法 $uname = "steve"; $password = "blue"; connect($uname, $password);
有時候,咱們不但願執行包括system()等在那的可以執行命令的php函數,或者可以查看phpinfo信息的
phpinfo()等函數,那麼咱們就能夠禁止它們:
disable_functions = system,passthru,exec,shell_exec,popen,phpinfo
若是你要禁止任何文件和目錄的操做,那麼能夠關閉不少文件操做
disable_functions = chdir,chroot,dir,getcwd,opendir,readdir,scandir,fopen,unlink,delete,copy,mkdir, rmdir,rename,file,file_get_contents,fputs,fwrite,chgrp,chmod,chown
以上只是部分經常使用的文件處理函數,你也能夠把上面執行命令函數和這個函數結合,應該就可以抵制大部分的phpshell了。
程序接受數據可能來源於未經驗證的用戶,網絡鏈接和其餘不受信任的來源,若是未對程序接受數據進行校驗,則可能會引起安全問題。
使用PreparedStatement預編譯SQL,解決SQL注入問題,傳遞給PreparedStatement對象的參數能夠被強制進行類型轉換,確保在插入或查詢數據時與底層的數據庫格式匹配。
String sqlString = "select * from db_user where username=? and password=?"; PreparedStatement stmt = connection.prepareStatement(sqlString); stmt.setString(1, username); stmt.setString(2, pwd); ResultSet rs = stmt.executeQuery();
經過StringBulider 或 StringBuffer 拼接XML文件時,需對輸入數據進行合法性校驗。 對數量quantity 進行合法性校驗,控制只能傳入0-9的數字:
if (!Pattern.matches("[0-9]+", quantity)) { // Format violation } String xmlString = "<item>\n<description>Widget</description>\n" + "<price>500</price>\n" + "<quantity>" + quantity + "</quantity></item>"; outStream.write(xmlString.getBytes()); outStream.flush();
對產生跨站的參數進行嚴格過濾,禁止傳入<SCRIPT>
標籤
//定義需過濾的字段串<script>
String s = "\uFE64" + "script" + "\uFE65";
// 過濾字符串標準化
s = Normalizer.normalize(s, Form.NFKC);
// 使用正則表達式匹配inputStr是否存在<script>
Pattern pattern = Pattern.compile(inputStr); Matcher matcher = pattern.matcher(s); if (matcher.find()) { // Found black listed tag throw new IllegalStateException(); } else { // ... }
例:
錯誤的寫法:
public class Cycle { private final int balance; private static final Cycle c = new Cycle(); private static final int deposit = (int) (Math.random() * 100); // Random deposit public Cycle() { balance = deposit - 10; // Subtract processing fee } public static void main(String[] args) { System.out.println("The account balance is: " + c.balance); } }
類加載時初始化指向Cycle類的靜態變量c,而類Cycle的無參構造方法又依賴靜態變量deposit,致使沒法預期的結果。 正確的寫法:
public class Cycle { private final int balance; private static final int deposit = (int) (Math.random() * 100); // Random deposit private static final Cycle c = new Cycle(); // Inserted after initialization of required fields public Cycle() { balance = deposit - 10; // Subtract processing fee } public static void main(String[] args) { System.out.println("The account balance is: " + c.balance); } }
忽略方法的放回值可能會致使沒法預料的結果。
錯誤的寫法:
public void deleteFile(){ File someFile = new File("someFileName.txt"); someFile.delete(); }
正確的寫法:
public void deleteFile(){ File someFile = new File("someFileName.txt"); if (!someFile.delete()) { // handle failure to delete the file } }
當一個變量指向一個NULL值,使用這個變量的時候又沒有檢查,這時會致使。NullPointerException。
在使用變量前必定要作是否爲NULL值的校驗。
數組沒有覆蓋的Object. equals()
方法,調用Object. equals()
方法其實是比較數組的引用,而不是他們的內容。程序必須使用兩個參數Arrays.equals()
方法來比較兩個數組的內容
public void arrayEqualsExample() { int[] arr1 = new int[20]; // initialized to 0 int[] arr2 = new int[20]; // initialized to 0 Arrays.equals(arr1, arr2); // true }
使用java.lang.Number. BigInteger類進行整數運算,防止整數溢出。
public class BigIntegerUtil { private static final BigInteger bigMaxInt = BigInteger.valueOf(Integer.MAX_VALUE); private static final BigInteger bigMinInt = BigInteger.valueOf(Integer.MIN_VALUE); public static BigInteger intRangeCheck(BigInteger val) throws ArithmeticException { if (val.compareTo(bigMaxInt) == 1 || val.compareTo(bigMinInt) == -1) { throw new ArithmeticException("Integer overflow"); } return val; } public static int addInt(int v1, int v2) throws ArithmeticException { BigInteger b1 = BigInteger.valueOf(v1); BigInteger b2 = BigInteger.valueOf(v2); BigInteger res = intRangeCheck(b1.add(b2)); return res.intValue(); } public static int subInt(int v1, int v2) throws ArithmeticException { BigInteger b1 = BigInteger.valueOf(v1); BigInteger b2 = BigInteger.valueOf(v2); BigInteger res = intRangeCheck(b1.subtract(b2)); return res.intValue(); } public static int multiplyInt(int v1, int v2) throws ArithmeticException { BigInteger b1 = BigInteger.valueOf(v1); BigInteger b2 = BigInteger.valueOf(v2); BigInteger res = intRangeCheck(b1.multiply(b2)); return res.intValue(); } public static int divideInt(int v1, int v2) throws ArithmeticException { BigInteger b1 = BigInteger.valueOf(v1); BigInteger b2 = BigInteger.valueOf(v2); BigInteger res = intRangeCheck(b1.divide(b2)); return res.intValue(); } }
要避免由於分母爲零而致使除法和取模運算出現異常。
if (num2 == 0) { // handle error } else { result1= num1 /num2; result2= num1 % num2; }
攻擊者能夠用意想不到的方式操縱public或protected的數據成員,因此須要將數據成員爲private,對外提供可控的包裝方法訪問數據成員。
包含私人的,機密或其餘敏感數據的類是不容許被複制的,解決的方法有兩種:
一、類聲明爲final
final class SensitiveClass { // ... }
二、Clone 方法拋出CloneNotSupportedException異常
class SensitiveClass { // ... public final SensitiveClass clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } }
若是由同一個類裝載器裝載,它們具備相同的徹底限定名稱,則它們是兩個相同的類。 不正確寫法:
// Determine whether object auth has required/expected class object if (auth.getClass().getName().equals( "com.application.auth.DefaultAuthenticationHandler")) { // ... } 正確寫法: // Determine whether object auth has required/expected class name if (auth.getClass() == com.application.auth.DefaultAuthenticationHandler.class) { // ... }
硬編碼的敏感信息,如密碼,服務器IP地址和加密密鑰,可能會泄露給攻擊者。
敏感信息均必須存在在配置文件或數據庫中。
驗證方法的參數,可確保操做方法的參數產生有效的結果。不驗證方法的參數可能會致使不正確的計算,運行時異常,違反類的不變量,對象的狀態不一致。 對於跨信任邊界接收參數的方法,必須進行參數合法性校驗
private Object myState = null; //對於修改myState 方法的入參,進行非空和合法性校驗 void setState(Object state) { if (state == null) { // Handle null state } if (isInvalidState(state)) { // Handle invalid state } myState = state; }
在程序代碼中使用過期的、陳舊的或低效的類或方法可能會致使錯誤的行爲。
某個方法返回一個對敏感對象的內部數組的引用,假定該方法的調用程序不改變這些對象。即便數組對象自己是不可改變的,也能夠在數組對象之外操做數組的內容,這種操做將反映在返回該數組的對象中。若是該方法返回可改變的對象,外部實體能夠改變在那個類中聲明的 public 變量,這種改變將反映在實際對象中。
不正確的寫法:
public class XXX { private String[] xxxx; public String[] getXXX() { return xxxx; } }
正確的寫法:
public class XXX { private String[] xxxx; public String[] getXXX() { String temp[] = Arrays.copyof(…); // 或其餘數組複製方法 return temp; } }
垃圾收集器只收集不可達的對象,所以,存在未使用的可到達的對象,仍然表示內存管理不善。過分的內存泄漏可能會致使內存耗盡,拒絕服務(DoS)。
對於捕獲的異常要進行相應的處理,不能忽略已捕獲的異常
不正確寫法:
class Foo implements Runnable { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { // 此處InterruptedException被忽略 } } }
正確寫法:
class Foo implements Runnable { public void run() { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); // Reset interrupted status } } }
沒有過濾敏感信息的異常堆棧每每會致使信息泄漏,
不正確的寫法:
try { FileInputStream fis = new FileInputStream(System.getenv("APPDATA") + args[0]); } catch (FileNotFoundException e) { // Log the exception throw new IOException("Unable to retrieve file", e); }
正確的寫法:
class ExceptionExample { public static void main(String[] args) { File file = null; try { file = new File(System.getenv("APPDATA") + args[0]).getCanonicalFile(); if (!file.getPath().startsWith("c:\\homepath")) { log.error("Invalid file"); return; } } catch (IOException x) { log.error("Invalid file"); return; } try { FileInputStream fis = new FileInputStream(file); } catch (FileNotFoundException x) { log.error("Invalid file"); return; } } }
不正確的寫法:
boolean isCapitalized(String s) { if (s == null) { throw new RuntimeException("Null String"); } } private void doSomething() throws Exception { //... }
正確寫法:
boolean isCapitalized(String s) { if (s == null) { throw new NullPointerException(); } } private void doSomething() throws IOException { //... }
不正確的寫法:
boolean isName(String s) { try { String names[] = s.split(" "); if (names.length != 2) { return false; } return (isCapitalized(names[0]) && isCapitalized(names[1])); } catch (NullPointerException e) { return false; } }
正確的寫法:
boolean isName(String s) /* throws NullPointerException */ { String names[] = s.split(" "); if (names.length != 2) { return false; } return (isCapitalized(names[0]) && isCapitalized(names[1])); }
對於共享變量,要確保一個線程對它的改動對其餘線程是可見的。 線程可能會看到一個陳舊的共享變量的值。爲了共享變量是最新的,能夠將變量聲明爲volatile
或同步讀取和寫入操做。 將共享變量聲明爲volatile
:
final class ControlledStop implements Runnable { private volatile boolean done = false; @Override public void run() { while (!done) { try { // ... Thread.currentThread().sleep(1000); // Do something } catch(InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } } } public void shutdown() { done = true; } }
同步讀取和寫入操做:
final class ControlledStop implements Runnable { private boolean done = false; @Override public void run() { while (!isDone()) { try { // ... Thread.currentThread().sleep(1000); // Do something } catch(InterruptedException ie) { Thread.currentThread().interrupt(); // Reset interrupted status } } } public synchronized boolean isDone() { return done; } public synchronized void shutdown() { done = true; } }
除了要確保共享變量的更新對其餘線程可見的,還須要確保對共享變量的操做是原子的,這時將共享變量聲明爲volatile每每是不夠的。須要使用同步機制或Lock 同步讀取和寫入操做:
final class Flag { private volatile boolean flag = true; public synchronized void toggle() { flag ^= true; // Same as flag = !flag; } public boolean getFlag() { return flag; } }
//使用讀取鎖確保讀取和寫入操做的原子性
final class Flag { private boolean flag = true; private final ReadWriteLock lock = new ReentrantReadWriteLock(); private final Lock readLock = lock.readLock(); private final Lock writeLock = lock.writeLock(); public void toggle() { writeLock.lock(); try { flag ^= true; // Same as flag = !flag; } finally { writeLock.unlock(); } } public boolean getFlag() { readLock.lock(); try { return flag; } finally { readLock.unlock(); } } }
public final class SocketReader implements Runnable { private final SocketChannel sc; private final Object lock = new Object(); public SocketReader(String host, int port) throws IOException { sc = SocketChannel.open(new InetSocketAddress(host, port)); } @Override public void run() { ByteBuffer buf = ByteBuffer.allocate(1024); try { synchronized (lock) { while (!Thread.interrupted()) { sc.read(buf); // ... } } } catch (IOException ie) { // Forward to handler } } public static void main(String[] args) throws IOException, InterruptedException { SocketReader reader = new SocketReader("somehost", 25); Thread thread = new Thread(reader); thread.start(); Thread.sleep(1000); thread.interrupt(); } }
有限線程池指定能夠同時執行在線程池中的線程數量的上限。程序不得使用有限線程池線程執行相互依賴的任務。可能會致使線程飢餓死鎖,全部的線程池執行的任務正在等待一個可用的線程中執行一個內部隊列阻塞
Java的文件操做方法每每有一個返回值,而不是拋出一個異常,表示失敗。所以,忽略返回值文件操做的程序,每每沒法檢測到這些操做是否失敗。Java程序必須檢查執行文件I / O方法的返回值。
不正確的寫法:
File file = new File(args[0]); file.delete(); 正確的寫法: File file = new File("file"); if (!file.delete()) { log.error("Deletion failed"); }
垃圾收集器沒法釋放非內存資源,如打開的文件描述符與數據庫的鏈接。所以,不釋放資源,可能致使資源耗盡攻擊。
try { final FileInputStream stream = new FileInputStream(fileName); try { final BufferedReader bufRead = new BufferedReader(new InputStreamReader(stream)); String line; while ((line = bufRead.readLine()) != null) { sendLine(line); } } finally { if (stream != null) { try { stream.close(); } catch (IOException e) { // forward to handler } } } } catch (IOException e) { // forward to handler }
序列化容許一個對象的狀態被保存爲一個字節序列,而後從新在稍後的時間恢復,它沒有提供任何機制來保護序列化的數據。敏感的數據不該該被序列化的例子包括加密密鑰,數字證書。 解決方法:
class SensitiveClass extends Number { // ... protected final Object writeObject(java.io.ObjectOutputStream out) throws NotSerializableException { throw new NotSerializableException(); } protected final Object readObject(java.io.ObjectInputStream in) throws NotSerializableException { throw new NotSerializableException(); } protected final Object readObjectNoData(java.io.ObjectInputStream in) throws NotSerializableException { throw new NotSerializableException(); } }
不正確的寫法:
class SensorData implements Serializable { // 1 MB of data per instance! public static SensorData readSensorData() {...} public static boolean isAvailable() {...} } class SerializeSensorData { public static void main(String[] args) throws IOException { ObjectOutputStream out = null; try { out = new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream("ser.dat"))); while (SensorData.isAvailable()) { // note that each SensorData object is 1 MB in size SensorData sd = SensorData.readSensorData(); out.writeObject(sd); } } finally { if (out != null) { out.close(); } } } }
正確寫法:
class SerializeSensorData { public static void main(String[] args) throws IOException { ObjectOutputStream out = null; try { out = new ObjectOutputStream( new BufferedOutputStream(new FileOutputStream("ser.dat"))); while (SensorData.isAvailable()) { // note that each SensorData object is 1 MB in size SensorData sd = SensorData.readSensorData(); out.writeObject(sd); out.reset(); // reset the stream } } finally { if (out != null) { out.close(); } } } }
(完成)
自己要注意的有,一些危險函數,危險模塊的調用,主要是系統調用。這個若是調用必定要對輸入輸出作好過濾,如下是代碼中各類致使進行系統調用的方式。儘可能避免。
避免各類狀況致使系統調用
謹慎使用Eval
數據序列化
對應Web編程中安全概念在python web框架中的實現。url跳轉,目錄遍歷,任意文件讀取也須要考慮在內。針對不一樣的框架也須要。
可參考phithon的博客,有較多相關資料。
安裝使用方式較爲簡單,因此不作介紹。 - AST-based static Analyzer: Bandit - Static Analyzer: PYT
待定
移動安全帶來了許多Web安全的挑戰 - 普遍的受衆,快速開發和持續的網絡鏈接 - 加上更多傳統胖客戶端應用程序(例如緩衝區管理,本地加密和惡意軟件)的常見風險。 移動環境的一個獨特功能是來自未知開發人員的已安裝應用程序的流行,這些應用程序應被視爲「不受信任的」。
以下所示,移動攻擊能夠涉及設備層,網絡層,數據中心或這些的組合。 固有平臺漏洞和社會工程繼續爲網絡盜賊提供重要機會,從而爲那些尋求保護用戶數據的人帶來重大挑戰。
在移動技術鏈中有三個點,惡意方可能利用漏洞來發起惡意攻擊:
移動設備對敏感的公司信息(SCI)構成重大風險; 主要風險包括數據丟失和安全性受損。 不管是iPhone,Android或其餘智能手機,針對設備自己的攻擊者能夠使用各類入口點:
基於瀏覽器的攻擊點能夠包括:
網絡釣魚 – 涉及經過電子郵件欺騙來假裝爲受信任實體來獲取我的信息,例如用戶名,密碼和信用卡詳細信息。 研究代表,移動用戶比網絡用戶提交我的信息的可能性是釣魚網站的三倍。 這在必定程度上多是因爲移動瀏覽器運行的縮小的環境,因爲有限的屏幕不動產,有限的警告對話,縮小的安全鎖圖標,而且放棄了許多用戶界面指示器,所述環境只顯示URL的一小部分 例如大的STOP圖標,突出顯示的地址欄和其餘可視指示器。
框架 - 構架涉及在iFrame中傳送Web / WAP站點,這能夠使「包裝器」站點執行點擊劫持攻擊。
點擊劫持 – 也稱爲UI修復,點擊劫持涉及欺騙用戶揭露機密信息或當用戶點擊看起來無害的連接或按鈕時控制他們的設備。 此攻擊採用嵌入式代碼或腳本的形式,無需用戶知識。 點擊劫持已被利用在包括Facebook的網站竊取信息或直接用戶攻擊網站。
下載驅動攻擊 – Android尤爲容易受到這種攻擊,其中網站訪問致使發生沒有用戶知識的下載,或經過誘騙用戶具備欺騙性的提示。 下載能夠是惡意應用,而且用戶而後能夠由設備自動提示以安裝應用。 當Android設備設置爲容許來自「未知來源」的應用時,容許安裝。
Man-in-the-Mobile (MitMo) – 容許惡意用戶利用放置在移動設備上的惡意軟件繞過經過短信向用戶的手機發送代碼以進行身份確認的密碼驗證系統。
電話/短信攻擊點能夠包括:
基帶攻擊 – 利用在手機的GSM / 3GPP基帶處理器中發現的漏洞的攻擊,GSM / 3GPP基帶處理器是向小區基站發送和接收無線電信號的硬件。
短信釣魚 – 相似於釣魚,但使用手機短信代替電子郵件,以提示用戶訪問非法網站並輸入敏感信息,如用戶名,密碼和信用卡號。
射頻攻擊 – 藍牙,NFC攻擊和其餘RF攻擊在各類外圍通訊信道上發現一般在附近的設備到設備通訊中使用的漏洞。
基於應用的攻擊點能夠包括:
敏感數據存儲 – 2011年viaForensics研究發現83%的流行應用程序採樣存儲數據不安全。
無加密或弱加密 – 容許傳輸未加密或弱加密數據的應用程序容易受到攻擊。
SSL驗證不正確 – 應用程序的安全套接字層(SSL)驗證過程當中的錯誤可能會容許數據安全漏洞。
配置操做 – 包括未經受權訪問管理界面,配置存儲和檢索明文配置數據。
動態運行時注入 – 容許攻擊者操縱和濫用應用程序的運行時,繞過安全鎖,繞過邏輯檢查,訪問應用程序的特權部分,甚至竊取存儲在內存中的數據。
非必要權限 – 錯誤配置的應用有時可能會經過授予非必要的權限來打開攻擊者的大門。
提高的權限 – 利用一個錯誤,設計缺陷或配置監督,以得到一般受應用程序或用戶保護的資源。
基於操做系統的攻擊點能夠包括:
沒有密碼 – 許多用戶選擇不設置密碼,或使用弱PIN,密碼或模式鎖定。
iOS 越獄 – 「越獄」是用於消除製造商和運營商提出的防止未經受權的代碼在設備上運行的安全機制的術語。 一旦這些限制被刪除,設備能夠成爲惡意軟件和其餘攻擊的網關。
Android rooting – 相似於越獄,rooting容許Android用戶更改或替換系統應用程序和設置,運行須要管理員級權限的專門應用程序。 像越獄,它可能致使敏感數據的暴露。
密碼和數據的可訪問性 – 諸如Apple的iOS設備系列的設備在其用於存儲加密密碼和數據的加密機制中已經存在漏洞。 具備這些漏洞知識的攻擊者能夠解密設備的鑰匙串,暴露用戶密碼,加密密鑰和其餘私人數據。
運營商預安裝軟件 – 預安裝在設備上的軟件可能包含安全漏洞。 最近,在Android手機上的一些預加載應用程序被發現包含安全漏洞,可用於擦除手機,竊取數據,甚至竊聽電話。
零日漏洞 – 攻擊常常發生在漏洞被首次利用的時間和軟件開發人員可以發佈解決問題的版本之間的窗口期間。
基於網絡的攻擊點能夠包括:
Wi-Fi (弱加密/無加密) – 當在Wi-Fi網絡上使用沒法實施加密的應用程序時,存在惡意攻擊者竊聽無線鏈接而竊取數據的風險。 許多應用程序使用SSL / TLS,這提供了必定程度的保護; 然而一些針對SSL / TLS的攻擊也被證實能夠將關鍵用戶數據暴露給攻擊者。
惡意接入點 – 涉及物理安裝受權各方訪問安全網絡的未受權無線接入點。
數據包嗅探 – 容許惡意入侵者捕獲和分析網絡流量,這一般包括以明文傳輸的用戶名和密碼信息。
中間人攻擊 (MITM) – 涉及竊聽現有網絡鏈接,侵入該鏈接,攔截消息和修改選擇數據。
SSLStrip – 一種中間人攻擊的形式,利用了網站上的SSL / TLS實現的弱點,這能夠依賴於用戶驗證HTTPS鏈接是否存在。 攻擊將鏈接降級到HTTP,無需加密,用戶很難在移動瀏覽器中檢測到。
會話劫持 – 涉及會話密鑰的利用以得到對用戶和網絡信息的未受權訪問。
DNS 劫持 – 利用網絡DNS能夠將網站的用戶引導到攻擊者選擇的另外一個網站。 在某些狀況下,攻擊還能夠經過應用程序注入內容。
假SSL證書 – 另外一箇中間人攻擊涉及發出假SSL證書,容許惡意用戶攔截假定安全的HTTPS鏈接上的流量。
針對數據中心的攻擊者使用兩個主要入口點:
基於Web服務器的攻擊和漏洞包括:
平臺漏洞 – 操做系統,服務器軟件或Web服務器上運行的應用程序模塊的漏洞可能被攻擊者利用。 有時能夠經過監視移動設備和web服務器之間的通訊來發現脆弱性,以發現協議或訪問控制中的弱點。
服務器錯誤配置 – 配置不良的Web服務器可能容許對一般受保護的資源的未受權訪問。
跨站點腳本 (XSS) – 跨站點腳本是一種涉及將惡意JavaScript代碼注入網站的攻擊。 容易受到此類攻擊的頁面會將用戶輸入返回瀏覽器,而不會正確地對其進行整理。 此攻擊一般用於在用戶訪問頁面時自動運行代碼,從而控制用戶的瀏覽器。 在已經創建對瀏覽器的控制以後,攻擊者能夠將該控制用於各類攻擊,諸如內容注入或惡意軟件傳播。
跨站點請求僞造 (CSRF) – 跨站點請求僞造涉及攻擊者根據特定Web應用程序的功能知識建立HTTP(Web)請求,並誘騙用戶或瀏覽器提交這些請求。 若是Web應用程序易受攻擊,攻擊能夠執行彷佛來自用戶的事務或提交。 CSRF一般在攻擊者已經經過XSS,社交工程或其餘方法得到對用戶會話的控制以後使用。
弱輸入驗證 – 許多Web服務過分信任來自移動應用程序的輸入,依靠應用程序來驗證最終用戶提供的數據。 可是,攻擊者能夠僞造本身與Web服務器的通訊,或徹底繞過應用程序的邏輯檢查,容許他們利用服務器上缺乏的驗證邏輯來執行未經受權的操做。
暴力攻擊 – 暴力攻擊只是試圖猜想對字段的有效輸入,一般使用高速率的嘗試和可能值的字典。 暴力攻擊的最多見用法是身份驗證,但也可用於在Web應用程序中發現其餘有效值。
數據庫攻擊和漏洞包括:
SQL 注入 – 沒有正確驗證用戶輸入的接口可能致使SQL被注入到其餘無害的應用程序查詢中,致使數據庫暴露或以其餘方式操縱一般應該限制用戶或應用程序的數據。
執行操做系統級命令 – 與SQL注入相似,某些數據庫系統提供了執行操做系統級命令的方法。 攻擊者能夠將這些命令插入到查詢中,使數據庫在服務器上執行這些命令,從而爲攻擊者提供額外的權限,直至幷包括根級別系統訪問。
權限提高 – 當攻擊利用一些漏洞得到更大的訪問時,會發生這種狀況。 在數據庫上,這可能致使敏感數據被盜。 數據轉儲 - 攻擊者致使數據庫轉儲數據庫中的一些或全部數據,暴露敏感記錄。
移動應用一般分爲三個操做類別:
Web – 經過通用網絡瀏覽器操做的應用。 有時被稱爲WAP或移動網站,這些是移動等同於在過去十年中激增的功能性網絡應用程序,提供許多功能,如網上銀行和購物。 雖然常規網站可用於移動網絡瀏覽器,但許多公司如今建立單獨的移動網絡應用以優化移動屬性,例如更小的屏幕尺寸,基於觸摸的導航和GPS位置的可用性。
Native – 安裝的應用程序,其操做本機移動設備操做系統,爲特定的移動平臺編譯並利用其API。 這些一般(但不老是)經過應用程序市場下載和安裝。
Wrapper – 經過在專用本機應用程序包裝器(有時也稱爲「shell應用程序」或「混合應用程序」)中利用網頁操做的應用程序。雖然對最終用戶顯示爲本機應用程序,但基於Web的功能可能致使不一樣的漏洞 比在徹底本地編碼的應用程序中發現。
反向工程應用程序能夠提供有價值的洞察您的應用程序的工做原理。 使您的應用程序在內部更復雜,攻擊者更難以看到應用程序如何操做,這能夠減小攻擊面的數量。
反向工程一個Android應用程序(.apk文件)是很容易實現的,而後能夠檢查應用程序的內部工做。 混淆代碼,以使惡意用戶更難以檢查應用程序的內部工做,以下面連接到Android開發人員#### 參考文章中所述。
此外,因爲iOS應用程序的設計方式,它們容易受到逆向工程攻擊。 應用程序的類和協議存儲在對象文件中,容許攻擊者徹底映射應用程序的設計。 Objective-C自己是一種反射語言,可以感知和修改本身的狀態; 具備正確工具的攻擊者能夠以與運行時管理應用程序相同的方式感知和修改應用程序的狀態。 Objective-C包含一個簡單的消息框架,它很是容易跟蹤,而且能夠被操縱來攔截甚至篡改應用程序的運行時。 能夠使用相對簡單的攻擊來操縱Objective-C運行時繞過身份驗證和策略檢查,內部應用程序健全檢查或警告應用程序策略的那種邏輯檢查。
若是應用程序處理高度敏感的數據,請考慮實施反調試技術。 存在能夠增長逆向工程代碼的複雜性的各類技術。 一種技術是使用C / C ++來限制攻擊者輕鬆地運行操做。 有豐富的C和C ++庫,它們很是成熟,而且易於與Objective-C集成,而且Android提供了JNI(Java Native Interface)。 在iOS上,考慮在低級C中編寫代碼的關鍵部分,以免Objective-C運行時或Objective-C逆向工程工具(如class-dump,class-dump-z,Cycript或Frida)的暴露和操做。
限制調試器 – 應用程序能夠使用特定的系統調用來指定,以防止操做系統容許調試器附加到進程。 經過防止調試器attach到進程,攻擊者干擾低級運行時的能力受到限制。 攻擊者必須首先規避調試限制,以便在低級別上攻擊應用程序。 這增長了攻擊的進一步複雜性。 Android應用程序應該在應用程序清單中設置「android:debuggable =」false「」,以防止攻擊者或惡意軟件輕鬆運行運行時操做。 在iOS上,您能夠使用PT_DENY_ATTACH
。
跟蹤檢查 – 應用程序能夠肯定其當前是否由調試器或其餘調試工具跟蹤。 若是正在被跟蹤,則應用能夠執行任何數量的響應動做,例如,丟棄加密密鑰以保護用戶數據,通知服務器管理員或其餘這樣的響應以試圖保護自身。 能夠經過檢查進程狀態標誌或使用其餘技術(例如比較「ptrace attach」的返回值,檢查父進程,將進程列表中的調試器列入黑名單或比較程序不一樣部分的時間戳)來檢測調試器跟蹤。
優化 - 爲了隱藏高級數學計算和其餘類型的複雜邏輯,利用編譯器優化能夠幫助混淆目標代碼,使其不容易被攻擊者反彙編。 這使得攻擊者更難以得到對特定代碼的理解。 在Android中,經過使用本機編譯庫和本機開發工具包(NDK)能夠更容易地實現。 此外,使用LLVM Obfuscator或任何保護程序SDK將提供更好的機器代碼混淆。
Stripping binaries – 清除原生二進制文件是增長攻擊者所需的時間和技能以便查看應用程序低級功能的有效方法。 經過剝離二進制,二進制的符號表被剝離,以便攻擊者不能輕易地調試或反向工程應用程序。 剝離二進制文件不會丟棄iOS上的Objective-C類或對象映射數據。 在Android上,您能夠重用在gNU / Linux系統上使用的技術,例如sstrip
或使用UPX。
分佈在App Store中的iOS應用程序中的二進制文件被加密,增長了另外一層的複雜性。 雖然存在從這些二進制文件中剝離FairPlay數字版權管理(DRM)加密的工具,但這一層DRM增長了攻擊二進制所需的時間和熟練程度。 然而,App Store應用程序中使用的加密可能會被熟練的攻擊者剝離。 攻擊者經過轉儲在運行時從設備的內存中直接加載應用程序的內存來實現這一點。
代碼中的簡單邏輯測試更容易受到攻擊。 例如:
if sessionIsTrusted == 1
這是一個簡單的邏輯測試,若是攻擊者能夠改變這個值,他們能夠繞過安全控制。 蘋果iOS被攻擊使用這種類型的弱點和Android應用程序已經他們的Dalvik二進制補丁繞過各類保護機制。 這些邏輯測試很容易在許多級別上回避。 在組裝級別上,攻擊者能夠僅使用調試器來攻擊iOS應用程序,以找到正確的CBZ(零比較和分支)或CBNZ(比較和非零分支)指令並將其反轉。 這能夠在運行時執行,只需遍歷對象的內存地址,並在應用程序運行時更改其實例變量。 在Android上,應用程序能夠反編譯爲SMALI,並在從新編譯以前修補分支條件。
考慮一個更好的編程範例,當會話不受信任時,由服務器強制執行權限,或者經過防止某些數據被解密或以其餘方式可用,直到應用程序能夠使用質詢/響應,OTP或其餘 形式的認證。 此外,#### 建議將全部健全檢查功能聲明爲靜態內聯。 使用這種方法,它們被內聯編譯,使得更難以修補(即攻擊者不能簡單地重寫一個函數或修補一個函數)。 這種技術將須要攻擊者從應用程序中尋找並修補檢查的每一個實例,增長了攻擊所需的複雜性。 對於高度敏感的應用程序,創建在安全編碼原則中的更復雜的方法可能值得進一步調查。 集成技術(如加密,定時回調和基於流的編程)可能增長攻擊者的複雜性。
一樣,存儲在對象中的簡單邏輯變量能夠容易地被攻擊者操縱。 例如:
session.trusted = TRUE
這樣的值能夠由應用程序當前使用的類的實例內的攻擊者讀取和寫入。 在iOS上,經過操做Objective-C運行時,能夠操縱這些變量,以便下次應用程序引用這些變量時,將讀取任何操做的值。
開發人員很是依賴第三方庫。 在測試代碼時,完全探查和測試這一點很重要。 第三方庫能夠包含漏洞和弱點。 許多開發人員認爲第三方庫已經完善並通過測試,然而,問題可能並且確實存在於他們的代碼中。
安全審計必須完全測試第三方庫和功能。 這應該包括核心的iOS和Android代碼/庫。 升級到新版本的第三方庫(或操做系統版本)應視爲您的應用程序的一部分。 更新的第三方庫(或新操做系統版本)可能包含新的漏洞或暴露您的代碼中的問題。 應該測試它們,就像爲應用程序測試新代碼同樣。 在iOS上,靜態編譯第三方庫以免LD_PRELOAD攻擊; 在這種攻擊中,一個庫及其功能能夠被替換爲具備被惡意代碼替換的攻擊者庫。
攻擊者能夠在應用上篡改或安裝後門,從新簽名並將惡意版本發佈到第三方應用市場。 這種攻擊一般針對流行的應用程序和金融應用程序。
採用防篡改和篡改檢測技術來防止非法應用程序執行。
使用校驗和,數字簽名和其餘驗證機制來幫助檢測文件篡改。 當攻擊者試圖操縱應用程序時,不會保留正確的校驗和,而且這能夠檢測和防止非法執行。 注意,這樣的技術不是萬無一失的,而且能夠被充分動機的攻擊者繞過。 校驗和,數字簽名和其餘驗證技術增長了攻擊者必須花費的時間和精力才能成功地破壞應用程序。 應用程序能夠在檢測到篡改的狀況下以靜默方式擦除其用戶數據,密鑰或其餘重要數據,以進一步挑戰攻擊者。 檢測到篡改的應用程序還能夠通知管理員。
在Android上,用於簽名應用程序的公鑰能夠從應用程序的證書中讀取,並用於驗證應用程序是否已使用開發人員的私鑰簽名。 使用PackageManager類,能夠檢索應用程序的簽名,而後將它們與正確的值進行比較。 若是有人篡改或從新簽名了應用程序,比較將失敗,致使檢測到篡改應用程序。
一般,iOS開發人員會將應用程序設置存儲在plist文件中,在某些狀況下這可能會受到影響。
當應用程序正在使用時,用戶或應用程序特定的數據能夠存儲在RAM中,而且在用戶註銷或會話超時時不會正確清除。 由於Android將應用程序存儲在內存中(即便在使用後),直到內存被回收,加密密鑰可能會保留在內存中。 發現或竊取設備的攻擊者能夠附加調試器並從應用程序轉儲內存,或者加載內核模塊以轉儲內存中的所有內容。
當管理密碼和其餘敏感信息時,應用程序會將該信息保存在內存中,即便緩衝區釋放了一段時間。 若是應用程序容易出現緩衝區溢出,格式化字符串,數據泄露和其餘漏洞,這多是一個安全問題,這可能容許攻擊者轉儲進程的內存以恢復敏感信息。
不要將內存中保存敏感數據(例如加密密鑰)長於所需的時間。 清除使用後保存密鑰的任何變量。 避免對敏感的密鑰或密碼使用不可變對象,如在Androidjava.lang.String
中,而是使用char數組。 即便對不可變對象的引用被刪除或清空,它們可能保留在內存中,直到垃圾回收發生(這不能被應用程序強制)。
這隻能經過低級語言完成,由於若是優化例程檢測到緩衝區在覆蓋後再也不使用,編譯器和即時虛擬機將會因性能緣由而忽略這些操做。
有一些工具能夠來繞過編譯器優化以清除這些緩衝區,但他們都依賴工具鏈,特定的語言和平臺。
在Android上,調用file.delete()將不會安全地擦除目標文件,而且只要它沒有被覆蓋,它能夠從設備的物理圖像刻出。 因爲對NAND閃存的積極管理,擦除文件的傳統方法一般不在移動設備上工做。
在假設任何寫入設備的數據均可以恢復的狀況下操做。 在某些狀況下,加密可能會增長額外的保護層。
對於大多數應用程序不推薦使用如下方法,但可能刪除文件並用大文件覆蓋全部可用空間(這將迫使NAND閃存擦除全部未分配的空間)。 這種技術的缺點包括耗盡NAND閃存,致使應用和整個設備響應緩慢,並顯着的功耗。
儘量避免在設備上存儲敏感數據。
加密存儲在文件中的敏感數據,在刪除以前重寫文件的內容和同步能夠幫助,可是如上所述,它們不是徹底可靠的解決方案。
一個主要的突破口是執行一個簡單的通過修改過的查詢字符串。查詢字符串參數是可見的,而且可能常常意外地緩存(從網絡歷史記錄,Web服務器或代理日誌等)。應該避免使用未加密的有意義的數據做爲查詢字符串。 若是用戶憑證做爲查詢字符串參數傳輸,而不是在POST請求的正文中傳輸,那麼這些憑證可能會被記錄在各類地方 - 例如,在用戶的瀏覽器歷史記錄中,在Web服務器日誌中,以及在日誌中或者在基礎設施服務商採用的任何反向代理。 若是攻擊者成功地得到這些資源中的任何一個,則他能夠經過捕獲存儲在那裏的用戶憑證來提高權限。
使用安全的具備XSRF令牌保護的POST方法來發送用戶數據。 在能夠找到查詢字符串數據的區域中,默認狀況下不會記錄POST數據。 不管是POST仍是GET,都應使用臨時會話Cookie。 使用非零初始化向量和臨時會話密鑰加密數據也能夠幫助防止重放攻擊。 若是須要,能夠使用在主機之間使用安全算法(例如Diffie-Hellman)協商的臨時會話密鑰來加密查詢字符串數據。
Pinto, Marcus (2007). The Web Application Hacker’s Handbook: Discovering and Exploiting Security Flaws (Kindle Locations 2813-2816). Wiley. Kindle Edition.
在移動設備上安全地存儲數據須要適當的技術。 只要有可能「簡單地不要存儲或緩存數據」 是避免數據在設備上被獲取最直接的方式。
儘可能不要存儲敏感數據。 減小用戶信息存儲的方法包括:
若是在設備上存儲敏感數據是應用程序需求,則應向數據添加額外的通過驗證的第三方加密(例如,SQLCipher)。
經過添加另外一層加密,您能夠更好地控制實施和攻擊,主要集中在主要的操做系統加密類。 例如,對iOS數據保護類(如今已被入侵)的攻擊將沒法直接危害您的應用程序。 這種方法具備更復雜的缺點,而且若是實施得很差,實際上會減小安全係數。 若是您不肯定是否包括通過驗證的第三方加密庫,Apple和Android的通用加密庫提供了許多標準加密功能,若是使用得當,能夠提供至關安全的加密實現。
下面是一些方法:
每當您加密用戶數據時,旨在使用隨機生成的主密鑰對其進行加密,該主密鑰在用戶訪問數據時也使用用戶提供的密碼加密。 這將防止數據被容易地恢復,若是攻擊者從設備中提取主密鑰。 因爲Apple的數據保護API和鑰匙串中的漏洞數量以及大多數Android手機上缺乏設備加密,所以不#### 建議將主密鑰或密碼存儲在設備上。
在Android中,記住外部存儲設備(如SD卡)沒有細粒度的權限,任何應用程序默認狀況下具備對存儲的讀訪問權限,能夠讀取全部文件。 從Android 4.4開始應用程序能夠在某些狀況下以受保護的方式在SD卡上存儲數據 (#### 參考 http://source.android.com/devices/tech/storage/).
Android和iOS實現標準加密庫,例如AES,可用於保護數據。 請注意被此方法加密的數據安全依賴於用於導出密鑰和密鑰管理的密碼安全。 須要考慮密碼策略,長度和複雜性與用戶方便性以及加密密鑰如何存儲在內存中。 並且root權限能夠轉儲正在運行的進程的內存,並搜索它的加密密鑰。
還要注意,使用標準加密提供程序「AES」一般將默認爲較不安全的AES-ECB。 最佳作法是使用256位密鑰和SecureRandom生成的隨機IV指定AES-CBC或AES-GCM。 您還應該使用通過良好測試的PBKDF2(基於密碼的密鑰導出函數)來從密碼導出密鑰。
iOS中內置的數據保護API與複雜的密碼短語相結合,能夠提供額外的數據保護層,但不像實施其餘第三方驗證的加密技術那麼安全。 爲了利用這一點,文件必須被專門標記。(#### 參考最佳實踐 6.1 謹慎使用keychain). 任何沒有專門使用apple 的文件保護api加密的數據都是未加密存儲的
若是Cookie未標記爲「Secure」,則不管與主機的會話是否安全,均可能經過不安全的鏈接進行傳輸。 換句話說,它能夠經過HTTP鏈接來傳輸。
此外,因爲Cookie沒法經過客戶端訪問(例如,沒法使用JavaScript代碼段訪問),所以在Cookie上設置「HTTPOnly」標誌可防止跨站點腳本(XSS)等攻擊。
Set-Cookie頭應該使用「Secure」和「HTTPOnly」設置。 這些設置應適用於本機和/或網絡應用程序的全部Cookie。
許多應用程序沒有正確驗證SSL / TLS證書,使他們容易受到中間人(MITM)攻擊。 若是應用程序沒法正確驗證其與服務器的鏈接,則該應用程序容易受到特權網絡攻擊者的MITM攻擊。 這種類型的攻擊使罪犯可以捕獲,查看和修改在應用程序和服務器之間發送和接收的流量。
未正確驗證其與服務器的鏈接的應用程序容易受到擁有網絡管理權限的攻擊者的中間人攻擊。 這意味着攻擊者將可以捕獲,查看和修改在應用程序和服務器之間發送和接收的流量。
開發人員可能會由於各類緣由而停用應用中的證書驗證。 一個例子是開發人員須要在生產服務器上測試代碼,但沒有測試環境的域證書。 在這種狀況下,開發人員能夠向網絡庫添加代碼以接受全部有效的證書。 然而,接受全部證書爲有效的,容許攻擊者經過簡單地使用自簽名證書對應用程序執行MITM攻擊。 這種開發應用程序的方法使SSL / TLS的效果無效,而且相對於未加密的純文本鏈接(除了須要主動MITM攻擊來查看和修改流量,而純文本鏈接能夠被動監控以外)沒有實質上的安全提高。
如下是接受全部SSL / TLS證書的有效Android代碼示例:
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() { public java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; } public void checkClientTrusted(X509Certificate[] certs, String authType) { } public void checkServerTrusted(X509Certificate[] certs, String authType) { } } }; //Globally set the broken TrustManager SSLContext sc = SSLContext.getInstance("SSL"); sc.init(null, trustAllCerts, new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory()); //Make the connection to the server URL url = new URL("https://paypal.com"); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); InputStream ins = urlConnection.getInputStream(); InputStreamReader isr = new InputStreamReader(ins); BufferedReader in = new BufferedReader(isr); String inputLine; in.close();
在實施SSL / TLS時,另外一個常見的開發人員錯誤是設置一個容許全部主機名的主機名驗證器(hostname verifier)。 在這種狀況下,應用程序將不接受自簽名證書,證書仍然須要被驗證。 可是若是應用程序「容許全部主機名」,任何有效的證書頒發機構(CA)爲任何域名頒發的證書均可以被用來進行中間人攻擊(MITM)和簽名網絡數據。
下面是一個易受攻擊的Android代碼示例,它設置了一個容許全部主機名的主機名驗證器:
URL url = new URL("https://paypal.com"); HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(); urlConnection.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); InputStream ins = urlConnection.getInputStream(); InputStreamReader isr = new InputStreamReader(ins); BufferedReader in = new BufferedReader(isr); String inputLine; in.close();
對於處理高度敏感數據的任何應用程序,請使用證書鎖定以防止MITM攻擊。 大多數應用程序都定義了它們鏈接的位置(它們的後端服務器),並固有地信任它們鏈接的基礎設施,所以使用「私有」公鑰基礎結構(與公共證書分開)是能夠接受的(一般更安全) 當局。 使用這種方法,攻擊者須要來自服務器端的私鑰對他們沒有物理訪問的設備執行MITM攻擊。
若是沒法對處理高度敏感數據的任何應用程序功能實施證書鎖定,請實施正確的證書驗證,該證書驗證由兩部分組成:
將證書固定到Android隨附的默認Apache HTTP客戶端包括獲取所需主機的證書,轉換.bks格式的證書,而後將證書固定到DefaultHttpClient實例。 BKS密鑰庫一般包含在應用程序的APK文件的assets / raw目錄中。
如下示例代碼演示瞭如何加載BKS密鑰庫:
InputStream in = resources.openRawResource(certificateRawResource); keyStore = KeyStore.getInstance("BKS"); keyStore.load(resourceStream, password);
httpClient實例能夠被配置爲僅容許接受存在於應用程序內存儲的證書籤名的證書。
如下示例代碼說明了此方法:
HttpParams httpParams = new BasicHttpParams(); SchemeRegistry schemeRegistry = new SchemeRegistry(); schemeRegistry.register(new Scheme("https", new SSLSocketFactory(keyStore), 443)); ThreadSafeClientConnManager clientMan = new ThreadSafeClientConnManager(httpParams, schemeRegistry); httpClient = new DefaultHttpClient(clientMan, httpParams);
有關在Android中實現證書鎖定的更多信息,請參閱OWASP Certificate and Public Key Pinning guide
此外,CWAC-NetSecurity 是一個將Android 7.0網絡安全配置子系統返回到API級別17(Android 4.2)的庫。它使得將應用程序綁定到特定的證書頒發機構或證書更容易。支持自簽名證書,以及處理其餘高級SSL證書方案。
一個方案是使用NSURLSession
或AFNetworking
類在iOS中實現證書鎖定。 此實現的其餘詳細信息能夠在apple developer網站上HTTPS Server Trust Evaluation中找到。
此外,一個開源框架的TrustKit能夠幫助開發人員更容易地在iOS中部署公鑰鎖定。
使用這種形式的中間人攻擊,攻擊者能夠經過透明地劫持網絡上的HTTP流量,監控HTTPS請求,而後消除SSL / TLS來繞過SSL / TLS,從而在客戶端和服務器之間建立不安全的鏈接。 這種攻擊在移動網絡應用上尤爲難以預防(移動網絡應用本質上是一個看起來像應用的網頁)。
經過TLS提供全部流量,甚至非敏感流量。 這防止了任何可能的降級/剝離攻擊,由於攻擊者須要初始明文「入口點」來完成所述攻擊。
驗證SSL / TLS是否處於活動狀態。 在徹底本機應用程序中驗證SSL / TLS是相對簡單的。 移動網絡應用能夠經過JavaScript驗證SSL / TLS,以便若是未檢測到HTTPS鏈接,則客戶端將重定向到HTTPS。 要求SSL / TLS的更可靠的手段是HTTP嚴格傳輸安全(HSTS)頭。 HSTS標頭強制與該域的全部後續鏈接使用TLS和原始證書。 瀏覽器只是開始實現HSTS頭而移動瀏覽器老是滯後。
在應用程序中使用圖標或語言,以確保用戶在所述鏈接不依賴於通過驗證的HTTPS會話時知道並進行安全鏈接。 教育用戶是下降SSL / TLS降級攻擊風險的重要組成部分。 在應用程式內使用彈出提示和文字提示,強化使用者使用HTTPS保護網路流量的重要性。
最近在Android和iOS中實施的另外一種緩解措施是將非TLS /純文本流量視爲開發人員錯誤。Android最近添加 android:usesCleartextTraffic
(Android M and the War on Cleartext Traffic,而iOS 9及更高版本要求您手動添加明文流量的例外。 替換Web協議HTTP / 2是另外一個將來的解決方案,由於它僅使用TLS(而且包括其餘功能).
大多數移動設備具備在製造時爲了識別目的而分配的惟一ID(也稱爲通用惟一標識符(UUID))。 例如,iOS設備分配了所謂的惟一設備標識符(UDID)。 惟一標識設備的能力對於獲取,管理和保護數據一般很重要。 開發人員迅速採用UUID和UDID進行設備識別,從而使其成爲許多系統的安全基礎。
不幸的是,這種方法帶來了幾個隱私和安全問題。 首先,許多在線系統已將設備的UUID鏈接到單個用戶,以便即便在用戶未登陸到應用時也可以跨應用進行跟蹤。 這種跟蹤用戶的高級功能已經成爲主要的隱私問題。
除此以外,經過UUID識別人員的應用程序有風險暴露設備的之前的全部者的數據到新的全部者。 在一個實例中,在從新設置iPhone以後,即便全部用戶數據已被擦除,咱們也能夠訪問先前用戶的在線音樂服務的賬戶。 這不只是一個隱私問題,它的安全威脅,由於攻擊者能夠僞造一個UUID。
蘋果已經認識到iOS的UDID的隱私和安全風險,並刪除了開發者對它的訪問。 在UDID不可用的狀況下,一些開發人員應用涉及無線網絡接口或OpenUDID的MAC地址的其餘設備識別方法。 這些方法如今已在系統/ API級別被禁止,而且做爲AppStore審查過程的一部分被標記和拒絕。
咱們#### 建議開發人員避免使用任何設備提供的標識符來標識設備,特別是若是它是實施設備身份驗證的一部分。 相反,咱們#### 建議在註冊,安裝或首次執行時建立應用程序惟一的「設備因子」。 而後可能須要將此應用程序惟一的設備因子與用戶身份驗證結合,以建立會話。 設備因子也能夠用做加密例程中的附加因子。
因爲它不依賴於可預測的,設備提供的數據,所以開發變得更加困難。 經過利用挑戰 - 響應方法,服務器和設備能夠在用戶認證以前彼此認證。 要得到系統訪問,攻擊者必須利用這兩個因素。 開發人員還能夠實如今客戶端或服務器端重置設備因素的功能,從而強制對用戶和設備進行更嚴格的從新身份驗證。
爲了在保留廣告功能的同時保護用戶隱私,Apple#### 建議使用advertisingIdentifier - 在系統中全部應用程序之間共享的惟一標識符。用戶能夠隨時在設置 - >隱私 - >廣告菜單中重置其設備上的advertisingIdentifier。
Android和iOS能夠使用GPS準確地肯定位置。 處理此GPS數據是一個隱私問題,若是攻擊者知道其當前或過去的位置,可能會使用戶容易受到其餘攻擊。 本地藍牙、NFC 、RFID標籤的信息也可能泄漏地理位置信息。
此外,訪問圖庫圖片的應用程序也能夠是用戶的隱私問題,它能夠經過檢查時間戳而且假設圖片是用戶本身拍攝的圖片來抓取存儲在其中的GPS位置(若是有的話)。
考慮使用和避免存儲GPS數據的影響。 爲了更好的隱私,儘可能使用最粗粒度的位置服務。 除非必要,不要記錄或存儲GPS信息。 雖然在某些應用中使用GPS可能頗有用,但不多須要記錄和存儲數據。 避免這種狀況防止了許多隱私和安全問題。 GPS定位信息一般在iOS上的locationd緩存和Android上的各類緩存之間緩存一段時間。 一些應用程序自動使用GPS。 一個例子是一般對圖像進行地理標記的相機。 若是這是一個問題,請確保從圖像中剝離EXIF數據。
在須要安全的地點工做時,請記住,GPS數據可能會報告給Apple和Google服務器,以提升準確性。 Android和iOS設備都能捕獲範圍內附近接入點的信息,不管設備是否鏈接到它們。 不要在將在安全位置或其附近運行的應用程序中激活GPS,其座標或無線網絡拓撲不該報告給供應商。 除此以外,攻擊者能夠使用單個接入點的硬件地址的知識來模擬安全無線環境並從蘋果或Google返回環境的GPS座標。
移動設備常常丟失或被盜,攻擊者能夠利用活動的會話來訪問敏感數據,執行事務或在設備全部者的賬戶上執行偵察。 此外,若是沒有適當的會話超時,應用可能容易受到中間人攻擊的數據攔截。
任什麼時候間應用程序不使用超過5分鐘,終止活動會話,將用戶重定向到登陸屏幕,確保沒有應用程序數據可見,並要求用戶從新輸入登陸憑據以訪問 應用程序。
超時後,還要丟棄和清除與用戶數據相關聯的全部內存,包括用於解密數據的任何主密鑰
此外,確保客戶端和服務器端都發生會話超時,以減輕攻擊者修改本地超時機制。
弱或不存在的身份驗證能夠授予攻擊者對應用程序的未經受權的訪問權限。
密碼不該該是簡單的。 最好要求(若是不是至少支持)複雜密碼,包括至少六個字母數字字符的長度(更多字符老是更強)。 做爲登陸過程的一部分,要求選擇一個祕密詞或圖標(不是用戶本身建立的)能夠幫助保護用戶的賬戶,以防他們重複使用密碼,並防止密碼被從其餘數據猜出。
在某些狀況下,用戶名和密碼不能爲移動應用程序提供足夠的安全性。 當涉及敏感數據或事務時,實施雙因素身份驗證。 在用戶每次登陸時都進行二次身份驗證可能不大合適,但能夠按時間間隔或在訪問所選功能時使用。 能夠考慮逐步認證方法以提供對非事務性區域的正常訪問,但須要針對敏感功能進行第二層認證。
加強認證的選項包括:
對於最高級別的安全性,使用一次性密碼,要求用戶不只擁有正確的憑據,並且還要包括一次性密碼的物理令牌。
iOS開發人員常常將應用程序設置存儲在plist文件中,在某些狀況下可能會受到損害。 相似地,Android開發人員一般將設置存儲在共享首選項XML文件或SQLite數據庫中,這些數據庫在默認狀況下未加密,能夠使用root權限讀取或甚至修改,或使用備份。
儘量將設置編譯爲代碼。 經過plist文件在iOS上配置應用程序沒有什麼好處,由於更改必須綁定並部署爲新的應用程序。 相反,若是將配置包含在應用程序代碼中,攻擊者須要更多的時間和技能才能修改。 除非先加密不要在字典或其餘文件中存儲任何關鍵設置。 理想狀況下,使用由用戶提供的密碼加密的主密鑰或用戶登陸系統時遠程提供的密鑰加密全部配置文件。
許多app在各類UI顯示中存儲完整的賬號。
鑑於移動應用在公共場所的普遍使用,顯示部分號碼(例如***9881)能夠幫助確保此信息的最大隱私。 除非須要在設備上存儲完整的數字,不然存儲部分隱藏的數字。 一般,賬號用於查詢服務器端賬戶數據; 該數據能夠容易地從存儲器中被盜取,或者在某些狀況下被操縱以處理用戶不該該具備訪問權限的賬戶。 #### 建議將令牌(token)分配給每一個賬戶,並提供給客戶端,而不是賬號。 這些令牌(不該由用戶推斷)具備到實際賬戶的服務器端映射。 若是應用程序數據被盜,用戶的賬號不會被暴露,攻擊者必須首先肯定映射回賬戶的令牌,而不能直接查詢賬號。
在iOS中,若是你意識到
> - (BOOL)textField:(UITextField *)textField > shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
做爲文本字段的委託的一部分,您能夠更改輸入文本的可見性。
與網絡瀏覽器不一樣,移動設備一般不會公開應用程序是否使用SSL / TLS來保護數據傳輸,所以應用程序用戶只能相信應用程序的開發人員已實施網絡加密。
多年來,SSL(後繼者是TLS)一直是Web通訊加密的標準,包括爲移動應用程序提供支持的Web服務。 然而,違反認證機構如DigiNotar和Comodo暴露了許多用戶僞造證書。 蘋果 「goto fail」 錯誤進一步暴露了SSL / TLS的可靠性依賴於應用程序開發人員。
今天,最佳實踐要求應用提供商有效地使用SSL / TLS來保護經過網絡傳輸密碼,登陸ID和其餘敏感數據,甚至進一步利用應用層加密來保護用戶數據。
使用SSL / TLS與標準信任驗證,或爲了增長安全性,實施證書鎖定(#### 參考 OWASP 「Pinning Cheat Sheet」).
爲了防止經過受損的SSL / TLS鏈接攔截高度敏感的值(例如登陸ID,密碼,PIN,賬號等),請在傳輸過程當中增長額外的加密。 使用密鑰大小256爲AES(也稱爲Rijndael)加密高度敏感的值。而對於hash,請使用諸如SHA-256或更高版本的算法。
在服務器端,請考慮僅接受強TLS密碼和密鑰,並禁用較低級別的加密,例如導出級40位加密
即便數據是從您的應用程序生成的,這些數據也可能被攔截和操縱。 這可能包括致使應用程序崩潰(生成關鍵崩潰日誌),緩衝區溢出,SQL注入和其餘攻擊的攻擊。 經過實現UITextFieldDelegate中的方法並利用上面的#### 建議,這能夠很容易地在iOS中執行。
與正確的Web應用程序安全性同樣,客戶端的全部輸入都必須被視爲不受信任。 服務必須完全過濾和驗證應用程序和用戶的輸入。 適當的清理包括在發送以前和接收期間的全部用戶輸入。
在Android或iOS設備上執行數據備份還能夠備份存儲在應用程序的私人目錄中的敏感信息。
默認狀況下,Android應用程序的Manifest文件中的allowBackup
的值爲true
。 這將產生一個Android備份文件(backup.ab),包括設備文件系統上的應用程序私有目錄中包含的全部子目錄和文件。 所以,顯式聲明allowBackup
標誌爲false
。
在對安裝了特定應用程序的設備執行iTunes備份時,備份將包括設備文件系統上包含在該應用程序的私人目錄中的全部子目錄(「Caches」子目錄除外)和文件。 所以,請避免將任何敏感數據以明文存儲在應用程序的私有目錄或子目錄中的任何文件或文件夾中。
數據能夠在不少地方被捕獲,儘管許可能是無心的。 開發人員常常忽略一些能夠存儲數據的方式,包括日誌/調試文件,cookie,網絡歷史記錄,網頁緩存,屬性列表,文件和SQLite數據庫。 在移動設備上安全地存儲數據須要適當的技術。 只要有可能「簡單地不要存儲或緩存數據」 是避免數據在設備上被獲取最直接的方式。
阻止HTTP高速緩存。 開發人員能夠將iOS和Android配置爲不緩存網絡數據,特別是HTTPS流量。 在iOS中,查看實現NSURLConnection委託並禁用newCachedResponse。 此外,咱們#### 建議採起步驟,以免緩存任何Web進程(如註冊)的URL歷史記錄和頁面數據。 HTTP緩存頭在此重要,並在Web服務器上配置。 HTTP協議在響應標頭中支持「no-store」指令,指示瀏覽器它不得存儲響應或引起它的請求的任何部分。 對於Web應用程序,HTML表單輸入能夠使用autocomplete = off設置指示瀏覽器不緩存值。 應用程序啓動後,能夠經過對設備數據進行讀取檢查來驗證是否已經緩存了數據。
有不少用於跟蹤用戶使用狀況並收集iOS和Android的崩潰日誌的framework,這些framework都是開發的有用工具,但重要的是要在開發人員的足夠調試信息和攻擊者的信息減小之間找到平衡。
若是應用程序崩潰,生成的日誌能夠爲攻擊者提供有價值的信息。
確保已發佈的應用程序構建時沒有任何警告,並通過完全測試,以免崩潰。 這確定老是目標,值得一提的是因爲崩潰日誌的價值。 考慮禁用iOS的NSAssert。 若是斷言失敗,此設置將致使應用程序當即崩潰。 它更加優雅地處理失敗的斷言比崩潰和生成崩潰日誌。 此外,避免經過網絡以純文本發送崩潰日誌。
使用安全的開發工具,如clang-analyzer,coverity,ASAN和其餘linting實用程序,以肯定全部可能的操做,能夠使應用程序崩潰或錯誤功能。
此外,若是應用程序被混淆和剝離,開發人員將須要保留一個地址到符號數據庫,以便在崩潰日誌中恢復有意義的回溯,使攻擊者的生活更加困難,由於在函數中缺少可理解的名稱。
在iOS上,當用戶啓用「保存此用戶ID」功能時,用戶名將緩存在CredentialsManager對象中。 在運行時,用戶名在任何類型的身份驗證以前加載到內存中,從而容許惡意進程攔截用戶名。
很難同時向用戶提供保存的用戶名的便利,以及避免經過不安全的存儲或在運行時的潛在攔截來泄露用戶名。 雖然不像密碼那麼敏感,可是用戶名是應該保護的私人數據。 提供具備更高安全性的高速緩存用戶名選項的一種潛在方法是存儲掩蔽的用戶名而不是實際的用戶名,而且在認證中將用戶名值替換爲哈希值。 能夠建立哈希值,包括在註冊時存儲的惟一設備令牌。 使用散列和設備令牌的進程的好處是,實際用戶名不存儲在本地或不加保護地加載到內存中,而且複製到另外一個設備或在網絡上使用的值將不夠。 惡意用戶必須發現更多信息才能成功竊取認證用戶名。
調試日誌一般設計爲用於檢測和糾正應用程序中的缺陷。 這些日誌可能泄漏敏感信息,這可能有助於攻擊者建立更強大的攻擊。
開發人員應考慮調試日誌在生產環境中可能出現的風險。 通常來講,咱們#### 建議他們在生產中禁用。
一般由應用程序用於輸出調試消息的Android系統日誌是存儲在存儲器中的幾千字節的循環緩衝器。 在內核崩潰的狀況下,還能夠從文件系統恢復調試日誌。 在設備從新啓動時,它被清除,但在此以前,具備READ_LOGS權限的任何Android應用程序均可以查詢日誌。 在最新版本的Android中,日誌文件已被更仔細地隔離,而且不須要請求系統級權限。
在Android中,還能夠利用ProGuard或DexGuard徹底刪除發佈版本中Log類的方法調用,從而取消對Log.d,Log.i,Log.v,Log.e方法的全部調用。
在 proguard.cfg 中,添加如下代碼段:
> -assumenosideeffects class android.util.Log { > public static *** d(...); > public static *** v(...); > public static *** i(...); > public static *** e(...); > }
在iOS上禁用NSLog語句將刪除可能被攔截的潛在敏感信息,由於額外的好處可能會稍微提升應用程序的性能。 例如,一種方法是在生產構建中定義NSLog:
> #define NSLog(s,...) This macro effectively removes all NSLog statements and replaces it with empty text at compilation time. > NSLog(@」Breakpoint here with data %@」,data.description); becomes effectively a no-op. > ;
iOS記錄用戶鍵入的內容,以便提供自定義自動更正和表單完成等功能,但敏感數據也能夠存儲。 幾乎每一個非數字字按照鍵入的順序緩存在鍵盤緩存中; 緩存的內容超出了應用程序的管理權限,所以應用程序沒法從緩存中刪除數據。
對任何敏感信息(而不只僅是密碼字段)禁用自動更正功能。 因爲鍵盤緩存敏感信息,它能夠恢復。 對於UITextField,查看將autocorrectionType屬性設置爲UITextAutocorrectionTypeNo以禁用緩存。 隨着SDK更新,這些設置可能會隨時間而變化,以確保其獲得充分研究。 添加企業策略以按期清除鍵盤字典。 這能夠由最終用戶經過簡單地去設置應用程序,通用>重置>重置鍵盤字典。
Android包含用戶字典,用戶輸入的字詞能夠保存以供未來自動更正。 此用戶字典可用於沒有特殊權限的任何應用程序。 爲了提升安全性,請考慮實施自定義鍵盤(以及可能的PIN輸入),這能夠禁用緩存,並提供針對惡意軟件的額外保護。
iOS和Android都支持複製/粘貼。 敏感數據能夠以明文形式存儲,恢復或者能夠從剪貼板修改,而無論數據的源是否最初被加密。 若是在用戶複製它時它是純文本,當其餘應用程序訪問剪貼板時,它將是明文。
例如,它遵循嚴格的規則,這意味着應用程序不能讀取或寫入剪貼板,而且使用它的惟一方式是經過用戶交互,作長按來彈出剪貼板菜單。
在適當狀況下,禁用用於處理敏感數據的區域的複製/粘貼。 取消複製選項有助於避免數據暴露。 在Android上,剪貼板能夠由任何應用程序訪問,所以#### 建議使用通過適當配置的內容提供程序來傳輸複雜的敏感數據。 在iOS上,考慮用戶是否須要在應用程序或系統範圍內複製/粘貼數據,並選擇適當類型的粘貼板。
此外,值得注意的是在取得內容後清除剪貼板,以免其餘應用程序讀取它們並泄漏用戶正在作什麼。
Frame劫持涉及在iFrame中傳送Web / WAP站點。 這種攻擊能夠使「包裝」站點執行點擊劫持攻擊。 點擊劫持是一個很是真實的威脅,已被利用高信息服務(例如Facebook)竊取信息或重定向用戶到攻擊者控制的網站。
Frame劫持的主要目的是誘騙用戶點擊不一樣的東西,他們的意圖。 目標是經過連接漏洞(如跨站腳本)收集機密信息或控制受影響的計算機。 這種攻擊一般採用嵌入在源代碼中的腳本的形式,該腳本在用戶不知道的狀況下執行。 當用戶單擊看起來執行其餘功能的按鈕時,能夠觸發。
在iOS中防止這種作法的最好方法是不使用WebViews。 很是很是當心的使用
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
(click here for more info on the NSString Class Reference).
防止Frame劫持的一種機制利用客戶端JavaScript。 大多數網站已經不能離開JavaScript,所以在JavaScript中實現安全措施(和禁用沒有它的網站)是一個方案。 雖然客戶端不是不能被篡改,可是這方案確實提升了攻擊者的標準。 下面是一個JavaScript代碼示例,它強制網站到「頂部」框架,從而「破壞」已加載網站的框架。
攻擊者能夠添加一些額外的代碼來防止Frame劫持被破壞,例如在Frame unload時提醒用戶不要退出。 更復雜的JavaScript可能可以對抗這樣的技術。 可是包含Frame劫持破壞代碼使得簡單的Frame劫持變得困難。
X-FRAME-OPTIONS HEADER– 最近在一些瀏覽器中基於響應中的HTTP頭實現了一種新的更好的反frame 劫持方案。 經過在Webserver級別配置此HTTP頭,指示瀏覽器不在Frame或iFrame中顯示響應內容。在代碼示例中提供了Apache配置文件中的示例實現。
專門爲WebView設計的API可能被濫用來危害WebView中指定的Web內容的安全性。 保護應用程序及其用戶免受這個衆所周知的漏洞的最佳方法是:
防止X-Frame-Option HTTP響應頭加載請求其餘域名託管的內容的框架。 可是,這種方案不適用於處理受影響的主機。
利用內部防護機制,確保全部UI元素在頂層框架中加載; 這樣就避免了在較低的層次,經過不信任的Frame展現內容。
基本Frame破解javascript:
if( self != top ) { top.location = self.location ; }
服務器端Apache配置文件的反iframe方案:
Header add X-FRAME-OPTIONS "DENY"
另外一個選項是將此值設置爲「SAMEORIGIN」,它將只容許來自相同域的Frame。 此標題已在各類瀏覽器上測試,包括iOS 4上的Safari,並確承認防止在iFrame中顯示頁面。 若是在iFrame中沒有傳送要求,#### 建議使用DENY。
CSRF (Cross-site Request Forgery) 依賴於已知或可預測的表單值和登陸的瀏覽器會話。
每一個表單提交應包含一個令牌,該令牌在表單中或在用戶會話的開頭載入。 在接收POST請求時,在服務器上檢查此令牌,以確保是用戶啓動它。 此功能已經被主流Web平臺提供,僅須要少許定製表單開發。
iOS提供了安全數據存儲的鑰匙串。 然而,在幾種狀況下,鑰匙串可能被泄密並隨後被解密。
在iOS的全部版本,包括iOS 7,若是攻擊者能夠訪問加密的iTunes備份,鑰匙串可能部分破解。 因爲iOS在建立iTunes備份時從新加密鑰匙串條目的機制,因此當iTunes備份可用且備份加密的密碼已知時,鑰匙串能夠被部分解密。 可是,未加密的iTunes備份不容許解密鑰匙串項。
若是越獄已應用於設備,則鑰匙串訪問控制將無效。 在越獄的狀況下,在設備上運行的任何應用程序均可能讀取每一個其餘應用程序的鑰匙串項目。
最後,對於存在BootROM漏洞的舊設備(例如,iPhone 4),該鑰匙串可能被具備對該設備的物理訪問的攻擊者獲取。
當在鑰匙串中存儲數據時,使用最嚴格的保護類(由kSecAttrAccessible
屬性定義)仍然容許您的應用程序正常工做。 例如,若是您的應用程序不是設計爲在後臺運行,請使用kSecAttrAccessibleWhenUnlocked
或kSecAttrAccessibleWhenUnlockedThisDeviceOnly
。
要防止經過iTunes備份暴露鑰匙串項目,請在實用的狀況下使用ThisDeviceOnly 選項。
最後,對於高度敏感的數據,考慮使用應用程序級加密來加強鑰匙串提供的保護。 例如,依靠用戶輸入密碼在應用程序內進行認證,而後使用該密碼在將數據存儲到密鑰鏈以前對數據進行加密。
爲了提供界面中的視覺過渡,iOS會將屏幕截圖做爲圖像存儲在設備NAND閃存的文件系統部分中。 當應用程序暫停(而不是終止)時,當按下Home按鈕或電話呼叫或其餘事件暫時掛起應用程序時,會發生這種狀況。 這些圖像一般能夠包含用戶和應用程序數據。 在一個已發佈的案例中,它們包含用戶的全名,DOB,地址,僱主和信用評分。
要保護敏感數據,請使用API配置或代碼阻止應用程序快照的緩存。
當applicationDidEnterBackground:方法運行結束時,iOS將採用應用程序用戶界面的快照,而且它用於轉換動畫並存儲在文件系統中。 應該重載此方法,而且在返回以前應刪除用戶界面中的全部敏感信息。 這樣快照就不會包含它們。
這個最佳實踐涵蓋了三個iOS代碼實現,幫助開發人員減輕緩衝區溢出攻擊他們的應用程序的風險:自動引用計數(ARC),地址空間佈局隨機化(ASLR)和堆棧崩潰保護。
自動引用計數(ARC)是一種內存管理系統,在編譯時自動處理對象的引用計數,而不是將此任務留給開發人員。 此功能是與iOS 5一塊兒引入的,但它能夠反向運行到之前的版本,由於操做是在編譯時執行的。
ASLR(地址空間佈局隨機化)是iOS 4.3中引入的一種安全功能,它隨機化應用在內存中的加載和維護。 ASLR對應用程序中使用的地址空間進行隨機化,使得在沒有首先致使應用程序崩潰的狀況下執行惡意代碼變得很困難。 它還使轉儲分配的應用程序的內存的過程變得複雜。 此測試檢查應用程序二進制文件是否使用-PIE(位置無關可執行文件)標誌進行編譯。
當應用程序使用堆棧崩潰保護編譯時,已知的值或「canary」被放置在堆棧上直接在局部變量以前,以保護保存的基指針,保存的指令指針和函數參數。 在函數返回時檢查"canary"的值,以查看它是否已被覆蓋。 編譯器使用啓發式方法來智能地將堆棧崩潰保護應用於函數(一般是使用字符數組的函數)。
啓用 ARC - 在Xcode項目中啓用ARC,或者使用Xcode中的重構工具將現有項目遷移到ARC。
ASLR - 編譯支持PIE的應用程序。 當經過命令行使用選項-PIE
(在iOS 4.3或更高版本)上編譯時,能夠啓用PIE。
堆棧崩潰保護 - 使用-fstack-protector-all
編譯器標誌編譯應用程序,以保護應用程序免受緩衝區溢出攻擊。
Transitioning to ARC Release Notes - https://developer.apple.com/library/content/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
Address Space Layout Randomization - https://developer.apple.com/library/prerelease/content/documentation/Security/Conceptual/SecureCodingGuide/Articles/BufferOverflows.html#//apple_ref/doc/uid/TP40002577-SW22
Other Compiler Flags That Affect Security - https://developer.apple.com/library/content/documentation/Security/Conceptual/SecureCodingGuide/Articles/BufferOverflows.html#//apple_ref/doc/uid/TP40002577-SW26
默認狀況下,iOS的NSURLRequest
將響應緩存在Cache.db文件中。 爲了防止這種不安全的行爲,開發人員必須明確禁用緩存。
開發人員能夠設置NSURLRequest
的cachePolicy
屬性來禁用HTTP(S)請求和響應的緩存。 禁用緩存的許多方法之一以下面的代碼片斷所示 (從Stack Overflow轉載 NSURLConnection Delegate Returns Null :
(NSCachedURLResponse)connection:(NSURLConnection)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse { return nil; }
開發人員還能夠在下面引用的Apple Developer文章「Understanding cache access」中找到禁用緩存HTTP(S)請求和響應的其餘方法。
iOS 9中的新功能,ATS(App Transport Security)有助於確保應用程序和任何後端服務器之間的安全鏈接。 默認狀況下,當應用程序與iOS 9.0 SDK或更高版本連接時,它會啓用。 啓用ATS後,HTTP鏈接將強制使用HTTPS(TLS v1.2),而且使用不安全HTTP鏈接的任未嘗試都將失敗。
應用ATS包括幾個方案:
對於在iOS 9.0或更高版本上運行的應用程序,最佳作法是經過連接到iOS 9.0或更高版本的SDK來啓用ATS,而且不要將NSAllowsArbitraryLoads
鍵設置爲「Yes」或「True」。 蘋果目前容許開發人員爲任何不能實施TLS的域設置爲例外。 能夠使用NSExceptionAllowsInsecureHTTPLoads
或NSThirdPartyExceptionAllowsInsecureHTTPLoads
鍵來設置例外。 重要的是要注意,從2017年1月開始,蘋果將要求開發人員對應用程序中聲明的任何異常(在App Store審覈期間)提供合理的理由。 不然,全部通訊必須使用ATS。
Touch ID一般被用來容許用戶在不輸入密碼的狀況下對其設備進行認證和解鎖。 一些開發人員還使用Touch ID,容許用戶使用存儲的設備指紋對其應用進行身份驗證。
當開發人員在其應用中應用Touch ID時,一般會採用如下兩種方式之一:
LAContextevaluatePolicy:localizedReason:reply
方法來實現當使用Touch ID進行身份驗證時,將應用程序的密鑰存儲在鑰匙串中,並將ACL分配給該項目。 使用此方法,iOS將在讀取和將Keychain項目返回到應用程序以前執行用戶存在檢查。 開發人員能夠在Apple網站上找到示例代碼: https://developer.apple.com/library/ios/samplecode/KeychainTouchID/Listings/KeychainTouchID_AAPLKeychainTestsViewController_m.html.
全部人可讀的文件能夠做爲程序的一個向量,泄漏敏感信息。 全部人可寫文件可能會暴露您的應用程序,讓攻擊者經過覆蓋您的應用從存儲讀取的數據影響其行爲。 示例包括設置文件和存儲的登陸信息。
不要建立具備MODE_WORLD_READABLE或MODE_WORLD_WRITABLE權限的文件,除非它是必需的,由於任何應用程序都能讀取或寫入該文件,即便它可能存儲在應用程序的私人數據目錄中。
注意: 這些常量在Android API級別17中已棄用。#### 參考: http://developer.android.com/reference/android/content/Context.html
不要使用chmod二進制或系統調用接受文件模式(chmod,fchmod,creat等)的模式,例如0666,0777和0664,
Intents用於組件間信令,並且能夠被用來作如下事情:
不正確的實現可能致使數據泄露,受限功能被調用和程序流被操縱。
經過Intents訪問的組件能夠是公共的或私有的。 默認值取決於Intents過濾器,很容易錯誤地容許組件被公開。 能夠在應用程序的Manifest中將組件設置爲android:exported = false
,以防止出現這種狀況。
默認狀況下,在清單中聲明的公共組件是開放的,因此任何應用程序均可以訪問它們。 若是組件不須要被全部其餘應用程序訪問,請考慮設置對清單中聲明的組件的權限。
公共組件接收的數據不可信任,必須仔細檢查。
一般在Android應用程序中,Activity是應用程序中的「屏幕」。
任何應用程序均可以調用exported
和 enabled
的Activity . 這可能容許攻擊者以開發者可能不想要的方式加載UI元素,例如跳過密碼鎖定屏幕訪問數據或功能。 默認狀況下,不會導出Activity,可是,若是爲Activity定義了Intent過濾器,系統將導出Activity。
Activities 能夠經過檢查內部應用程序狀態來驗證它們是否能夠加載來確保正確的行爲。 例如,首先看看應用程序是否處於「未鎖定」狀態,若是沒有,則跳回到鎖定屏幕。 不管定義什麼Intent過濾器,exported
/enabled
均可以直接使用未定義的數據調用Activity,所以當對不受信任的源提供的數據進行操做時,#### 建議使用輸入驗證。
傳遞Intent額外ID的示例代碼,而不是整個對象。
//bad passing the whole paracable object public static Intent getStartingIntent(Context context, User user) { Intent i = new Intent(context, UserDetailsActivity.class); i.putExtra(EXTRA_USER, user); return i; } //better to pass just the ID to lookup the user details public static Intent getStartingIntent(Context context, String userId) { Intent i = new Intent(context, UserDetailsActivity.class); i.putExtra(EXTRA_USER_ID, userId); return i; }
Avoid intent filters on Activities if they are private, instead use explicit intent. 避免對私有的Activities添加intent過濾器,而是使用顯式intent。
<activity android:name="com.app.YourActivity" android:label="@string/app_name" android:excludeFromRecents="true" android:exported="false" > </activity>
若是在發送廣播Intent時未設置權限,則任何非特權應用程序均可以接收Intent,除非它有明確的目標。
攻擊者能夠經過如下方式利用沒有任何設置權限的Intent:
使用權限來保護應用程序中的Intents。 請記住,當經過廣播Intent向第三方組件發送信息時,該組件可能已被惡意安裝替換。
PendingIntent容許應用程序將Intent傳遞給第二個應用程序,而後能夠執行該Intent,就像它是原始應用程序同樣(即具備相同的權限)。
使用PendingIntent,應用程序能夠將Intent傳遞給第二個應用程序,而後能夠執行該Intent,就像它是原始應用程序同樣(即具備相同的權限)。 這容許其餘應用程序回調到原始應用程序的私有組件。 外部應用程序,若是是惡意的,可能會嘗試影響目標 和/或 數據/完整性。
使用PendingIntents做爲對私有BroadcastReceivers或broadcast activities的延遲迴調,並在基本Intent中顯式指定組件名稱。
服務一般用於後臺處理。 與BroadcastReceivers和應用程序 activities 同樣,應用程序服務能夠由外部應用程序調用,所以應該由權限和導出標誌保護。
服務能夠具備能夠從外部調用者調用的多於一個方法。 能夠爲每一個方法定義任意權限,並經過使用checkPermission()
檢查調用包是否具備相應的權限。 或者,能夠經過使用AndroidManifest中定義的權限來定義單獨的服務和訪問權限。
當調用具備敏感數據的服務時,驗證正在調用正確的服務,而不是惡意服務。 若是您知道要鏈接的組件的確切名稱,請在用於鏈接的意圖中指定該名稱。 另外一種方法是再次使用checkPermission()
來驗證調用包是否具備接收所需Intent所需的權限。 用戶在安裝期間嚮應用程序授予權限。
下面是一個例子,聲明並須要在訪問com.example.MyService.
時使用自定義權限
<permission android:name="com.example.mypermission" android:label="my_permission" android:protectionLevel="dangerous"></permission>`
<service android:name="com.example.MyService" android:permission="com.example.mypermission"> <intent-filter> <action android:name="com.example.MY_ACTION" /> </intent-filter> </service>
當activity由另外一個使用廣播Intent的應用程序啓動時,Intent中傳遞的數據能夠由惡意應用程序讀取。
當另外一個應用程序經過發送廣播Intent啓動activity時,惡意應用程序能夠讀取Intent中包含的數據。 惡意應用程序還能夠讀取應用程序的最近Intent列表。 例如,若是應用程序調用並傳遞URL到Android Web瀏覽器,攻擊者能夠嗅探該URL。
不要在使用廣播Intent的應用之間傳遞敏感數據。 而使用顯式Intent。
Content providers 容許應用程序使用URI尋址方案和關係數據庫模型共享數據。 它們也能夠用於經過URI方案訪問文件。
Content providers 能夠聲明權限和單獨的讀寫訪問。 除非絕對必要,不然不要給內容提供者寫訪問權限。 除非必需,請確保設置權限,以便非特權應用程序沒法讀取ContentProvider
實例。
將訪問限制爲操做所需的最低限度。 例如,要與向某個聯繫人發送該郵件的其餘應用程序共享即時消息,只共享該單個郵件,而不是全部即時消息。 內容提供商中的記錄級委派功能容許共享特定記錄或文件,而不共享整個數據庫。 一旦外部應用程序返回到原始應用程序,表明結束。
將傳遞給內容提供者的參數視爲不受信任的輸入,而且不在沒有防禦的狀況下直接在SQL查詢中使用它們。 沒有防禦的SQL代碼能夠經過內容提供者請求發送。 若是SQL代碼包含在查詢中,它能夠返回數據或向攻擊者提供控制權。
基於文件名傳遞給提供者的文件的內容提供者應該確保路徑遍歷被過濾掉。 例如,若是攻擊者在請求中包含`../../../ file',它可能致使程序讀取並返回攻擊者在其餘狀況下不能訪問的文件中的數據。 應用程序。 此外,請注意,攻擊者建立的如下符號連接可能具備相似的結果。
WebView能夠引入一些安全問題,應該當心地使用。 目前已經發現了使用addJavscriptInterface API所產生的許多可利用的漏洞。
若是不須要JavaScript和Plugin支持,請禁用。 雖然默認狀況下都禁用它們,但最佳作法須要明確將其設置爲禁用。 禁用本地文件訪問。 這限制了對應用程序的資源和資產目錄的訪問,並減輕了來自網頁的攻擊,該網頁試圖得到對其餘本地可訪問文件的訪問。
禁止從第三方主機加載內容。 這可能很難在應用程序內實現。 可是,開發人員能夠覆蓋shouldOverrideUrlLoading和shouldInterceptRequest來攔截,檢查和驗證從WebView中發起的大多數請求。 開發者還能夠考慮經過使用URI類來檢查URI的組件以確保其匹配已批准資源的列表中的條目來實現白名單方案。
示例代碼 https://gist.github.com/scottyab/6f51bbd82a0ffb08ac7a
遠程支票存款應用程序容許一我的用手機的相機拍攝支票的圖片,而後將圖像發送到他們的金融機構存入他們的賬戶。
使用遠程支票存款應用程序,一我的能夠用手機的相機拍照支票,而後將圖像發送到他們的金融機構存入他們的賬戶。 許多這些應用程序將保留檢查圖像(或其一部分)在移動設備的NAND內存中,即便它被刪除。
不要在設備上使用非易失性存儲器傳輸支票圖像,支票圖像可能會殘留。 一個可能的替代方案是:
此方法將只維護易失性內存中的圖像,並防止支票圖像在非易失性存儲器中的緩存。
特別是使用Android Camera類,能夠使用方法takePicture指定當使用Camera.PictureCallback
接口生成.jpg時的回調。 特別是,咱們對方法「public void onPictureTaken(byte [] bytes,Camera camera)感興趣。
使用這種技術,能夠使用「bytes」數組內容,其中包含RAM中的照片。
遠程支票存款應用程序容許人們使用他們的設備拍攝支票的照片,並將其發送到其金融機構以存入賬戶。
Android將應用程序屏幕保留在內存中,而且多任務能夠致使將整個應用程序保留在內存中(即便用戶註銷其賬戶)。 這容許發現或竊取設備的攻擊者直接導航到保留的屏幕,其能夠包括做爲GUI的一部分的敏感用戶數據。 例如,若是用戶退出銀行應用,但不退出或關閉應用,則能夠保留顯示交易活動的屏幕,而且攻擊者能夠看到該屏幕。
爲了解決這個問題,開發人員有三個常見的選擇:
當用戶註銷時,徹底退出應用程序。 雖然違反Android設計原則退出您本身的應用程序,它是更安全,由於退出應用程序將銷燬任何保留的GUI屏幕。
任什麼時候間啓動活動或訪問屏幕時,請執行檢查以肯定用戶是否處於已登陸狀態。 若是用戶未登陸,則顯示登陸屏幕。
在離開屏幕或註銷以前,在GUI屏幕上清除數據。
APK應使用未過時的證書正確簽名。
下面是一個生成私鑰的Keytool命令的示例:
$ keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 -validity 10000
Web服務器上的某些設置能夠提升安全性。 Web服務器上一般被忽視的漏洞是信息泄露。 信息泄露可能致使嚴重的問題,由於每個信息攻擊者均可以從服務器得到使攻擊更容易。
減小信息泄露的一種簡單方法是禁用詳細錯誤。 詳細錯誤在開發環境中頗有用,但在生產環境中可能會泄露關鍵信息,例如Web框架信息和版本。 攻擊者能夠使用此信息來定位旨在利用實施特定缺陷的攻擊。
減小信息泄露的另外一個簡單方法是返回服務器響應中的最少許的信息。 默認狀況下,Apache將返回其版本號,運行它的操做系統和插件運行。 經過更改配置文件中的單個行,能夠減小到只公開服務器正在運行Apache而不影響功能。
能夠大大提升安全性的服務器中的一個配置更改是更改任何默認目錄。 攻擊者常常在Internet上搜索具備「low-hanging fruit」的網站,例如默認登陸,容易猜到的管理界面,以及簡單的「隱藏」目錄命名方案。 這是一個好的策略,模糊處理須要網絡訪問的服務器上的任何敏感網頁的位置。
管理或其餘限制區域不該公開網絡訪問,除非絕對必要,而且必須抵抗暴力攻擊。 HTTP認證或沒有鎖定保護的表單認證能夠(而且將)被暴力攻擊。
許多Web服務器容許較低的加密設置,例如很是弱的導出級40位加密。 實施強密碼套件以保護用於建立共享密鑰,在客戶端和服務器之間加密消息,以及生成消息哈希和簽名以確保這些消息的完整性的信息。 還要確保禁用弱協議。
確保正確安裝和配置SSL證書以實現最高的加密。 若是可能,僅啓用強密碼(128位及以上)。
TLSv1已超過10年,而且在2009年被發現很容易受到「從新協商攻擊」。
避免使用弱cipher,例如:
避免弱協議,例如:
如需獲取有關如何安全地設計和配置應用程序的傳輸層安全性的更多信息。#### 參考 OWASP Transport Layer Protection Cheat Sheet for more information about how to securely design and configure transport layer security for an app.
大多數應用程序都經過可能容易受到攻擊的Cookie來維護用戶的會話。
Web語言(例如Java,.NET)提供會話管理,這是通過良好開發和安全測試的。 使服務器軟件保持最新的安全補丁。 開發您本身的會話管理更有風險,只有在適當的專業知識。 確保會話cookie的大小足夠。 短的或可預測的會話cookie使攻擊者可能預測,高壓或對會話執行其餘攻擊。 在會話配置中使用高安全性設置。
已經被攻破的服務器有可能攔截用戶憑據並對應用用戶發起其餘攻擊。
通常來講,生產Web服務器必須通過完全測試和防護惡意攻擊。 生產服務器軟件應更新到最新版本,並加固以防止有關服務器軟件和接口的信息泄露。
身份驗證表單不該反映用戶名是否存在。 若是攻擊者有一個方法來肯定有效的用戶名,他們有一個起點的暴力攻擊和網絡釣魚攻擊。 經過向客戶端提供「無效的用戶/密碼組合」和「沒有找到此類用戶名」事件的相同響應,阻止用戶名收集。 全部的交換敏感數據的登陸表單和表單/頁面都應該實現並須要HTTPS。 Web服務器不該容許沒有SSL的客戶端鏈接用於此類資源。 關閉詳細錯誤,刪除任何遺留的沒必要要的站點或頁面,並持續強化Web資源以防潛在的攻擊。
用於內部使用的資源(例如管理員登陸表單)常用可能被暴力破解的身份驗證。 例如無鎖定的HTTP或表單認證。 管理或其餘內部資源的泄露可能致使普遍的數據丟失和其餘損害。
這種資源應該被阻止外部訪問。 任何不須要公共互聯網訪問的資源都應該使用防火牆規則和網絡分段進行限制。 若是登陸頁面,管理區域或其餘資源是外部可訪問的,它就會被惡意用戶發現和暴力攻擊。
參考文檔:https://github.com/nowsecure/secure-mobile-development/
待定
本文檔經過介紹常見開發過程當中因協議配置錯誤或代碼漏洞而致使安全的問題去避免相似現象的發生。 常見開發過程當中的協議:
數據庫做爲數據管理的平臺,它的安全性首先由系統的內部安全和網絡安全兩部分來決定。對於系統管理員來講,首先要保證系統自己的安全,在安裝MySQL數據庫時,須要對基礎環境進行較好的配置。
缺省安裝的MySQL的root用戶是空密碼的,爲了安全起見,必須修改成強密碼,所謂的強密碼,至少8位,由字母、數字和符號組成的不規律密碼。使用MySQL自帶的命令mysaladmin修改root密碼,同時也能夠登錄數據庫,修改數據庫mysql下的user表的字段內容,修改方法以下所示:
# /usr/local/mysql/bin/mysqladmin -u root password 「upassword」 //使用mysqladmin #mysql> use mysql; #mysql> update user set password=password('upassword') where user='root'; #mysql> flush privileges; //強制刷新內存受權表,不然用的仍是在內存緩衝的口令
通常狀況下,MySQL數據庫安裝在本地,而且也只須要本地的php腳本對mysql進行讀取,因此不少用戶不須要,尤爲是默認安裝的用戶。MySQL初始化後會自動生成空用戶和test庫,進行安裝的測試,這會對數據庫的安全構成威脅,有必要所有刪除,最後的狀態只保留單個root便可,固然之後根據須要增長用戶和數據庫。
#mysql> show databases; #mysql> drop database test; //刪除數據庫test #use mysql; #delete from db; //刪除存放數據庫的表信息,由於尚未數據庫信息。 #mysql> delete from user where not (user='root') ; // 刪除初始非root的用戶 #mysql> delete from user where user='root' and password=''; //刪除空密碼的root,儘可能重複操做 Query OK, 2 rows affected (0.00 sec) #mysql> flush privileges; //強制刷新內存受權表。
系統mysql的管理員名稱是root,而通常狀況下,數據庫管理員都沒進行修改,這必定程度上對系統用戶窮舉的惡意行爲提供了便利,此時修改成複雜的用戶名,請不要在設定爲admin或者administraror的形式,由於它們也在易猜的用戶字典中。
mysql> update user set user="newroot" where user="root"; //改爲不易被猜想的用戶名mysql> flush privileges;
密碼是數據庫安全管理的一個很重要因素,不要將純文本密碼保存到數據庫中。若是你的計算機有安全危險,入侵者能夠得到全部的密碼並使用它們。相反,應使用MD5()、SHA1()或單向哈希函數。也不要從詞典中選擇密碼,有專門的程序能夠破解它們,請選用至少八位,由字母、數字和符號組成的強密碼。在存取密碼時,使用mysql的內置函數password()的sql語句,對密碼進行加密後存儲。例如如下方式在users表中加入新用戶。
#mysql> insert into users values (1,password(1234),'test');
絕對不要做爲使用root用戶運行MySQL服務器。這樣作很是危險,由於任何具備FILE權限的用戶可以用root建立文件(例如,~root/.bashrc)。mysqld拒絕使用root運行,除非使用–user=root選項明顯指定。應該用普通非特權用戶運行mysqld。正如前面的安裝過程同樣,爲數據庫創建獨立的linux中的mysql帳戶,該帳戶用來只用於管理和運行MySQL。
要想用其它Unix用戶啓動mysqld,增長user選項指定/etc/my.cnf
選項文件或服務器數據目錄的my.cnf
選項文件中的[mysqld]
組的用戶名。
#vim /etc/my.cnf [mysqld] user=mysql
該命令使服務器用指定的用戶來啓動,不管你手動啓動或經過mysqld_safe
或mysql.server
啓動,都能確保使用mysql的身份。也能夠在啓動數據庫是,加上user參數。
# /usr/local/mysql/bin/mysqld_safe --user=mysql &
做爲其它linux用戶而不用root運行mysqld,你不須要更改user表中的root用戶名,由於MySQL帳戶的用戶名與linux帳戶的用戶名無關。確保mysqld運行時,只使用對數據庫目錄具備讀或寫權限的linux用戶來運行。
在命令行netstat -ant下看到,默認的3306端口是打開的,此時打開了mysqld的網絡監聽,容許用戶遠程經過賬號密碼鏈接數本地據庫,默認狀況是容許遠程鏈接數據的。爲了禁止該功能,啓動skip-networking,不監聽sql的任何TCP/IP的鏈接,切斷遠程訪問的權利,保證安全性。假如須要遠程管理數據庫,可經過安裝PhpMyadmin來實現。假如確實須要遠程鏈接數據庫,至少修改默認的監聽端口,同時添加防火牆規則,只容許可信任的網絡的mysql監聽端口的數據經過。
# vim /etc/my.cf 將#skip-networking註釋去掉。 # /usr/local/mysql/bin/mysqladmin -u root -p shutdown //中止數據庫 #/usr/local/mysql/bin/mysqld_safe --user=mysql & //後臺用mysql用戶啓動mysql
數據庫的某用戶屢次遠程鏈接,會致使性能的降低和影響其餘用戶的操做,有必要對其進行限制。能夠經過限制單個帳戶容許的鏈接數量來實現,設置my.cnf
文件的mysqld中的max_user_connections
變量來完成。GRANT語句也能夠支持 資源控制選項來限制服務器對一個帳戶容許的使用範圍。
#vim /etc/my.cnf [mysqld] max_user_connections 2
默認的mysql是安裝在/usr/local/mysql,而對應的數據庫文件在/usr/local/mysql/var目錄下,所以,必須保證該目錄不能讓未經受權的用戶訪問後把數據庫打包拷貝走了,因此要限制對該目錄的訪問。確保mysqld運行時,只使用對數據庫目錄具備讀或寫權限的linux用戶來運行。
# chown -R root /usr/local/mysql/ //mysql主目錄給root # chown -R mysql.mysql /usr/local/mysql/var //確保數據庫目錄權限所屬mysql用戶
數據庫相關的shell操做命令都會分別記錄在.bash_history,若是這些文件不慎被讀取,會致使數據庫密碼和數據庫結構等信息泄露,而登錄數據庫後的操做將記錄在.mysql_history文件中,若是使用update表信息來修改數據庫用戶密碼的話,也會被讀取密碼,所以須要刪除這兩個文件,同時在進行登錄或備份數據庫等與密碼相關操做時,應該使用-p參數加入提示輸入密碼後,隱式輸入密碼,建議將以上文件置空。
# rm .bash_history .mysql_history //刪除歷史記錄 # ln -s /dev/null .bash_history //將shell記錄文件置空 # ln -s /dev/null .mysql_history //將mysql記錄文件置空
在mysql中,提供對本地文件的讀取,使用的是load data local infile命令,默認在5.0版本中,該選項是默認打開的,該操做令會利用MySQL把本地文件讀到數據庫中,而後用戶就能夠非法獲取敏感信息了,假如你不須要讀取本地文件,請務必關閉。
測試:首先在測試數據庫下創建sqlfile.txt文件,用逗號隔開各個字段
# vi sqlfile.txt 1,sszng,111 2,sman,222 #mysql> load data local infile 'sqlfile.txt' into table users fields terminated by ','; //讀入數據 #mysql> select * from users; +--------+------------+----------+ | userid | username | password | +--------+------------+----------+ | 1 | sszng | 111 | | 2 | sman | 222 | +--------+------------+----------+
成功的將本地數據插入數據中,此時應該禁止MySQL中用「LOAD DATA LOCAL INFILE」
命令。網絡上流傳的一些攻擊方法中就有用它LOAD DATA LOCAL INFILE
的,同時它也是不少新發現的SQL Injection
攻擊利用的手段!黑客還能經過使用LOAD DATALOCAL INFILE
裝載「/etc/passwd」
進一個數據庫表,而後能用SELECT顯示它,這個操做對服務器的安全來講,是致命的。能夠在my.cnf中添加local-infile=0
,或者加參數local-infile=0
啓動mysql。
#/usr/local/mysql/bin/mysqld_safe --user=mysql --local-infile=0 & #mysql> load data local infile 'sqlfile.txt' into table users fields terminated by ','; #ERROR 1148 (42000): The used command is not allowed with this MySQL version
--local-infile=0選項啓動mysqld從服務器端禁用全部LOAD DATA LOCAL命令,假如須要獲取本地文件,須要打開,可是建議關閉。
MySQL服務器權限控制 MySQL權限系統的主要功能是證明鏈接到一臺給定主機的用戶,而且賦予該用戶在數據庫上的SELECT、INSERT、UPDATE和DELETE等權限(詳見user超級用戶表)。它的附加的功能包括有匿名的用戶並對於MySQL特定的功能例如LOAD DATA INFILE進行受權及管理操做的能力。
管理員能夠對user,db,host等表進行配置,來控制用戶的訪問權限,而user表權限是超級用戶權限。只把user表的權限授予超級用戶如服務器或數據庫主管是明智的。對其餘用戶,你應該把在user表中的權限設成’N’而且僅在特定數據庫的基礎上受權。你能夠爲特定的數據庫、表或列受權,FILE權限給予你用LOAD DATA INFILE和SELECT … INTO OUTFILE語句讀和寫服務器上的文件,任何被授予FILE權限的用戶都能讀或寫MySQL服務器能讀或寫的任何文件。(說明用戶能夠讀任何數據庫目錄下的文件,由於服務器能夠訪問這些文件)。 FILE權限容許用戶在MySQL服務器具備寫權限的目錄下建立新文件,但不能覆蓋已有文件在user表的File_priv設置Y或N。,因此當你不須要對服務器文件讀取時,請關閉該權限。
#mysql> load data infile 'sqlfile.txt' into table loadfile.users fields terminated by ','; Query OK, 4 rows affected (0.00 sec) //讀取本地信息sqlfile.txt' Records: 4 Deleted: 0 Skipped: 0 Warnings: 0 #mysql> update user set File_priv='N' where user='root'; //禁止讀取權限 Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> flush privileges; //刷新受權表 Query OK, 0 rows affected (0.00 sec) #mysql> load data infile 'sqlfile.txt' into table users fields terminated by ','; //重登錄讀取文件 #ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) //失敗 # mysql> select * from loadfile.users into outfile 'test.txt' fields terminated by ','; ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES)
爲了安全起見,隨時使用SHOW GRANTS語句檢查查看誰已經訪問了什麼。而後使用REVOKE語句刪除再也不須要的權限。
Chroot是linux中的一種系統高級保護手段,它的創建會將其與主系統幾乎徹底隔離,也就是說,一旦遭到什麼問題,也不會危及到正在運行的主系統。這是一個很是有效的辦法,特別是在配置網絡服務程序的時候。
若是不打算讓Web訪問使用MySQL數據庫,沒有提供諸如PHP這樣的Web語言的時候,從新設置或編譯你的PHP,取消它們對MySQL的默認支持。假如服務器中使用php等web程序,試試用Web形式非法的請求,若是獲得任何形式的MySQL錯誤,當即分析緣由,及時修改Web程序,堵住漏洞,防止MySQL暴露在web面前。
對於Web的安全檢查,在MySQL官方文檔中這麼建議,對於web應用,至少檢查如下清單:
試試用Web形式輸入單引號和雙引號(‘’’和‘」’)。若是獲得任何形式的MySQL錯誤,當即分析緣由。
試試修改動態URL,能夠在其中添加%22(‘」’)、%23(‘#’)和%27(‘’’)。
試試在動態URL中修改數據類型,使用前面示例中的字符,包括數字和字符類型。你的應用程序應足夠安全,能夠防範此類修改和相似攻擊。
試試輸入字符、空格和特殊符號,不要輸入數值字段的數字。你的應用程序應在將它們傳遞到MySQL以前將它們刪除或生成錯誤。將未通過檢查的值傳遞給MySQL是很危險的!
將數據傳給MySQL以前先檢查其大小。
用管理帳戶以外的用戶名將應用程序鏈接到數據庫。不要給應用程序任何不須要的訪問權限。
通常可採用本地備份和網絡備份的形式,可採用MySQL自己自帶的mysqldump的方式和直接複製備份形式, 直接拷貝數據文件最爲直接、快速、方便,但缺點是基本上不能實現增量備份。爲了保證數據的一致性,須要在備份文件前,執行如下 SQL 語句:FLUSH TABLES WITH READ LOCK;也就是把內存中的數據都刷新到磁盤中,同時鎖定數據表,以保證拷貝過程當中不會有新的數據寫入。這種方法備份出來的數據恢復也很簡單,直接拷貝回原來的數據庫目錄下便可。
使用mysqldump能夠把整個數據庫裝載到一個單獨的文本文件中。這個文件包含有全部重建您的數據庫所須要的SQL命令。這個命令取得全部的模式(Schema,後面有解釋)而且將其轉換成DDL語法(CREATE語句,即數據庫定義語句),取得全部的數據,而且從這些數據中建立INSERT語句。這個工具將您的數據庫中全部的設計倒轉。由於全部的東西都被包含到了一個文本文件中。這個文本文件能夠用一個簡單的批處理和一個合適SQL語句導回到MySQL中。
使用 mysqldump進行備份很是簡單,若是要備份數據庫」 nagios_db_backup 」,使用命令,同時使用管道gzip命令對備份文件進行壓縮,建議使用異地備份的形式,能夠採用Rsync等方式,將備份服務器的目錄掛載到數據庫服務器,將數據庫文件備份打包在,經過crontab定時備份數據:
#!/bin/sh time=`date +"("%F")"%R` $/usr/local/mysql/bin/mysqldump -u nagios -pnagios nagios | gzip >/home/sszheng/nfs58/nagiosbackup/nagios_backup.$time.gz # crontab -l # m h dom mon dow command 00 00 * * * /home/sszheng/shnagios/backup.sh 恢復數據使用命令: gzip -d nagios_backup.\(2008-01-24\)00\:00.gz nagios_backup.(2008-01-24)00:00 #mysql –u root -p nagios < /home/sszheng/nfs58/nagiosbackup/nagios_backup.\(2008-01-24\)12\:00
下列mysqld選項影響安全:
--allow-suspicious-udfs
--local-infile[={0|1}]
--old-passwords
(OBSOLETE) --safe-show-database
--safe-user-create
--secure-auth
--skip-grant-tables
--skip-name-resolve
--skip-networking
--skip-show-database
轉載:https://www.securitypaper.org