![java安全编码规范_第1页](http://file4.renrendoc.com/view11/M01/0C/3D/wKhkGWelr5CAZtRZAAFv1XwSh_U653.jpg)
![java安全编码规范_第2页](http://file4.renrendoc.com/view11/M01/0C/3D/wKhkGWelr5CAZtRZAAFv1XwSh_U6532.jpg)
![java安全编码规范_第3页](http://file4.renrendoc.com/view11/M01/0C/3D/wKhkGWelr5CAZtRZAAFv1XwSh_U6533.jpg)
![java安全编码规范_第4页](http://file4.renrendoc.com/view11/M01/0C/3D/wKhkGWelr5CAZtRZAAFv1XwSh_U6534.jpg)
![java安全编码规范_第5页](http://file4.renrendoc.com/view11/M01/0C/3D/wKhkGWelr5CAZtRZAAFv1XwSh_U6535.jpg)
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
安全开发-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. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 二零二五年度葡萄园生态循环农业承包合作协议
- 2023三年级数学上册 一 两、三位数乘一位数第3课时 倍的认识说课稿 苏教版
- 2025年度节水型喷灌设备采购及安装服务合同
- 炊具挂盘项目融资渠道探索
- 2025年度南京二手房买卖合同房屋质量检测与风险评估报告
- 2024-2025学年度九年级历史下册 第八单元 第17课 第三次科技革命说课稿 新人教版001
- 2025至2030年中国X射线光电子能谱仪数据监测研究报告
- 2025至2030年中国三羟基丙烷数据监测研究报告
- 2025年烘焙奶粉项目可行性研究报告
- 2025年水管接头配件项目可行性研究报告
- 法语专四四级词汇
- 动物检疫技术-动物检疫的对象(动物防疫与检疫技术)
- 中考记叙文阅读
- 《计算机应用基础》-Excel-考试复习题库(含答案)
- 产科沟通模板
- 2023-2024学年四川省成都市小学数学一年级下册期末提升试题
- GB/T 7462-1994表面活性剂发泡力的测定改进Ross-Miles法
- GB/T 2934-2007联运通用平托盘主要尺寸及公差
- GB/T 21709.13-2013针灸技术操作规范第13部分:芒针
- 2022年青岛职业技术学院单招语文考试试题及答案解析
- 急诊科进修汇报课件
评论
0/150
提交评论