漏洞扫描解决方案汇总

简单概要

360奇安信扫描
代码注入:SQL注入:MyBatis#变量名称创建参数化查询SQL语句,不会导致SQL注入。而$变量名称直接使用SQL指令,会导致SQL注入攻击#变量名称,创建参数化查询SQL语句此项目中出现的mybatis注入为框架自封装的数据权限方法,使用$处为将封装好的sql语句填入,并不会存才从外部注入sql的情况
跨站脚本:存储型XSS(66)存储型XSS是指应用程序通过Web请求获取不可信赖的数据,并且在未检验数据是否存在XSS代码的情况下,将其存入数据库。当程序下一次从数据库中获取该数据时,致使页面再次执行XSS代码。存储型XSS可以持续攻击用户,在用户提交了包含XSS代码的数据存储到数据库后,每当用户在浏览网页查询对应数据库中的数据时,那些包含XSS代码的数据就会在服务器解析并加载,当浏览器读到XSS代码后,会当做正常的HTML和JS解析并执行,于是发生存储型XSS攻击对从数据库或其它后端数据存储获取不可信赖的数据进行合理验证(如年龄只能是数字),对特殊字符(如<、>、'、"以及\、javascript等进行过滤。 根据数据将要置于HTML上下文中的不同位置(HTML标签、HTML属性、JavaScript脚本、CSS、URL),对所有不可信数据进行恰当的输出编码。360奇安信扫描的错误都是后端返回时报XSS漏洞,属硬扫描漏洞,前后端有XSS过滤工具类
跨站脚本:反射型XSS(33)反射型XSS是指应用程序通过Web请求获取不可信赖的数据,并在未检验数据是否存在恶意代码的情况下,将其发送给用户。反射型XSS一般可以由攻击者构造带有恶意代码参数的URL来实现,在构造的URL地址被打开后,其中包含的恶意代码参数被浏览器解析和执行。这种攻击的特点是非持久化,必须用户点击包含恶意代码参数的链接时才会触发对用户的输入进行合理验证(如年龄只能是数字),对特殊字符(如<、>、'、"以及\、javascript等进行过滤。 根据数据将要置于HTML上下文中的不同位置(HTML标签、HTML属性、JavaScript脚本、CSS、URL),对所有不可信数据进行恰当的输出编码。360奇安信扫描的错误都是后端返回时报XSS漏洞,属硬扫描漏洞,前后端有XSS过滤工具类
输入验证:重定向应用程序允许未验证的用户输入控制重定向中的URL,攻击通过构建URL,使用户重定向到任意URL,利用这个漏洞可以诱使用户访问某个页面,挂马、密码记录、下载任意文件等,常被用来钓鱼。防止重定向漏洞的方法是创建一份合法URL列表,用户只能从中进行选择,进行重定向操作。后端url在配置文件中配置的,是固定的
输入验证:路径遍历应用程序对用户可控制的输入未经合理校验,就传送给一个文件API。攻击者可能会使用一些特殊的字符(如../)摆脱受保护的限制,访问一些受保护的文件或目录程序对非受信的用户输入做过滤和验证,对网站用户提交的文件路径进行硬编码或统一编码,过滤非法字符。 对文件后缀进行白名单控制,拒绝包含了恶意的符号或空字节。 合理配置Web服务器的目录访问权限。增加路径名称过滤验证
输入验证:直接绑定敏感字段目前大部分WEB框架支持将HTTP请求参数与类的属性相匹配的而生成一个对象。因此,攻击者能够将值放入HTTP请求参数中从而绑定系统对象当程序将非将HTTP请求参数直接绑定给对象时,应该要控制绑定到对象的属性,防止暴露敏感属性。增加敏感字段验证
输入验证:文件上传(4)文件可能会被攻击者注入危险内容或恶意代码,当程序允许用户上传时,攻击者可以通过文件将恶意代码在服务器上运行或者将危险内容注入程序。检查代码逻辑,判断程序是否需要文件上传。扫描出的文件上传共有4个,都需要上传接口
代码注入:HTTP响应截断(4)程序从一个不可信赖的数据源获取数据,未进行验证就置于HTTP头文件中发给用户,可能会导致HTTP响应截断攻击。防止HTTP响应截断攻击的最安全的方法是创建一份安全字符白名单,只接受完全由这些受认可的字符组成的输入出现在HTTP响应头文件中。
输入验证:拒绝服务:正则表达式正则表达式引擎分成两类:一类称为DFA(确定性有限状态自动机),另一类称为NFA(非确定性有限状态自动机)。Java使用的是NFA正则引擎,使用正则式和文本比较,每碰到一个字符,就把它跟正则式比较,匹配就记下来,然后接着往下比较。一旦不匹配,就会后退直到回到上一次匹配的地方。而不可信赖数据被传递至应用程序并作为正则表达式使用,可能导致线程过度使用 CPU 资源,从而导致拒绝服务攻击。不要将不可信赖数据作为正则表达式使用。代码中是“名字脱敏”字符串替换,没有用到正则表达式
输入验证:日志伪造允许日志记录未经验证的用户输入,会导致日志伪造攻击。防止日志伪造攻击可以采用白名单、黑名单或验证用户输入数据的方式对不可信赖的数据进行校验。不输出具体日志
代码注入:资源注入(6)使用用户输入控制资源标识符,借此攻击者可以访问或修改其他受保护的系统资源。当满足以下两个条件时,就会发生资源注入为了避免资源注入漏洞攻击,可以采用黑名单或白名单策略。黑名单会有选择地拒绝或避免潜在的危险字符。但是,任何这样一份黑名单都不可能是完整的,而且将随着时间的推移而过时。比较好的方法是创建白名单,允许其中的字符出现在资源名称中,且只接受完全由这些被认可的字符所组成的输入。
输入验证:服务器端请求伪造(2)很多Web应用提供了从其他的服务器上获取数据的功能,例如用户指定URL让Web应用加载图片,下载文件等。如果恶意利用这个功能,可以让存在缺陷的Web应用作为代理攻击远程和本地的服务器。这种形式的攻击称为服务端请求伪造攻击(Server-side Request Forgery, SSRF)。攻击者利用SSRF可以实现的攻击主要有5种: 1. 可以对外网、服务器所在内网、本地进行端口扫描,获取一些服务器的banner信息; 2. 攻击运行在内网或本地的应用程序(比如溢出); 3. 对内网web应用进行指纹识别,通过访问默认文件实现; 4. 攻击内外网的web应用,主要是使用get参数就可以实现的攻击(比如struts2,sqli等); 5. 利用file协议读取本地文件等。1. 过滤返回信息,验证远程服务器对请求的响应是比较容易的方法。如果web应用是去获取某一种类型的文件。那么在把返回结果展示给用户之前先验证返回的信息是否符合标准。 2. 统一错误信息,避免用户可以根据错误信息来判断远端服务器的端口状态。 3. 限制请求的端口为http常用的端口,比如80,443,8080,8090。 4. 禁用不需要的协议。仅仅允许http和https请求。可以防止类似于file:///, gopher:// , ftp:// 等引起的问题。 5. 过滤内网ip,限制访问内网
输入验证:访问权限修饰符控制AccessibleObject类是Field、Method和Constructor对象的基类,能够允许反射对象修改访问权限修饰符,绕过由Java访问修饰符提供的访问控制检查。它让程序员能够更改私有字段或调用私有方法,这在通常情况下是不允许的。通过有权限的类更改访问权限修饰符,并确保修改的访问权限修饰符参数不能被攻击者控制。项目中调用Excelutils等工具类时,需要把工具类中的字段变成public
代码质量:有风险的SSL:过于广泛的信任证书由于盗用证书颁发机构的数量正在不断增加,因此即使是由CA签名的证书也不应该信任,因为拥有这些盗用证书的攻击者可能会拦截这些CA的SSL/TLS信息流不要直接信任用户证书,应该对证书进行判断和处理进行证书返回不为空
API误用:使用DNS名称作为安全性的依据(4)程序中采用DNS名称进行安全认证,但DNS名称是容易被攻击者进行欺骗的不要依赖DNS名称来做安全认证
API误用:不安全的框架绑定目前大部分WEB框架支持将HTTP请求参数与类的属性相匹配的而生成一个对象。因此,攻击者能够将值放入HTTP请求参数中从而绑定系统对象当程序将非将HTTP请求参数直接绑定给对象时,应该要控制绑定到对象的属性,防止暴露所有属性。 在Spring MVC中,可以配置绑定器使用setAllowedFieldssetDisallowedFields方法控制属性绑定过程以控制应绑定的属性。进行框架验证
密码管理:不安全的随机数Java API中提供了java.util.Random类实现PRNG(),该PRNG是可移植和可重复的,如果两个java.util.Random类的实例使用相同的种子,会在所有Java实现中生成相同的数值序列。在安全性要求较高的应用中,应使用更安全的随机数生成器,如java.security.SecureRandom类。使用更安全的随机数
密码管理:配置文件中的明文密码(11)空密码(4)及硬编码加密密钥(4)配置文件中采用明文存储密码,将会降低系统安全性。配置文件中的密码应进行加密存储
资源管理:格式化缺陷格式化对象是非线程安全的,java.text.Format中的parse()format()方法包含一个可导致用户看到其他用户数据的race condition。1. 将格式化对象定义成局部变量,但是每调用一次方法意味创建一个格式化对象,浪费内存。 2. 方法加同步锁synchronized,在同一时刻,只有一个线程可以执行类中的某个方法。这样性能较差,每次都要等待锁释放后其他线程才能进入。 3. 使用第三方库joda-time,由第三方考虑线程不安全的问题。 4. 使用ThreadLocal:每个线程拥有自己的格式化对象。进行统一格式化处理
资源管理:单例成员变量javax.servlet.http.HttpServletorg.apache.struts.action.Action的对象不是线程安全的。对于同一个Servlet对象(或struts1的Action对象)的多个请求,Servlet对象(或struts1的Action对象)将在一个多线程的环境中并发执行。Web容器默认采用单实例多线程的方式来处理Http请求,这将导致Servlet对象(或struts1的Action对象)成员变量访问的线程安全问题。使用Java EE的Servlet或struts1的Action时,必须保证其是线程安全的。修复方式举例如下:使用局部变量
输入验证:JavaScript劫持(1)使用JavaScript传送敏感数据的应用程序可能会存在JavaScript劫持的漏洞,该漏洞允许未经授权的攻击者从一个易受攻击的应用程序中读取机密数据。 JavaScript劫持可以简单的理解为模拟授权的用户,窃取用户在服务器上的信息。Web浏览器使用同源策略(Same Origin Policy),以保护用户免受恶意网站的攻击。同源策略规定:如果要使用JavaScript来访问某个网页的内容的话,则JavaScript和网页必须都来源于相同的域。若不采取同源策略,恶意网站便可以使用受害者的客户端凭证来运行 JavaScript,从其他网站加载的敏感信息,并对这些信息进行处理,然后将其返回给攻击者。 使用JSON传输数据的JavaScript应用更容易受到JavaScript劫持攻击。尽量避免跨域的数据传输,对于同域的数据传输使用xmlhttp的方式作为数据获取的方式。如果是跨域的数据传输,必须要对敏感的数据获取做权限认证,具体的方式可以包括: 1. referer的来源限制,利用前端referer的不可伪造性来保障请求数据的应用来源于可信的地方,此种方式力度较稀,完全依赖于referer,某些情况下(如存在XSS)可能导致被绕过。 2. 加入Token。利用Token对调用者的身份进行认证,这种方式对于调用者的身份会要求力度较细,但是一旦出现XSS也可能导致前端Token的泄露,从而导致保护失效。 3. 避免直接执行JavaScript响应:在响应中加入一些额外的字符。这些响应只有经过了修改,才能成功地转到JavaScript解释器进行处理。这样可以防止攻击者使用" }) public List<SysDept> selectDeptList(SysDept dept);
输入验证:路径遍历

new File()修改为org.apache.commons.io.FileUtils.getFile()

代码注入:有风险的SQL查询:MyBatis

同代码注入:SQL注入:MyBatis

输入验证:访问权限修饰符控制

使用ReflectionUtils.makeAccessible(method);代替/method.setAccessible(true);

密码管理:不安全的随机数

使用SecureRandom secureRandom = new SecureRandom();替代Random random = new Random();

密码管理:硬编码密码

从配置文件中获取经过加密的密码值并解密使用

@Component
public class SignatureBySM4AndSM2 {private static final Logger log = LoggerFactory.getLogger(SignatureBySM4AndSM2.class);private static ClientThreadPool connectPool;private static HSMWSTApiServiceImp imp;public static String password;@Value("${mimajiPwd}")public void setPassword(String mimajiPwd) {SignatureBySM4AndSM2.password = mimajiPwd;}}
密码管理:配置文件中的明文密码

项目中引入jasypt组件

<dependency><groupId>com.github.ulisesbocchiogroupId><artifactId>jasypt-spring-boot-starterartifactId><version>2.1.1version>
dependency>

使用jasyot对密码进行加密

@Component
public class JasypRunner implements ApplicationRunner {@Overridepublic void run(ApplicationArguments args) throws Exception {
//     System.out.println(" 加解密密码");
//     BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
//     //加密的盐
//     basicTextEncryptor.setPassword("F!X%pGCD?Z");
//     String key = "";
//     key = "Uf7Nu7KHWId02d";
//     System.out.println(key+"---加密后 = " + basicTextEncryptor.encrypt(key));
//     key = "dameng123";
//     System.out.println(key+"---加密后 = " + basicTextEncryptor.encrypt(key));
//     key = "7fc6wYb2Vj";
//     System.out.println(key+"---加密后 = " + basicTextEncryptor.encrypt(key));
//     key = "0Uvd4wU3e";
//     System.out.println(key+"---加密后 = " + basicTextEncryptor.encrypt(key));
//     key = "Uf7Nu39AU0sW";
//     System.out.println(key+"---加密后 = " + basicTextEncryptor.encrypt(key));//String decrypt = basicTextEncryptor.decrypt(ruphie);//System.out.println("解密后 = " + decrypt);}
}

在项目启动参数中增加–jasypt.encryptor.password=F!X%pGCD?Z

资源管理:格式化缺陷

保证DecimalFormat对象每次都是从ThreadLocal中获取的

private static ThreadLocal<DecimalFormat> tl = new ThreadLocal<>();private static DecimalFormat getDecimalFormat() {if (tl.get() == null) {tl.set(new DecimalFormat("######0.00"));}//保证DecimalFormat对象每次都是从ThreadLocal中获取的return tl.get();
}
代码质量:系统信息泄露:外部

不允许返回e.getMessage(),可以修改成如下格式

return AjaxResult.error("请求地址"+requestURI+",不支持"+e.getMethod()+"请求");
代码质量:比较Locale相关的数据未指定适当的Locale

可以在对字符串处理前,将默认的Locale设置为English。

Locale.setDefault(Locale.ENGLISH);
代码质量:硬编码IP和代码质量:硬编码手机号码和密码管理:硬编码加密密钥

1.都配置在配置文件里面

public static String decryptKey;@Value("${decryptKey}")
public void setDecryptKey(String decryptKey) {DrinEncryptUtils.decryptKey = decryptKey;
}

2.有的可能是测试代码,注释掉

代码质量:null引用

引用对象之前增加 !=null 判断,有的工具类如CollectionUtils.isNotEmpty()不能使用

if (hideColumnList!=null) {util.hideColumn(hideColumnList.toArray(new String[100]));
}
资源管理:资源未释放:流

要在finally里面使用in.close();关闭,不能使用IOUtils.closeQuietly(in)关闭

finally {if (in!=null){try {in.close();} catch (IOException e) {log.error("关闭输入流失败{}", e.getMessage());}}
}
密码管理:空的加密密匙

不允许出现空密钥,注释掉


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章