安全編碼規(guī)范_第1頁
安全編碼規(guī)范_第2頁
安全編碼規(guī)范_第3頁
安全編碼規(guī)范_第4頁
安全編碼規(guī)范_第5頁
已閱讀5頁,還剩27頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權,請進行舉報或認領

文檔簡介

安全編碼規(guī)范版本號:V1.0

修訂頁編號章節(jié)名稱修訂內(nèi)容簡述修訂日期修訂前版本號修訂后版本號修訂人批準人

目錄1 目的 52 背景 53 安全編碼規(guī)范 53.1 輸入驗證和數(shù)據(jù)合法性校驗 53.1.1 避免SQL注入 53.1.2 避免XML注入 53.1.3 避免跨站點腳本(XSS) 63.2 聲明和初始化 63.2.1 避免類初始化的相互依賴 63.3 表達式 73.3.1 不可忽略方法的返回值 73.3.2 不要引用空指針 83.3.3 使用Arrays.equals()來比較數(shù)組的內(nèi)容 83.4 數(shù)字類型和操作 83.4.1 防止整數(shù)溢出 83.4.2 避免除法和取模運算分母為零 93.5 類和方法操作 103.5.1 數(shù)據(jù)成員聲明為私有,提供可訪問的包裝方法 103.5.2 敏感類不允許復制 103.5.3 比較類的正確做法 103.5.4 不要硬編碼敏感信息 113.5.5 驗證方法參數(shù) 113.5.6 不要使用過時、陳舊或低效的方法 113.5.7 數(shù)組引用問題 113.5.8 不要產(chǎn)生內(nèi)存泄露 123.6 異常處理 123.6.1 不要忽略捕獲的異常 123.6.2 不允許暴露異常的敏感信息 133.6.3 不允許拋出RuntimeException,Exception,Throwable 143.6.4 不要捕獲NullPointerException或其他父類異常 143.7 多線程編程 153.7.1 確保共享變量的可見性 153.7.2 確保共享變量的操作是原子的 163.7.3 不要調用Thread.run(),不要使用Thread.stop()以終止線程 183.7.4 確保執(zhí)行阻塞操作的線程可以終止 183.7.5 相互依存的任務不要在一個有限的線程池執(zhí)行 193.8 輸入輸出 193.8.1 程序終止前刪除臨時文件 193.8.2 檢測和處理文件相關的錯誤 193.8.3 及時釋放資源 193.9 序列化 203.9.1 不要序列化未加密的敏感數(shù)據(jù) 203.9.2 在序列化過程中避免內(nèi)存和資源泄漏 213.9.3 反序列化要在程序最小權限的安全環(huán)境中 22安全編碼規(guī)范輸入驗證和數(shù)據(jù)合法性校驗程序接受數(shù)據(jù)也許來源于未經(jīng)驗證的用戶,網(wǎng)絡連接和其他不受信任的來源,假如未對程序接受數(shù)據(jù)進行校驗,則也許會引發(fā)安全問題。避免SQL注入使用PreparedStatement預編譯SQL,解決SQL注入問題,傳遞給PreparedStatement對象的參數(shù)可以被強制進行類型轉換,保證在插入或查詢數(shù)據(jù)時與底層的數(shù)據(jù)庫格式匹配。

