一裸卫、開發(fā)安全風(fēng)險(xiǎn)評(píng)估
序 | 開發(fā)安全規(guī)范 | 嚴(yán)重性 | 整改代價(jià) | 優(yōu)先級(jí) | 級(jí)別 |
---|---|---|---|---|---|
1 | 不要使用wrap()或duplicate()創(chuàng)建緩存仿贬,并將這些緩存暴露給非受信代碼 | 中 | 低等 | 18 | 1 |
2 | 對(duì)讀取一個(gè)字符或者字節(jié)的方法,使用int類型的返回值 | 高 | 中等 | 12 | 1 |
3 | 在終止前移除臨時(shí)文件 | 中 | 中等 | 8 | 2 |
4 | 發(fā)現(xiàn)并處理與文件相關(guān)的錯(cuò)誤 | 中 | 高等 | 4 | 3 |
5 | 不要在受信邊界之外記錄敏感信息 | 中 | 高等 | 4 | 3 |
- 級(jí)別:L1高危害墓贿、可利用性強(qiáng)茧泪、整改代價(jià)低;
- L2中危害聋袋、可能被利用队伟、整改代價(jià)中;
- 優(yōu)先級(jí):數(shù)值越高幽勒,越優(yōu)先修復(fù)嗜侮;
- 來源:Java安全編碼標(biāo)準(zhǔn)/朗(Long, F.)等著啥容,第十四章
二锈颗、開發(fā)安全規(guī)范說明
1、不要使用wrap()或duplicate()創(chuàng)建緩存咪惠,并將這些緩存暴露給非受信代碼
Buffer
類定義了一系列的wrap()
方法來封裝基礎(chǔ)數(shù)據(jù)類型到一個(gè)緩存區(qū)中击吱,并返回一個(gè)Buffer
對(duì)象來代表這個(gè)緩存區(qū)。新的緩存區(qū)由指定的字符數(shù)組來支持硝逢,也就是說姨拥,對(duì)緩存區(qū)的修改會(huì)導(dǎo)致數(shù)值的修改,反之亦然渠鸽。
將這些數(shù)組暴露給非受信的代碼叫乌,會(huì)將其背后的數(shù)組也暴露給惡意的修改。同樣徽缚,duplicate()
創(chuàng)建了額外的緩存區(qū)憨奸,這個(gè)緩存區(qū)背后是支持原始緩存區(qū)的數(shù)組。暴露這個(gè)額外的緩存區(qū)給非受信的代碼凿试,同樣將其暴露給惡意的修改排宰。
符合規(guī)范的示例:
1)使用asReadOnlyBuffer()
方法返回一個(gè)只讀的Buffer
似芝;
2)分配一個(gè)新的Buffer
,將原始數(shù)據(jù)拷貝進(jìn)入板甘,然后返回這個(gè)新Buffer
党瓮。
2、對(duì)讀取一個(gè)字符或者字節(jié)的方法盐类,使用int類型的返回值
抽象方法InputStream.read()
從一個(gè)輸入源中讀取一個(gè)簡(jiǎn)單字節(jié)寞奸,返回一個(gè)范圍在0~255
的整數(shù),僅當(dāng)在讀取到輸入流末尾的時(shí)候在跳,它會(huì)返回-1
枪萄。
類似地Reader.read()
方法讀取一個(gè)單獨(dú)的字符,返回范圍在0~65535
的整數(shù)猫妙,僅當(dāng)在讀取到輸入流的末尾時(shí)瓷翻,它會(huì)返回-1
,這兩個(gè)方法都會(huì)被子類覆寫割坠。
通常會(huì)用這些方法來從一個(gè)流中讀取一個(gè)字節(jié)或者字符齐帚。遺憾的是:在檢查是否已經(jīng)達(dá)到流末尾之前(這通過返回-1
來表示),許多開發(fā)者過早地將返回的int
類型轉(zhuǎn)換為byte
或char
類型韭脊。
符合規(guī)范的示例:
int inbuff;
char data;
while((inbuff=in.read())!=-1){
data=(char)inbuff;
//...
}
3童谒、在終止前移除臨時(shí)文件
開發(fā)人員通常在任何人都可以進(jìn)行寫操作的目錄(如/tmp/
或e:TEMP
)中創(chuàng)建臨時(shí)文件,雖然這些目錄中的文件會(huì)被定期刪除沪羔,但在刪除前饥伊,可訪問本地文件系統(tǒng)的攻擊者可以操作這些臨時(shí)文件。
因此蔫饰,對(duì)臨時(shí)文件的安全管理:
1)給予它們獨(dú)特和不可預(yù)測(cè)的文件名琅豆。這是一種減少在不安全或者共享目錄中創(chuàng)建文件帶來風(fēng)險(xiǎn)的一個(gè)通用做法。
2)在程序終止之前刪除它們篓吁。
符合規(guī)范的示例是:
1)JAVASE7及以上使用NIO2
中Files.createTempFile
方法來創(chuàng)建不可預(yù)測(cè)的文件名茫因;
2)JAVASE7及以上使用try
的構(gòu)造函數(shù)和DELETE_ON_CLOSE
選項(xiàng)來打開文件,如:
try(BufferedWriter writer = Files.newBufferedWriter(
tempfile,
Charset.forName(“UTF-8”),
StandardOpenOption.DELETE_ON_CLOSE))
{
// write data
}
4杖剪、發(fā)現(xiàn)并處理與文件相關(guān)的錯(cuò)誤
Java的文件操作方法通常使用返回值而不是拋出異常來指示其錯(cuò)誤冻押,所以難以得到有用的錯(cuò)誤信息(是文件不存在?還是沒有權(quán)限導(dǎo)致刪除失斒⒑佟洛巢?)。
忽略文件操作返回值的程序常常不能發(fā)現(xiàn)文件操作的失敗次兆,會(huì)導(dǎo)致意想不到的結(jié)果稿茉。因此恨豁,程序必須要對(duì)執(zhí)行文件I/O方法的返回值進(jìn)行檢查忘衍。
符合規(guī)范的示例:
1)JAVA SE6:檢查delete()
的返回值來判斷是否刪除成功调榄;
File file = new File(args[0]);
if(!file.delete()){
print("delete failed");
}
2)JAVA SE7及以上:使用java.nio.file.Files.delete()
方法刪除文件趟咆,其可拋出文件不存在、文件是非空目錄渺蒿、無刪除權(quán)限等異常痢士。
Path file = new File(args[0]).toPath();
try{
Files.delete(file);
}catch(IOException e){
// handle Error
}
異常 | 原因 |
---|---|
NoSuchFileException | 文件不存在 |
DirectoryNoEmptyException | 文件是一個(gè)不為空的目錄,所以不能刪除 |
IOException | 一個(gè)I/O異常產(chǎn)生 |
SecurityException | 在默認(rèn)的提供器和安全管理器安裝的情況下蘸嘶,調(diào)用SecurityManager.checkDelete(String)方法檢查文件是否有刪除訪問權(quán)限 |
5良瞧、不要在受信邊界之外記錄敏感信息
對(duì)于程序調(diào)試、事故響應(yīng)以及收集錯(cuò)誤信息训唱,日志是很重要的。然而挚冤,將敏感信息記入日志會(huì)帶來很多問題况增,包括會(huì)涉及利益相關(guān)人隱私、涉及法律對(duì)于個(gè)人信息收集上的限制训挡,以及將數(shù)據(jù)暴露給其他人員的潛在危險(xiǎn)等澳骤。
程序通常支持不同級(jí)別的保護(hù):
- 某些信息會(huì)被安全的記入日志,如訪問次數(shù)澜薄。
- 某些信息會(huì)記入日志为肮,但日志文件不向特定的管理員之外其他人開放。
- 其他的信息肤京,如信用卡號(hào)颊艳,只能通過加密形式包括在日志文件中。
- 例如像密碼這樣的信息忘分,完全不能記入日志棋枕。