Java编码安全规范
簡述:入職菊廠第一周,沒什么任務,正全力準備java安全編碼考試,跟阿里規范類似,不過要多很多安全攻防的內容和一些之前沒注意的知識點,所以記錄分享自己學到的經驗
命名規范
類似阿里規范,省略一萬字...
編碼規范
整數溢出
對于整數溢出問題,可以通過先決條件檢測、使用Math類的安全方法.向上類型轉換或者使用Biglnteger等方法進行規避。
除數不為0
對除數進行非0判斷,然后再進行除法或取余運算。
浮點比較
考慮浮點數的精度問題,可在一定的誤差范圍內判定兩個浮點數值相等。這個誤差應根據實際需要進行定義
精度計算
涉及精確的數值計算〔貨幣、金融等),建議使用int , long .BigDecimal 等;在構造BigDecimal 時,使用浮點數容易導致精度損失,應該使用字符串格式的數值構造BigDecimal
字符串換行和分割
用做換行〈回車"\r"、換行"\n")、文件路徑分隔《"\"、"/")的字符.在不同探作系統下是有區別的。使用Systerm.lineSeparalor()獲攻運行時環境的換行符。文件騖徑分割符可以使java.io.File中的separator和pathseparator靜態屬性。
字符和字節轉換
當跨平臺實現字符與寧節之間的轉換,可能會導致亂碼。所以字符與字節之間轉換時要明確指定編碼方式
包裝類型數值運算
包裝類型進行加減乘除,涉及拆箱,可能導致空指針
斷言
對不可信源進行報錯,對可信源進行斷言
斷言是否生效依賴運行時屬性的狀態,存在被禁用的場景
信息安全
異常泄露
程序拋出的異常中,可能會包含一些敏感信息,將這些異常直接記錄到日志或反饋給用戶,會導致敏感信息泄露風險。
應該把原生異常打印記錄日志,而向用戶拋出自定義異常信息。
日志攻擊
直接將外部數據記錄到日志中,可能存在以下風險:
·日志注入:惡意用戶可利用回車.換行等字符注入一條與系統日志規格類似的偽日志;
·敏感信息泄露:當用戶輸入敏感信息時,直接記錄到日志中可能會導致敏感信息泄露;
·垃圾日志或日志覆蓋:當用戶輸入的是很長的字符串,直接記錄到日志中可能會導致產生大量垃圾日志;
·當日志被循環覆蓋時,這樣還可能會導致有效日志被惡意覆蓋。
防御手段:
·換行回車replace其他字符
·敏感信息加密后在打印日志
·截斷較長字符串
安全管理器
所有的敏感操作必須經過安全管理器的檢查,防止被不可信的代碼調用
非法路徑參數
文件路徑來自外部數據時,必須對其合法性進行校驗,否則可能會產生路徑遍歷(Path Traversal〉漏洞。
對文件路徑的規范化處理必須使用getcanonicalPath0,禁止 用getAbsalutePatho〔該方法無法保證在所有的平臺上對文件路徑進行正碎的規范化處理}
非法解壓
使用java.util.zip.ZiplnputStream解壓zip文件時,可能會有兩類安全風險:
·將文件解壓到目標目錄之外
壓縮包中的文件名中如果包含..,可能導致文件被解壓到日標日錄之外,造成任意文件注入、文件惡
意篡改等風險。因此,壓縮包中的文件在解壓前,要先對解壓的目標路徑進行校驗。如果解壓目標路徑不在預期目錄之內,要么拒絕將其解壓出來,要么將其解壓到一個安全的位置
·解壓的文件消耗過多的系統資源
zip壓縮算法可能有很大的壓縮比,可以把超大文件壓縮成很小的zip文件〈例如可以將上G的文件壓縮為幾K大小,這樣的文件解壓可能會導致zip炸彈(zip bomb)攻擊。所以zip文件解壓時,需對解壓
的實際文件大小進行檢查,若解壓之后的文件大小超過一定的限制,必須拒絕解壓。具體的大小限制根據實際情況來確定。除此之外,解壓時,還需要對解壓出來的文件數量進行限制,防止zip壓縮包中是數量巨大的小文件說明:在統計解壓文件的大小時,不應該使用entry.getsize來統計文件大小, <entry.getSize:是從zip文件中的固定字股中瀆取單個文件壓縮前的大小,文件壓縮前的大小可被惡意篡改。>
非法序列化
當序列化結果中含有敏感信息時,序列化結果在磁盤上存儲、跨信任域傳遞等操作都存在敏感信息泄露風險
- 如果敏感信息必須序列化,需要先對越感信息迄行加密或對序列化結果進行加密,跨信任邊界傳遞含敏感信良的序列化結果時要先簽名后加密。
- 使用transient關鍵詞修飾含敏感信息的屬性,避免這些屬性進行序列化
非法反序列化
當反序列化操作的數善是外部數據時,惡意用戶可利用反序列化操作構造指定的對象、執行惡意代碼、向應用程序中注入有害數據等。
- 對className進行白名單校驗。如果反序列化的類不在白名單之中,直接拋出異常.
- 如果產品已經使用Java的安全管理器,建議使用Java安全管理器機制進行防護
安全隨機數
不安全的隨機數可能被部分或全部預測到,導致系統存在安全隱患,安全場景下使用的隨機數必須是密碼學意義上的安全隨機數。
常見安全場景包括但不限于以下場景:
- 用于密碼算法用途,如生成Ⅳ、鹽值、密鑰等;
- 會話標識〈sesslonld)的生成;
- 挑戰算法中的隨機數生成;·驗證碼的陸機數生成;
安全隨機數產生方式:
- Linux操作系統的/devrandom沒備接口(存在阻塞問題}.
- windows探作系統的CryptGenRandomn)接口
- Java中的SecureRandom是一種密碼學安全的偽機數產生,對于使用非真隨機數產生器產生隨機數時,要使用少量真隨機數作為種子
網絡通信
必須使用SSLSocket代替Socket來進行安全數據交互。在數據非敏感,或數搖已加密的情況下,可以使用Socket進行傳輸,效率更高。
sql注入
SQL注入產生的根本原因是使用外部數據直接拼接SQL語句
防護手段:
·使用參數化查淘:最有效的防護手段,但對sQL語句中的表名、字段名等不適用;
·對外部數據進行白名單校驗:適用于拼接SQL語句中的表名、字段名;
·對外部數據中的與SQL注入相關的特殊字符進行轉義:適用于必須通過字符串拼接構造SQL語句的場景,轉義僅對由引號限制的字段有效
命令注入
Runtime.exec()方法或java.lang.ProcessBuildier類被用來啟動一個新的進程,在新進程中執行
命令。命令執行通常會有兩種方式
·直接執行具體命令:例如Runtime.getRuntimel).exec "ping127.0.0.1"");
·通過shell方式執行命令: vindaws下使用cmd.exe、linux下通過sh方式執行命令,或通過腳本文件( *.bati*.sh)執行命令古接使用外部數據構造命令行,會存在以下鳳險:
shell方式執行命令時,需要命令行解釋器對命令字符串進行拆分,該方式可執行多條命令,存在命令注入風險;
·直接執行具體的命令時,可以通過空格、雙引號或以-頑開頭的字符串向命令行中注入參數,存在參數注入風險.
防御手段;
·避免直接執行命令,用其他類庫函數代替·對外部數據進行白名單([O-9A-Za-z@]+〕校驗
·對外部數據進行轉義(如果輸入校驗不能禁止有風險的特殊寧符,需先外部輸入進行轉義處理,轉義后的字段拼接命令行可有效防止命令注入的產生)
XML注入
使用未經校驗的數據來構造XML會導致XML注入漏洞
防御手段:
·白名單校驗\w
·使用安全的xml庫(dom4j)
·轉義
XXE攻擊(XML External Entity外部實體攻擊)
XML實體包括內部實體和外部實體。外部實體格式: <!ENTITY實體名SYSTEM URI"">或者
<!ENTITY實體名PUBLIC"public_ID""URI""> . Java中引入外部實體的協議包括http. https、ftp. file. jar. netdoc. mailto等。XXE漏洞發生在應用程序解析來自外郁的XML數據或文件時沒有禁止外部實體的加裁,造成任意文件讀取、內網端口掃描、內網網站攻擊,DoS攻擊等危害
防御手段:
- 禁止DTDs
- 白名單校驗
XEE攻擊(XML Entity Expansion內部實體拓展攻擊)
XMIL內部實體格式:<!ENTITY實體名""實體的值"">。內部實體攻擊比較常見的是XML EntityExpansion攻擊,它主要試圖通過消耗目標程序的服務器內存資源導致DoS攻擊。例如,解析下面的XML時,因為內部實體lo9是一個非常大的字符串,所以解析<lolz>節點時,會占用大量服務器內存資源,導致拒絕服務攻擊。
防御手段;
禁止DTDs
限制實體數量
并發多線程
data race數據競爭
兩個線程對一個非volatile的共享變量進行訪問操作,其中至少一個是寫操作,且兩個操作之間沒有happends-before關系,就是datarace
通過建立happends-before消除data race.建立happends-betore需要遠取合適的同步機制:
- 消息隊列iexecutor. future)
- synchronize或volatile
happend-before原則
- 單線程按原代碼順序執行- unlock發生于lock之前
- volatile變量特性:對此變瞼過的寫操作發生于讀操怍之前isynchronized沒有happends-before}
- 線程啟動特性; start先于此線程任何一個動作
- 線程中斷特性:interrupt先于中斷事件檢測的代碼發生
- 線程終止特性:線程的所有操作都先于終止檢測的代碼發生
- 對象絡結特性:一個對象的初始化完成都先于其finalize發生開始
實例鎖無法同步靜態共享變量
鎖對象并不是static,但共亨變量是static時,鎖代碼同步效果失效。
- 把鎖對象也聲明為static即可。
錯用共享對象鎖
如果鎖對象是同一個引用內存,容易出現不同的共享變量依賴相同的鎖。
eg:private final String lock = "lock"// 或者 = Boolean.TRUE
總結
以上是生活随笔為你收集整理的Java编码安全规范的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 天气预报的获取
- 下一篇: Java 编码规范8(编程规约-注释规约