java安全編碼規范_第1頁
java安全編碼規范_第2頁
java安全編碼規范_第3頁
java安全編碼規范_第4頁
java安全編碼規范_第5頁
已閱讀5頁,還剩83頁未讀 繼續免費閱讀

下載本文檔

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

文檔簡介

安全開發-java安全編碼規范申明:本文非筆者原創,原文轉載自:/SecurityPaper/SecurityPaper-web/blob/master/_posts/2.SDL%E8%A7%84%E8%8C%83%E6%96%87%E6%A1%A3/2018-08-17-SDL-3-java%E5%AE%89%E5%85%A8%E7%BC%96%E7%A0%81%E8%A7%84%E8%8C%83.md

1輸入驗證和數據合法性校驗程序接受數據可能來源于未經驗證的用戶,網絡連接和其他不受信任的來源,如果未對程序接受數據進行校驗,則可能會引發安全問題。1.1避免SQL注入使用PreparedStatement預編譯SQL,解決SQL注入問題,傳遞給PreparedStatement對象的參數可以被強制進行類型轉換,確保在插入或查詢數據時與底層的數據庫格式匹配。

StringsqlString="select*fromdb_userwhereusername=?andpassword=?";PreparedStatementstmt=connection.prepareStatement(sqlString);stmt.setString(1,username);stmt.setString(2,pwd);ResultSetrs=stmt.executeQuery();1.2避免XML注入通過StringBulider或StringBuffer拼接XML文件時,需對輸入數據進行合法性校驗。對數量quantity進行合法性校驗,控制只能傳入0-9的數字: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();1.3避免跨站點腳本(XSS)對產生跨站的參數進行嚴格過濾,禁止傳入<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{//...}2聲明和初始化2.1避免類初始化的相互依賴例:錯誤的寫法:publicclassCycle{privatefinalintbalance;privatestaticfinalCyclec=newCycle();privatestaticfinalintdeposit=(int)(Math.random()*100);//RandomdepositpublicCycle(){balance=deposit-10;//Subtractprocessingfee}publicstaticvoidmain(String[]args){System.out.println("Theaccountbalanceis:"+c.balance);}}類加載時初始化指向Cycle類的靜態變量c,而類Cycle的無參構造方法又依賴靜態變量deposit,導致無法預期的結果。正確的寫法:publicclassCycle{privatefinalintbalance;privatestaticfinalintdeposit=(int)(Math.random()*100);//RandomdepositprivatestaticfinalCyclec=newCycle();//InsertedafterinitializationofrequiredfieldspublicCycle(){balance=deposit-10;//Subtractprocessingfee}publicstaticvoidmain(String[]args){System.out.println("Theaccountbalanceis:"+c.balance);}}3表達式3.1不可忽略方法的返回值忽略方法的放回值可能會導致無法預料的結果。錯誤的寫法:publicvoiddeleteFile(){FilesomeFile=newFile("someFileName.txt");someFile.delete();}正確的寫法:publicvoiddeleteFile(){FilesomeFile=newFile("someFileName.txt");if(!someFile.delete()){//handlefailuretodeletethefile}}3.2不要引用空指針當一個變量指向一個NULL值,使用這個變量的時候又沒有檢查,這時會導致。NullPointerException。在使用變量前一定要做是否為NULL值的校驗。3.3使用Arrays.equals()來比較數組的內容數組沒有覆蓋的Object.equals()方法,調用Object.equals()方法實際上是比較數組的引用,而不是他們的內容。程序必須使用兩個參數Arrays.equals()方法來比較兩個數組的內容publicvoidarrayEqualsExample(){int[]arr1=newint[20];//initializedto0int[]arr2=newint[20];//initializedto0Arrays.equals(arr1,arr2);//true}4數字類型和操作4.1防止整數溢出使用java.lang.Number.BigInteger類進行整數運算,防止整數溢出。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();}}4.2避免除法和取模運算分母為零要避免因為分母為零而導致除法和取模運算出現異常。if(num2==0){//handleerror}else{result1=num1/num2;result2=num1%num2;}5類和方法操作5.1數據成員聲明為私有,提供可訪問的包裝方法攻擊者可以用意想不到的方式操縱public或protected的數據成員,所以需要將數據成員為private,對外提供可控的包裝方法訪問數據成員。5.2敏感類不允許復制包含私人的,機密或其他敏感數據的類是不允許被復制的,解決的方法有兩種:1、類聲明為finalfinalclassSensitiveClass{//...}2、Clone方法拋出CloneNotSupportedException異常classSensitiveClass{//...publicfinalSensitiveClassclone()throwsCloneNotSupportedException{thrownewCloneNotSupportedException();}}5.3比較類的正確做法如果由同一個類裝載器裝載,它們具有相同的完全限定名稱,則它們是兩個相同的類。不正確寫法://Determinewhetherobjectauthhasrequired/expectedclassobjectif(auth.getClass().getName().equals("com.application.auth.DefaultAuthenticationHandler")){//...}正確寫法://Determinewhetherobjectauthhasrequired/expectedclassnameif(auth.getClass()==com.application.auth.DefaultAuthenticationHandler.class){//...}5.4不要硬編碼敏感信息硬編碼的敏感信息,如密碼,服務器IP地址和加密密鑰,可能會泄露給攻擊者。敏感信息均必須存在在配置文件或數據庫中。5.5驗證方法參數驗證方法的參數,可確保操作方法的參數產生有效的結果。不驗證方法的參數可能會導致不正確的計算,運行時異常,違反類的不變量,對象的狀態不一致。對于跨信任邊界接收參數的方法,必須進行參數合法性校驗privateObjectmyState=null;//對于修改myState方法的入參,進行非空和合法性校驗voidsetState(Objectstate){

if(state==null){

//Handlenullstate

}

if(isInvalidState(state)){

//Handleinvalidstate

}

myState=state;}5.6不要使用過時、陳舊或低效的方法在程序代碼中使用過時的、陳舊的或低效的類或方法可能會導致錯誤的行為。5.7數組引用問題某個方法返回一個對敏感對象的內部數組的引用,假定該方法的調用程序不改變這些對象。即使數組對象本身是不可改變的,也可以在數組對象以外操作數組的內容,這種操作將反映在返回該數組的對象中。如果該方法返回可改變的對象,外部實體可以改變在那個類中聲明的public變量,這種改變將反映在實際對象中。不正確的寫法:publicclassXXX{ privateString[]xxxx; publicString[]getXXX(){ returnxxxx; }}正確的寫法:publicclassXXX{ privateString[]xxxx; publicString[]getXXX(){ Stringtemp[]=Arrays.copyof(…);//或其他數組復制方法 returntemp; }}5.8不要產生內存泄露垃圾收集器只收集不可達的對象,因此,存在未使用的可到達的對象,仍然表示內存管理不善。過度的內存泄漏可能會導致內存耗盡,拒絕服務(DoS)。6異常處理6.1不要忽略捕獲的異常對于捕獲的異常要進行相應的處理,不能忽略已捕獲的異常不正確寫法:classFooimplementsRunnable{publicvoidrun(){try{Thread.sleep(1000);}catch(InterruptedExceptione){//此處InterruptedException被忽略}}}正確寫法:classFooimplementsRunnable{publicvoidrun(){try{Thread.sleep(1000);}catch(InterruptedExceptione){Thread.currentThread().interrupt();//Resetinterruptedstatus}}}6.2不允許暴露異常的敏感信息沒有過濾敏感信息的異常堆棧往往會導致信息泄漏,不正確的寫法: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;}}}6.3不允許拋出RuntimeException,Exception,Throwable不正確的寫法:booleanisCapitalized(Strings){if(s==null){thrownewRuntimeException("NullString");}}privatevoiddoSomething()throwsException{//...}正確寫法:booleanisCapitalized(Strings){if(s==null){thrownewNullPointerException();}}privatevoiddoSomething()throwsIOException{//...}6.4不要捕獲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]));}7多線程編程7.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;}}7.2確保共享變量的操作是原子的除了要確保共享變量的更新對其他線程可見的,還需要確保對共享變量的操作是原子的,這時將共享變量聲明為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();}}}7.3不要調用Thread.run(),不要使用Thread.stop()以終止線程7.4確保執行阻塞操作的線程可以終止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();}}7.5相互依存的任務不要在一個有限的線程池執行有限線程池指定可以同時執行在線程池中的線程數量的上限。程序不得使用有限線程池線程執行相互依賴的任務。可能會導致線程饑餓死鎖,所有的線程池執行的任務正在等待一個可用的線程中執行一個內部隊列阻塞8輸入輸出8.1程序終止前刪除臨時文件8.2檢測和處理文件相關的錯誤Java的文件操作方法往往有一個返回值,而不是拋出一個異常,表示失敗。因此,忽略返回值文件操作的程序,往往無法檢測到這些操作是否失敗。Java程序必須檢查執行文件I/O方法的返回值。不正確的寫法:Filefile=newFile(args[0]);file.delete();正確的寫法:Filefile=newFile("file");if(!file.delete()){log.error("Deletionfailed");}8.3及時釋放資源垃圾收集器無法釋放非內存資源,如打開的文件描述符與數據庫的連接。因此,不釋放資源,可能導致資源耗盡攻擊。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}9序列化9.1不要序列化未加密的敏感數據序列化允許一個對象的狀態被保存為一個字節序列,然后重新在稍后的時間恢復,它沒有提供任何機制來保護序列化的數據。敏感的數據不應該被序列化的例子包括加密密鑰,數字證書。解決方法:對于數據成員可以使用transient,聲明該數據成員是瞬態的。重寫序列化相關方法writeObject、readObject、readObjectNoData,防止被子類惡意重寫classSensitiveClassextendsNumber{//...protectedfinalObjectwriteObject(java.io.ObjectOutputStreamout)throwsNotSerializableException{thrownewNotSerializableException();}protectedfinalObjectreadObject(java.io.ObjectInputStreamin)throwsNotSerializableException{thrownewNotSerializableException();}protectedfinalObjectreadObjectNoData(java.io.ObjectInputStreamin)throwsNotSerializableException{thrownewNotSerializableException();}}9.2在序列化過程中避免內存和資源泄漏不正確的寫法:classSensorDataimplementsSerializable{//1MBofdataperinstance!publicstaticSensorDatareadSensorData(){...}publicstaticbooleanisAvailable(){...}}classSerializeSensorData{publicstaticvoidmain(String[]args)throwsIOException{ObjectOutputStreamout=null;try{out=newObjectOutputStream(newBufferedOutputStream(newFileOutputStream("ser.dat")));while(SensorData.isAvailable()){//notethateachSensorDataobjectis1MBinsizeSensorDatasd=SensorData.readSensorData();out.writeObject(sd);}}finally{if(out!=null){out.close();}}}}正確寫法:classSerializeSensorData{publicstaticvoidmain(String[]args)throwsIOException{ObjectOutputStreamout=null;try{out=newObjectOutputStream(newBufferedOutputStream(newFileOutputStream("ser.dat")));while(SensorData.isAvailable()){//notethateachSensorDataobjectis1MBinsizeSensorDatasd=SensorData.readSensorData();out.writeObject(sd);out.reset();//resetthestream}}finally{if(out!=null){out.close();}}}}9.3反序列化要在程序最小權限的安全環境中(完成)JAVA安全編碼規范\t"/weixin_39997829/article/details/_blank"安全小哥

2021-11-1017:04:21

100

收藏

1分類專欄:

\t"/weixin_39997829/article/details/_blank"JAVA代碼審計

文章標簽:

\t"/weixin_39997829/article/details/_blank"java

\t"/weixin_39997829/article/details/_blank"安全

\t"/weixin_39997829/article/details/_blank"開發語言版權\o"JAVA代碼審計"\t"/weixin_39997829/article/details/_blank"JAVA代碼審計專欄收錄該內容19篇文章8訂閱訂閱專欄Java安全編碼規范-1.0.6byk4n5ha0\o"Java安全編碼規范-1.0.6byk4n5ha0"Java安全編碼規范-1.0.6byk4n5ha0\o"編寫依據與參考文件:"編寫依據與參考文件:\o"1.《信息安全技術應用軟件安全編程指南》(國標GBT38674-2020)"1.《信息安全技術應用軟件安全編程指南》(國標GBT38674-2020)\o"2.《CommonWeaknessEnumeration》-國際通用計算機軟件缺陷字典"2.《CommonWeaknessEnumeration》-國際通用計算機軟件缺陷字典\o"3.《OWASPTop102017》-2017年十大Web應用程序安全風險"3.《OWASPTop102017》-2017年十大Web應用程序安全風險\o"4.《fortify-代碼審計規則》"4.《fortify-代碼審計規則》\o"5.《java開發手冊》(阿里巴巴出品)"5.《java開發手冊》(阿里巴巴出品)\o"第一條設計開發必須符合概要設計及安全防護方案"第一條設計開發必須符合概要設計及安全防護方案\o"項目管理要求↓:"項目管理要求↓:\o"第二條上線代碼必須進行嚴格的安全測試并進行軟著備案"第二條上線代碼必須進行嚴格的安全測試并進行軟著備案\o"項目管理要求↓:"項目管理要求↓:\o"第三條嚴格限制帳號訪問權限"第三條嚴格限制帳號訪問權限\o"程序設計要求↓:"程序設計要求↓:\o"第四條提供完備的安全審計功能"第四條提供完備的安全審計功能\o"程序設計要求↓:"程序設計要求↓:\o"第五條采取有效措施保證認證安全"第五條采取有效措施保證認證安全\o"程序設計要求↓:"程序設計要求↓:\o"第六條保證代碼簡潔、注釋明確"第六條保證代碼簡潔、注釋明確\o"安全編碼要求↓:"安全編碼要求↓:\o"第七條使用安全函數和安全規范驗證所有外部輸入"第七條使用安全函數和安全規范驗證所有外部輸入\o"安全編碼要求↓:"安全編碼要求↓:\o"HTTP參數污染"HTTP參數污染\o"不受信任的查詢字符串"不受信任的查詢字符串\o"不受信任的HTTP請求頭"不受信任的HTTP請求頭\o"1.不受信任的Cookie頭"1.不受信任的Cookie頭\o"2.不受信任的Content-Type請求頭"2.不受信任的Content-Type請求頭\o"3.不受信任的HOST請求頭"3.不受信任的HOST請求頭\o"4.不受信任的User-Agent請求頭"4.不受信任的User-Agent請求頭\o"5.不受信任的IP請求頭"5.不受信任的IP請求頭\o"缺少CSRF攻擊的防護"缺少CSRF攻擊的防護\o"客戶端請求偽造"客戶端請求偽造\o"服務端請求偽造"服務端請求偽造\o"惡意的命令注入"惡意的命令注入\o"不安全的反序列化"不安全的反序列化\o"1.配置全局反序列化白名單"1.配置全局反序列化白名單\o"2.jackson安全反序列化編碼示例"2.jackson安全反序列化編碼示例\o"3.fastjson安全反序列化編碼示例"3.fastjson安全反序列化編碼示例\o"4.XStream安全反序列化編碼示例"4.XStream安全反序列化編碼示例\o"5.shiro安全反序列化編碼示例"5.shiro安全反序列化編碼示例\o"XML外部實體(XXE)攻擊"XML外部實體(XXE)攻擊\o"1.XStream"1.XStream\o"2.javax.xml.parsers.DocumentBuilderFactory"2.javax.xml.parsers.DocumentBuilderFactory\o"3.org.jdom2.input.SAXBuilder"3.org.jdom2.input.SAXBuilder\o"4.javax.xml.parsers.SAXParserFactory"4.javax.xml.parsers.SAXParserFactory\o"5.org.dom4j.io.SAXReader"5.org.dom4j.io.SAXReader\o"6.org.xml.sax.XMLReader"6.org.xml.sax.XMLReader\o"7.javax.xml.transform.sax.SAXTransformerFactory"7.javax.xml.transform.sax.SAXTransformerFactory\o"8.javax.xml.validation.SchemaFactory"8.javax.xml.validation.SchemaFactory\o"9.javax.xml.transform.TransformerFactory"9.javax.xml.transform.TransformerFactory\o"XPath注入"XPath注入\o"EL表達式引擎代碼注入"EL表達式引擎代碼注入\o"JS腳本引擎代碼注入"JS腳本引擎代碼注入\o"JavaBeans屬性注入"JavaBeans屬性注入\o"不安全的對象綁定"不安全的對象綁定\o"正則表達式DOS(ReDOS)"正則表達式DOS(ReDOS)\o"跨站腳本攻擊(XSS)"跨站腳本攻擊(XSS)\o"第八條必須過濾上傳文件"第八條必須過濾上傳文件\o"安全編碼要求↓:"安全編碼要求↓:\o"潛在的路徑遍歷(讀取文件)"潛在的路徑遍歷(讀取文件)\o"潛在的路徑遍歷(寫入文件)"潛在的路徑遍歷(寫入文件)\o"第九條確保多線程編程的安全性"第九條確保多線程編程的安全性\o"安全編碼要求↓:"安全編碼要求↓:\o"競爭條件"競爭條件\o"第十條設計錯誤、異常處理機制"第十條設計錯誤、異常處理機制\o"安全編碼要求↓:"安全編碼要求↓:\o"第十一條數據庫操作使用參數化請求方式"第十一條數據庫操作使用參數化請求方式\o"安全編碼要求↓:"安全編碼要求↓:\o"SQL注入"SQL注入\o"1.jdbc安全編碼規范"1.jdbc安全編碼規范\o"2.Mybatis安全編碼規范"2.Mybatis安全編碼規范\o"LDAP注入"LDAP注入\o"第十二條禁止在源代碼中寫入口令、服務器IP等敏感信息"第十二條禁止在源代碼中寫入口令、服務器IP等敏感信息\o"安全編碼要求↓:"安全編碼要求↓:\o"硬編碼密碼"硬編碼密碼\o"硬編碼密鑰"硬編碼密鑰\o"第十三條為所有敏感信息采用加密傳輸"第十三條為所有敏感信息采用加密傳輸\o"程序設計要求↓:"程序設計要求↓:\o"名稱類信息脫敏規則:"名稱類信息脫敏規則:\o"聯系類信息脫敏規則:"聯系類信息脫敏規則:\o"證件號脫敏規則:"證件號脫敏規則:\o"安全編碼要求↓:"安全編碼要求↓:\o"接受任何證書的TrustManager"接受任何證書的TrustManager\o"接受任何簽名證書的HostnameVerifier"接受任何簽名證書的HostnameVerifier\o"第十四條使用可信的密碼算法"第十四條使用可信的密碼算法\o"程序設計要求↓:"程序設計要求↓:\o"禁止使用弱加密"禁止使用弱加密\o"安全編碼要求↓:"安全編碼要求↓:\o"可預測的偽隨機數生成器"可預測的偽隨機數生成器\o"錯誤的十六進制串聯"錯誤的十六進制串聯\o"第十五條禁止在日志、表單、cookie等文件中記錄口令、銀行賬號、通信內容等敏感數據"第十五條禁止在日志、表單、cookie等文件中記錄口令、銀行賬號、通信內容等敏感數據\o"安全編碼要求↓:"安全編碼要求↓:\o"Cookie中的潛在敏感數據"Cookie中的潛在敏感數據\o"日志偽造"日志偽造\o"HTTP響應截斷"HTTP響應截斷\o"第十六條禁止高風險的服務及協議"第十六條禁止高風險的服務及協議\o"程序設計要求↓:"程序設計要求↓:\o"安全編碼要求↓:"安全編碼要求↓:\o"不安全的HTTP動詞"不安全的HTTP動詞\o"第十七條避免異常信息泄漏"第十七條避免異常信息泄漏\o"安全編碼要求↓:"安全編碼要求↓:\o"意外的屬性泄露"意外的屬性泄露\o"不安全的SpringBootActuator暴露"不安全的SpringBootActuator暴露\o"不安全的Swagger暴露"不安全的Swagger暴露\o"第十八條嚴格會話管理"第十八條嚴格會話管理\o"安全編碼要求↓:"安全編碼要求↓:\o"缺少HttpOnly標志的Cookie"缺少HttpOnly標志的Cookie\o"不安全的CORS策略"不安全的CORS策略\o"不安全的永久性Cookie"不安全的永久性Cookie\o"不安全的廣播(Android)"不安全的廣播(Android)編寫依據與參考文件:1.《信息安全技術應用軟件安全編程指南》(國標GBT38674-2020)2.《CommonWeaknessEnumeration》-國際通用計算機軟件缺陷字典3.《OWASPTop102017》-2017年十大Web應用程序安全風險4.《fortify-代碼審計規則》5.《java開發手冊》(阿里巴巴出品)第一條設計開發必須符合概要設計及安全防護方案項目管理要求↓:所有項目必須參照《概要設計》編寫《安全防護方案》,兩者均評審通過后才能啟動編碼工作。java8版本應不低于jdk-1.8_291java11版本應不低于jdk-11.0.11第二條上線代碼必須進行嚴格的安全測試并進行軟著備案項目管理要求↓:所有項目必須完成安全自測和第三方安全測試,并完成軟著相關工作才能上線運行,上線運行版本必須與測試通過版本一致。第三條嚴格限制帳號訪問權限程序設計要求↓:應用程序除公共功能外,禁止不同角色之間可以跨角色訪問其他角色的功能。例如:某互斥業務名為“發票打印”涉及三個子菜單,該業務是角色“會計”的專有功能。角色“會計”可以看到發票打印相關的三個子菜單并正常操作。角色“出納”無法看到三個子菜單并無法訪問該三個子菜單中對應的所有后端接口。如果“出納”可以訪問或操作“會計”的“發票打印”或其他“會計”專有的功能則應判定為越權。當用戶訪問無權限的菜單url或者接口url:后臺的HTTP響應碼禁止返回200。HTTP的響應包body內容必須返回“無權限”。原則禁止存在“記住密碼”的功能。第四條提供完備的安全審計功能程序設計要求↓:用戶在系統中只要在頁面中存在點擊、輸入、拖拽等操作行為,日志記錄中應當針對操作行為產生日志。一條日志所包含的字段應包括:事件的日期(年月日)時間(時分秒)事件類型(系統級、業務級二選一)登錄ID姓名IP地址事件描述(用戶主體對什么客體執行了什么操作?該操作的增刪改查的內容又是什么?)事件結果(成功、失敗)第五條采取有效措施保證認證安全程序設計要求↓:如果用戶連續登錄失敗(最多失敗10次),應將該用戶鎖定,禁止其登陸。外網系統用戶登錄時,應使用短信進行二次驗證可以保證用戶登錄的安全性。用戶登錄失敗時,應提示“用戶名或口令錯誤”,禁止提示“用戶名不存在”或“登錄口令錯誤”。用戶登錄時,必須使用合規的加密方案加密傳輸用戶的登錄名和密碼。合規的雙向加密數據的傳輸方案:1)后端生成非對稱算法(國密SM2、RSA2048)的公鑰B1、私鑰B2,前端訪問后端獲取公鑰B1。2)前端每次發送請求前,隨機生成對稱算法(國密SM4、AES256)的密鑰A1。3)公鑰、私鑰可以全系統固定為一對,前端可以儲存公鑰,但私鑰不能保存在后端數據庫中。4)前端用步驟2的密鑰A1加密所有業務數據生成encrypt_data,用步驟1獲取的公鑰B1加密密鑰A1生成encrypt_key。5)前端用哈希算法對encrypt_data+encrypt_key的值形成一個校驗值check_hash。6)前端將encrypt_data、encrypt_key、check_hash三個參數包裝在同一個http數據包中發送到后端。7)后端獲取三個參數后先判斷哈希值check_hash是否匹配encrypt_data+encrypt_key以驗證完整性。8)后端用私鑰B2解密encrypt_key獲取本次請求的對稱算法的密鑰A1。9)后端使用步驟8獲取的密鑰A1解密encrypt_data獲取實際業務數據。10)后端處理完業務邏輯后,將需要返回的信息使用密鑰A1進行加密后回傳給前端。11)加密數據回傳給前端后,前端使用A1對加密的數據進行解密獲得返回的信息。12)步驟2隨機生成的密鑰A1已經使用完畢,前端應將其銷毀。前端發送請求時必須設計防篡改和防重放攻擊的安全邏輯,后端必須開展對應的校驗。合規的防篡改和防重放攻擊的傳輸方案:1)客戶端獲取公鑰時應同時獲取后端服務器時間,保證客戶端和服務器時間一致。2)前端每次發送請求前,應在header請求頭中添加時間戳字段。3)通過url+時間戳+用戶token+http請求體(可以為空)產生sign簽名。4)將sign簽名添加到header請求頭中后發送請求。5)后端校驗sign簽名是否正確,如果簽名校驗不通過應提示"數據被篡改"并丟棄當前請求。6)如果時間戳的時間和服務器時間相差大于10秒,應丟棄當前請求。7)后臺應緩存每一個sign值10秒,在10秒內如果出現包含同一個sign值的請求,應丟棄當前請求。8)用戶token中部分數據(禁止全部)應存儲在sessionStorage中,以保證頁面關閉后登錄失效。第六條保證代碼簡潔、注釋明確安全編碼要求↓:應持續執行代碼審計工作。代碼中禁止出現goto語句。應禁止使用遞歸并及時去除程序中冗余的功能代碼。第七條使用安全函數和安全規范驗證所有外部輸入安全編碼要求↓:HTTP參數污染如果應用程序未正確校驗用戶輸入的數據,則惡意用戶可能會破壞應用程序的邏輯以執行針對客戶端或服務器端的攻擊。脆弱代碼1://攻擊者可以提交lang的內容為://en&user_id=1#//致使攻擊者可以隨意篡改user_id的值Stringlang=request.getParameter("lang");GetMethodget=newGetMethod("");//攻擊者提交lang=en&user_id=1#&user_id=123可覆蓋原始user_id的值get.setQueryString("lang="+lang+"&user_id="+user_id);get.execute();解決方案1://參數化綁定URIBuilderuriBuilder=newURIBuilder("/viewDetails");uriBuilder.addParameter("lang",input);uriBuilder.addParameter("user_id",userId);HttpGethttpget=newHttpGet(uriBuilder.build().toString());脆弱邏輯2:訂單系統計算訂單的價格步驟1:訂單總價=商品1單價*商品1數量+商品2單價*商品2數量+...步驟2:錢包余額=錢包金額-訂單總價當攻擊者將商品數量都篡改為負數,導致步驟1的訂單總價為負數。而負負得正,攻擊者不僅買入了商品并且錢包金額也增長了。解決方案2:應在后臺嚴格校驗訂單中每一個輸入參數的長度、格式、邏輯、特殊字符。整體解決方案:應按照長度、格式、邏輯以及特殊字符4個維度對每一個輸入參數進行安全校驗,然后再將其傳遞給敏感的API。原則上數據庫主鍵不能使用自增純數字,應使用uuid或雪花算法作為數據庫表主鍵以保證唯一性和不可預測性。身份信息應使用當前請求的用戶session或token安全的獲取,禁止直接信任用戶提交的身份信息。安全獲取用戶身份后,應對請求的數據資源進行邏輯判斷,防止用戶操作無權限的數據資源。不受信任的查詢字符串查詢字符串是GET參數名稱和值的串聯,可以傳入非預期參數。風險:例如URL請求/app/servlet.htm?a=1&b=2則對應查詢字符串提取為a=1&b=2那么HttpServletRequest.getParameter()HttpServletRequest.getQueryString()獲取的值都可能是不安全的。解決方案:查詢字符串只能在頁面渲染時使用,禁止將查詢字符串關聯任何業務請求。應按照長度、格式、邏輯以及特殊字符4個維度對每一個輸入的查詢字符串參數進行安全校驗,然后再將其傳遞給敏感的API。不受信任的HTTP請求頭攻擊者可以惡意篡改或偽造所有http請求頭中的參數,達到破壞應用程序的邏輯以執行針對客戶端或服務器端的目的。1.不受信任的Cookie頭HttpServletRequest.getRequestedSessionId()可以返回JSESSIONID的值。該值通常是字母、數字的組合值。(例如JSESSIONID=jp6q31lq2myn)攻擊者向后端發起請求時可以惡意偽造或篡改該值。例如:GET/somePageHTTP/1.1Host:User-Agent:Mozilla/5.0Cookie:JSESSIONID=Anyvalueoftheuser'schoice!!??'''">脆弱代碼:Cookie[]cookies=request.getCookies();for(inti=0;i<cookies.length;i++){Cookiec=cookies[i];if(c.getName().equals("authenticated")&&Boolean.TRUE.equals(c.getValue())){authenticated=true;}}以上代碼直接從cookie中而不是session中提取了參數作為登錄狀態的判斷,導致攻擊者可以偽造登錄狀態。解決方案:身份信息應使用當前請求的用戶session或token安全的獲取,而不是直接采用用戶提交的身份信息。身份信息應僅用于查看其值是否與請求的資源權限(包括菜單URL、接口URL、業務數據)是否匹配。如果權限不匹配,應停止業務邏輯并立刻告警,同時在審計日志中記錄一條越權日志。身份信息的值禁止記錄到日志中,否則內部人員可以劫持處于活動狀態的用戶權限。2.不受信任的Content-Type請求頭HTTP請求頭Content-Type可以由惡意的攻擊者控制。因此,HTTP的Content-Type值不應在任何重要的邏輯流程中使用。3.不受信任的HOST請求頭ServletRequest.getServerName()和HttpServletRequest.getHeader("Host")具有相同的邏輯,即提取Host請求頭。GET/testpageHTTP/1.1Host:因為惡意的攻擊者可以偽造Host請求頭,所以HTTP的Host值不應在任何重要的邏輯流程中使用。4.不受信任的User-Agent請求頭請求頭User-Agent很容易被客戶端偽造,不建議基于User-Agent的值采用不同的安全校驗邏輯。5.不受信任的IP請求頭以下IP請求頭,很容易被客戶端偽造,可能導致IP地址欺騙。X-Forwarded-ForX-Originating-IPX-Real-IPx-Remote-addrx-Remote-IP等其他解決方案1:應用程序與用戶間無代理時,應使用getRemoteAddr函數獲取用戶ip。解決方案2:應用程序與用戶間存在代理時,應使用代理頭獲取用戶ip。privateStringgetIpAddr(HttpServletRequestrequest){Stringip=request.getHeader("x-forwarded-for");System.out.println("x-forwarded-forip:"+ip);if(ip!=null&&ip.length()!=0&&!"unknown".equalsIgnoreCase(ip)){//多次反向代理后會有多個ip值,第一個ip才是真實ipif(ip.indexOf(",")!=-1){ip=ip.split(",")[0];}}if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ip=request.getHeader("Proxy-Client-IP");System.out.println("Proxy-Client-IPip:"+ip);}if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ip=request.getHeader("WL-Proxy-Client-IP");System.out.println("WL-Proxy-Client-IPip:"+ip);}if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ip=request.getHeader("HTTP_CLIENT_IP");System.out.println("HTTP_CLIENT_IPip:"+ip);}if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ip=request.getHeader("HTTP_X_FORWARDED_FOR");System.out.println("HTTP_X_FORWARDED_FORip:"+ip);}if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ip=request.getHeader("X-Real-IP");System.out.println("X-Real-IPip:"+ip);}if(ip==null||ip.length()==0||"unknown".equalsIgnoreCase(ip)){ip=request.getRemoteAddr();System.out.println("getRemoteAddrip:"+ip);}System.out.println("獲取客戶端ip:"+ip);returnip;}缺少CSRF攻擊的防護風險1:惡意用戶可以將惡意值分配給Referer請求頭進行Referer請求偽造攻擊。如果請求是從另一個安全的來源(HTTPS)發起的,則Referer將不存在。脆弱代碼2:@EnableWebSecuritypublicclassWebSecurityConfigextendsWebSecurityConfigurerAdapter{@Overrideprotectedvoidconfigure(HttpSecurityhttp)throwsException{//禁用csrf保護會導致csrf攻擊的產生http.csrf().disable();}}解決方案:任何越權判讀都不應基于Referer的值,應判斷session或token。應校驗Referer值阻止來自站外的請求,以避免csrf攻擊。避免Referer值欺騙攻擊,例如sec_部分匹配sec_的情況。任何CSRF防護都不應僅僅只基于Referer值,可以采用一次性的表單token。禁用SpringSecurity的CSRF保護對于標準Web應用程序是不安全的。客戶端請求偽造當Web應用程序將用戶重定向并轉發到其他頁面或其他外部網站,如果不驗證這些頁面的可信度,攻擊者可以將受害者重定向到網絡釣魚或惡意軟件站點,或者惡意利用轉發來訪問未經授權的頁面。脆弱代碼1:@RequestMapping("/redirect")publicStringredirect(@RequestParam("url")Stringurl){//不執行校驗就直接跳轉return"redirect:"+url;}脆弱代碼2:protectedvoiddoGet(HttpServletRequestreq,HttpServletResponseresp)throwsServletException,IOException{//不執行校驗就直接跳轉resp.sendRedirect(req.getParameter("redirectUrl"));}誘使用戶訪問惡意URL(將website偽造成vvebsite):\o"/login?redirect=/fake/login"/login?redirect=/fake/login將用戶重定向到偽造的登錄頁面,該頁面看起來像他們信任的站點:\o"/fake/login"/fake/login用戶輸入其憑據。惡意站點竊取用戶的憑據,并將其重定向到原始網站。解決方案:完整URL格式:protocol://hostname[:port]/path/[;parameters][?query]#fragment禁止直接接受來自用戶的URL目標,所有URL請求應使用白名單校驗。原則上應接受相對路徑請求。而絕對路徑的URL應盡可能使用白名單校驗每一個格式參數。驗證URL的域名部分時應避免sec_部分匹配sec_的惡意偽造。可以使用哈希映射到目標地址,并使用哈希在URL白名單中查找合法目標。服務端請求偽造當Web應用程序根據用戶請求對數據資源發起請求,如果不對該數據資源執行安全校驗,攻擊者可能獲取敏感數據資源。脆弱代碼:@WebServlet("/downloadServlet")publicclassdownloadServletextendsHttpServlet{protectedvoiddoPost(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{this.doGet(request,response);}protectedvoiddoGet(HttpServletRequestrequest,HttpServletResponseresponse)throwsServletException,IOException{Stringfilename="1.txt";//沒有校驗url變量的安全性Stringurl=request.getParameter("url");response.setHeader("content-disposition","attachment;fileName="+filename);intlen;OutputStreamoutputStream=response.getOutputStream();//直接使用url變量導致任意文件讀取URLfile=newURL(url);byte[]bytes=newbyte[1024];InputStreaminputStream=file.openStream();while((len=inputStream.read(bytes))>0){outputStream.write(bytes,0,len);}}}使用以下請求可以下載服務器硬盤上的文件http://localhost:8080/downloadServlet?url=file:///c:\1.txt解決方案:完整URL格式:protocol://hostname[:port]/path/[;parameters][?query]#fragment禁止直接接受來自用戶的URL目標,所有URL請求應使用白名單校驗。原則上應接受相對路徑請求。而絕對路徑的URL應盡可能使用白名單校驗每一個格式參數。驗證URL的域名部分時應避免sec_部分匹配se

溫馨提示

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

評論

0/150

提交評論