StringsqlString="select*fromdb_userwhereusername=?andpassword=?";PreparedStatementstmt=connection.prepareStatement(sqlString);stmt.setString(1,username);stmt.setString(2,pwd);ResultSetrs=stmt.executeQuery();避免XML注入通過StringBulider或StringBuffer拼接XML文獻時,需對輸入數(shù)據(jù)進行合法性校驗。對數(shù)量quantity進行合法性校驗,控制只能傳入0-9的數(shù)字:if(!Pattern.matches("[0-9]+",quantity)){//Formatviolation}StringxmlString="<item>\n<description>Widget</description>\n"+"<price>500</price>\n"+"<quantity>"+quantity+"</quantity></item>";outStream.write(xmlString.getBytes());outStream.flush();避免跨站點腳本(XSS)對產(chǎn)生跨站的參數(shù)進行嚴格過濾,嚴禁傳入<SCRIPT>標簽//定義需過濾的字段串<script>Strings="\uFE64"+"script"+"\uFE65";//過濾字符串標準化s=Normalizer.normalize(s,Form.NFKC);//使用正則表達式匹配inputStr是否存在<script>Patternpattern=Ppile(inputStr);Matchermatcher=pattern.matcher(s);if(matcher.find()){//FoundblacklistedtagthrownewIllegalStateException();}else{//...}聲明和初始化避免類初始化的互相依賴例:錯誤的寫法:publicclassCycle{privatefinalintbalance;privatestaticfinalCyclec=newCycle();privatestaticfinalintdeposit=(int)(Math.random()*100);//RandomdepositpublicCycle(){balance=deposit-10;//Subtractprocessingfee}publicstaticvoidmain(String[]args){System.out.println("Theaccountbalanceis:"+c.balance);}}類加載時初始化指向Cycle類的靜態(tài)變量c,而類Cycle的無參構造方法又依賴靜態(tài)變量deposit,導致無法預期的結果。對的的寫法:publicclassCycle{privatefinalintbalance;privatestaticfinalintdeposit=(int)(Math.random()*100);//RandomdepositprivatestaticfinalCyclec=newCycle();//InsertedafterinitializationofrequiredfieldspublicCycle(){balance=deposit-10;//Subtractprocessingfee}publicstaticvoidmain(String[]args){System.out.println("Theaccountbalanceis:"+c.balance);}}表達式不可忽略方法的返回值忽略方法的放回值也許會導致無法預料的結果。錯誤的寫法:publicvoiddeleteFile(){FilesomeFile=newFile("someFileName.txt");someFile.delete();}對的的寫法:publicvoiddeleteFile(){FilesomeFile=newFile("someFileName.txt");if(!someFile.delete()){//handlefailuretodeletethefile}}不要引用空指針當一個變量指向一個NULL值,使用這個變量的時候又沒有檢查,這時會導致。NullPointerException。在使用變量前一定要做是否為NULL值的校驗。使用Arrays.equals()來比較數(shù)組的內(nèi)容數(shù)組沒有覆蓋的Object.equals()方法,調用Object.equals()方法事實上是比較數(shù)組的引用,而不是他們的內(nèi)容。程序必須使用兩個參數(shù)Arrays.equals()方法來比較兩個數(shù)組的內(nèi)容publicvoidarrayEqualsExample(){int[]arr1=newint[20];//initializedto0int[]arr2=newint[20];//initializedto0Arrays.equals(arr1,arr2);//true}數(shù)字類型和操作防止整數(shù)溢出使用\o"java.lang中的類"java.lang.Number.BigInteger類進行整數(shù)運算,防止整數(shù)溢出。publicclassBigIntegerUtil{privatestaticfinalBigIntegerbigMaxInt=BigInteger.valueOf(Integer.MAX_VALUE);privatestaticfinalBigIntegerbigMinInt=BigInteger.valueOf(Integer.MIN_VALUE);publicstaticBigIntegerintRangeCheck(BigIntegerval)throwsArithmeticException{if(pareTo(bigMaxInt)==1||pareTo(bigMinInt)==-1){thrownewArithmeticException("Integeroverflow");}returnval;}publicstaticintaddInt(intv1,intv2)throwsArithmeticException{BigIntegerb1=BigInteger.valueOf(v1);BigIntegerb2=BigInteger.valueOf(v2);BigIntegerres=intRangeCheck(b1.add(b2));returnValue();}publicstaticintsubInt(intv1,intv2)throwsArithmeticException{BigIntegerb1=BigInteger.valueOf(v1);BigIntegerb2=BigInteger.valueOf(v2);BigIntegerres=intRangeCheck(b1.subtract(b2));returnValue();}publicstaticintmultiplyInt(intv1,intv2)throwsArithmeticException{BigIntegerb1=BigInteger.valueOf(v1);BigIntegerb2=BigInteger.valueOf(v2);BigIntegerres=intRangeCheck(b1.multiply(b2));returnValue();}publicstaticintdivideInt(intv1,intv2)throwsArithmeticException{BigIntegerb1=BigInteger.valueOf(v1);BigIntegerb2=BigInteger.valueOf(v2);BigIntegerres=intRangeCheck(b1.divide(b2));returnValue();}}避免去法和取模運算分母為零要避免由于分母為零而導致除法和取模運算出現(xiàn)異常。if(num2==0){//handleerror}else{result1=num1/num2;result2=num1%num2;}類和方法操作數(shù)據(jù)成員聲明為私有,提供可訪問的包裝方法襲擊者可以用意想不到的方式操縱public或protected的數(shù)據(jù)成員,所以需要將數(shù)據(jù)成員為private,對外提供可控的包裝方法訪問數(shù)據(jù)成員。敏感類不允許復制包含私人的,機密或其他敏感數(shù)據(jù)的類是不允許被復制的,解決的方法有兩種:類聲明為finalfinalclassSensitiveClass{//...}Clone方法拋出CloneNotSupportedException異常classSensitiveClass{//...publicfinalSensitiveClassclone()throwsCloneNotSupportedException{thrownewCloneNotSupportedException();}}比較類的對的做法假如由同一個類裝載器裝載,它們具有相同的完全限定名稱,則它們是兩個相同的類。不對的寫法://Determinewhetherobjectauthhasrequired/expectedclassobjectif(auth.getClass().getName().equals("com.application.auth.DefaultAuthenticationHandler")){//...}對的寫法://Determinewhetherobjectauthhasrequired/expectedclassnameif(auth.getClass()==com.application.auth.DefaultAuthenticationHandler.class){//...}不要硬編碼敏感信息硬編碼的敏感信息,如密碼,服務器IP地址和加密密鑰,也許會泄露給襲擊者。敏感信息均必須存在在配置文獻或數(shù)據(jù)庫中。驗證方法參數(shù)驗證方法的參數(shù),可保證操作方法的參數(shù)產(chǎn)生有效的結果。不驗證方法的參數(shù)也許會導致不對的的計算,運營時異常,違反類的不變量,對象的狀態(tài)不一致。對于跨信任邊界接受參數(shù)的方法,必須進行參數(shù)合法性校驗privateObjectmyState=null;//對于修改myState方法的入?yún)ⅲM行非空和合法性校驗voidsetState(Objectstate){

if(state==null){

//Handlenullstate

}

if(isInvalidState(state)){

//Handleinvalidstate

}

myState=state;}不要使用過時、陳舊或低效的方法在程序代碼中使用過時的、陳舊的或低效的類或方法也許會導致錯誤的行為。數(shù)組引用問題某個方法返回一個對敏感對象的內(nèi)部數(shù)組的引用,假定該方法的調用程序不改變這些對象。即使數(shù)組對象自身是不可改變的,也可以在數(shù)組對象以外操作數(shù)組的內(nèi)容,這種操作將反映在返回該數(shù)組的對象中。假如該方法返回可改變的對象,外部實體可以改變在那個類中聲明的public變量,這種改變將反映在實際對象中。不對的的寫法:publicclassXXX{ privateString[]xxxx; publicString[]getXXX(){ returnxxxx; }}對的的寫法:publicclassXXX{ privateString[]xxxx; publicString[]getXXX(){ Stringtemp[]=Arrays.copyof(…);//或其他數(shù)組復制方法 returntemp; }}不要產(chǎn)生內(nèi)存泄露垃圾收集器只收集不可達的對象,因此,存在未使用的可到達的對象,仍然表達內(nèi)存管理不善。過度的內(nèi)存泄漏也許會導致內(nèi)存耗盡,拒絕服務(DoS)。異常解決不要忽略捕獲的異常對于捕獲的異常要進行相應的解決,不能忽略已捕獲的異常不對的寫法:classFooimplementsRunnable{publicvoidrun(){try{Thread.sleep(1000);}catch(InterruptedExceptione){//此處InterruptedException被忽略}}}對的寫法:classFooimplementsRunnable{publicvoidrun(){try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();//Resetinterruptedstatus}}}不允許暴露異常的敏感信息沒有過濾敏感信息的異常堆棧往往會導致信息泄漏,不對的的寫法:try{FileInputStreamfis=newFileInputStream(System.getenv("APPDATA")+args[0]);}catch(FileNotFoundExceptione){//LogtheexceptionthrownewIOException("Unabletoretrievefile",e);}對的的寫法:classExceptionExample{publicstaticvoidmain(String[]args){Filefile=null;try{file=newFile(System.getenv("APPDATA")+args[0]).getCanonicalFile();if(!file.getPath().startsWith("c:\\homepath")){log.error("Invalidfile");return;}}catch(IOExceptionx){log.error("Invalidfile");return;}try{FileInputStreamfis=newFileInputStream(file);}catch(FileNotFoundExceptionx){log.error("Invalidfile");return;}}}不允許拋出RuntimeException,Exception,Throwable不對的的寫法:booleanisCapitalized(Strings){if(s==null){thrownewRuntimeException("NullString");}}privatevoiddoSomething()throwsException{//...}對的寫法:booleanisCapitalized(Strings){if(s==null){thrownewNullPointerException();}}privatevoiddoSomething()throwsIOException{//...}不要捕獲NullPointerException或其他父類異常不對的的寫法:booleanisName(Strings){try{Stringnames[]=s.split("");if(names.length!=2){returnfalse;}return(isCapitalized(names[0])&&isCapitalized(names[1]));}catch(NullPointerExceptione){returnfalse;}}對的的寫法:booleanisName(Strings)/*throwsNullPointerException*/{Stringnames[]=s.split("");if(names.length!=2){returnfalse;}return(isCapitalized(names[0])&&isCapitalized(names[1]));}多線程編程保證共享變量的可見性對于共享變量,要保證一個線程對它的改動對其他線程是可見的。線程也許會看到一個陳舊的共享變量的值。為了共享變量是最新的,可以將變量聲明為volatile或同步讀取和寫入操作。將共享變量聲明為volatile:finalclassControlledStopimplementsRunnable{privatevolatilebooleandone=false;@Overridepublicvoidrun(){while(!done){try{//...Thread.currentThread().sleep(1000);//Dosomething}catch(InterruptedExceptionie){Thread.currentThread().interrupt();//Resetinterruptedstatus}}}publicvoidshutdown(){done=true;}}同步讀取和寫入操作:finalclassControlledStopimplementsRunnable{privatebooleandone=false;@Overridepublicvoidrun(){while(!isDone()){try{//...Thread.currentThread().sleep(1000);//Dosomething}catch(InterruptedExceptionie){Thread.currentThread().interrupt();//Resetinterruptedstatus}}}publicsynchronizedbooleanisDone(){returndone;}publicsynchronizedvoidshutdown(){done=true;}}保證共享變量的操作是原子的除了要保證共享變量的更新對其他線程可見的,還需要保證對共享變量的操作是原子的,這時將共享變量聲明為volatile往往是不夠的。需要使用同步機制或Lock同步讀取和寫入操作:finalclassFlag{privatevolatilebooleanflag=true;publicsynchronizedvoidtoggle(){flag^=true;//Sameasflag=!flag;}publicbooleangetFlag(){returnflag;}}//使用讀取鎖保證讀取和寫入操作的原子性finalclassFlag{privatebooleanflag=true;privatefinalReadWriteLocklock=newReentrantReadWriteLock();privatefinalLockreadLock=lock.readLock();privatefinalLockwriteLock=lock.writeLock();publicvoidtoggle(){writeLock.lock();try{flag^=true;//Sameasflag=!flag;}finally{writeLock.unlock();}}publicbooleangetFlag(){readLock.lock();try{returnflag;}finally{readLock.unlock();}}}不要調用Thread.run(),不要使用Thread.stop()以終止線程保證執(zhí)行阻塞操作的線程可以終止publicfinalclassSocketReaderimplementsRunnable{privatefinalSocketChannelsc;privatefinalObjectlock=newObject();publicSocketReader(Stringhost,intport)throwsIOException{sc=SocketChannel.open(newInetSocketAddress(host,port));}@Overridepublicvoidrun(){ByteBufferbuf=ByteBuffer.allocate(1024);try{synchronized(lock){while(!Terrupted()){sc.read(buf);//...}}}catch(IOExceptionie){//Forwardtohandler}}publicstaticvoidmain(String[]args)throwsIOException,InterruptedException{SocketReaderreader=newSocketReader("somehost",25);Threadthread=newThread(reader);thread.start();Thread.sleep(1000);errupt();}}互相依存的任務不要在一個有限的線程池執(zhí)行有限線程池指定可以同時執(zhí)行在線程池中的線程數(shù)量的上限。程序不得使用有限線程池線程執(zhí)行互相依賴的任務。也許會導致線程饑餓死鎖,所有的線程池執(zhí)行的任務正在等待一個可用的線程中執(zhí)行一個內(nèi)部隊列阻塞輸入輸出程序終止前刪除臨時文獻檢測和解決文獻相關的錯誤Java的文獻操作方法往往有一個返回值,而不是拋出一個異常,表達失敗。因此,忽略返回值文獻操作的程序,往往無法檢測到這些操作是否失敗。Java程序必須檢查執(zhí)行文獻I/O方法的返回值。不對的的寫法:Filefile=newFile(args[0]);file.delete();對的的寫法:Filefile=newFile("file");if(!file.delete()){log.error("Deletionfailed");}及時釋放資源垃圾收集器無法釋放非內(nèi)存資源,如打開的文獻描述符與數(shù)據(jù)庫的連接。因此,不釋放資源,也許導致資源耗盡襲擊。try{finalFileInputStreamstream=newFileInputStream(fileName);try{finalBufferedReaderbufRead=newBufferedReader(newInputStreamReader(stream));Stringline;while((line=bufRead.readLine())!=null){sendLine(line);}}finally{if(stream!=null){try{stream.close();}catch(IOExceptione){//forwardtohandler}}}}catch(IOExceptione){//forwardtohandler}序列化不要序列化未加密的敏感數(shù)據(jù)序列化允許一個對象的狀態(tài)被保存為一個字節(jié)序列,然后重新在稍后的時間恢復,它沒有提供任何機制來保護序列化的數(shù)據(jù)。敏感的數(shù)據(jù)不應當被序列化的例子涉及加密密鑰,數(shù)字證書。解決方法:對于數(shù)據(jù)成員可以使用transient,聲明該數(shù)據(jù)成員是瞬態(tài)的。重寫序列化相關方法writeObject、readObject、readObjectNoData,防止被子類惡意重寫classSensitiveClassextendsNumber{//...protectedfinalObjectwriteObject(java.io.ObjectOutputStreamout)throwsNotSerializableException{thrownewNotSerializableException();}protectedfinalObjectreadObject(java.io.ObjectInputStreamin)throwsNotSeriali

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
  • 4. 未經(jīng)權益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
  • 6. 下載文件中如有侵權或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論