1.跨站脚本
1.1.反射型XSS
- 漏洞说明
反射型XSS是指应用程序通过Web请求获取不可信赖的数据,并在未检验数据是否存在恶意代码的情况下,将其发送给用户。反射型XSS一般可以由攻击者构造带有恶意代码参数的URL来实现,在构造的URL地址被打开后,其中包含的恶意代码参数被浏览器解析和执行。这种攻击的特点是非持久化,必须用户点击包含恶意代码参数的链接时才会触发。
- 解决方法
- 添加相关依赖
<dependency> <groupId>org.owasp.esapi</groupId> <artifactId>esapi</artifactId> <version>2.3.0.0</version> </dependency>
- 对服务层返回的字符串进行编码,解决此类问题,奇安信代码卫士扫描验证通过
//对返回的字符串进行编码,防止反射型XSS漏洞 applicationNo = ESAPI.encoder().encodeForJavaScript(applicationNo);
- 如果服务层返回的是对象(List、Map、Object),暂时未找到修复方案
1.2.存储型XSS
- 漏洞说明
存储型XSS是指应用程序通过Web请求获取不可信赖的数据,并且在未检验数据是否存在XSS代码的情况下,将其存入数据库。当程序下一次从数据库中获取该数据时,致使页面再次执行XSS代码。存储型XSS可以持续攻击用户,在用户提交了包含XSS代码的数据存储到数据库后,每当用户在浏览网页查询对应数据库中的数据时,那些包含XSS代码的数据就会在服务器解析并加载,当浏览器读到XSS代码后,会当做正常的HTML和JS解析并执行,于是发生存储型XSS攻击。
- 解决方案
- 添加相关依赖
<dependency> <groupId>org.owasp.esapi</groupId> <artifactId>esapi</artifactId> <version>2.3.0.0</version> </dependency>
- 对服务层返回的字符串进行编码,解决此类问题,奇安信代码卫士扫描验证通过
//对返回的字符串进行编码,防止反射型XSS漏洞 applicationNo = ESAPI.encoder().encodeForJavaScript(applicationNo);
- 如果服务层返回的是对象(List、Map、Object),暂时未找到修复方案
2.输入验证
2.1.路径遍历
- 漏洞说明
应用程序对用户可控制的输入未经合理校验,就传送给一个文件API。攻击者可能会使用一些特殊的字符(如
..
和/
)摆脱受保护的限制,访问一些受保护的文件或目录。
- 解决方案
- 添加相关依赖
<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.6</version> </dependency>
- 添加路径处理代码,奇安信代码卫士扫描验证通过
//解决路径遍历漏洞-路径 String filePath = FilenameUtils.getFullPath(path);
- 添加文件名处理代码,奇安信代码卫士扫描验证通过
String fileName = FilenameUtils.getName(targetName);
2.2.JavaScript劫持
- 漏洞说明
使用JavaScript传送敏感数据的应用程序可能会存在JavaScript劫持的漏洞,该漏洞允许未经授权的攻击者从一个易受攻击的应用程序中读取机密数据。
JavaScript劫持可以简单的理解为模拟授权的用户,窃取用户在服务器上的信息。Web浏览器使用同源策略(Same Origin Policy),以保护用户免受恶意网站的攻击。同源策略规定:如果要使用JavaScript来访问某个网页的内容的话,则JavaScript和网页必须都来源于相同的域。若不采取同源策略,恶意网站便可以使用受害者的客户端凭证来运行 JavaScript,从其他网站加载的敏感信息,并对这些信息进行处理,然后将其返回给攻击者。 使用JSON传输数据的JavaScript应用更容易受到JavaScript劫持攻击。
- 解决方案
代码替换
//response.setContentType("application/json; charset=utf-8"); //代码替换成 response.setHeader("Content-Type", "application/json; charset=utf-8");
3.代码质量
3.1.Cookie:未设置HTTPOnly属性
- 漏洞说明
Cookie设置HttpOnly属性意味着客户端脚本不允许读取cookie,对于防范跨站脚本攻击大有帮助,浏览器也不会将其发送给任何第三方。
- 解决方案
添加下列代码
//设置HTTPOnly属性 cookie.setHttpOnly(true);
3.2.Cookie:未经过SSL加密
- 漏洞说明
使用未加密的网络传输通道发送Cookie易受到网络截取攻击。创建Cookie时,需要将secure标记设置为true,表明浏览器必须通过HTTPS来加密传输Cookie。
- 解决方案
添加下列代码
//设置Secure属性 cookie.setSecure(true);
4.密码管理
4.1.不安全的随机数
- 漏洞说明
Java API中提供了
java.util.Random
类实现PRNG()
,该PRNG是可移植和可重复的,如果两个java.util.Random
类的实例使用相同的种子,会在所有Java实现中生成相同的数值序列。
- 解决方案
替换随机数定义代码
SecureRandom random = null; try { random = SecureRandom.getInstance("SHA1PRNG"); //业务代码,例如: String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num"; // 输出字母还是数字 } catch (NoSuchAlgorithmException e) { e.printStackTrace(); }
4.2.配置文件中的明文密码
- 漏洞说明
配置文件中采用明文存储密码,所有能够访问该文件的人都能访问该密码,将会降低系统安全性。
- 解决方案
- 添加maven依赖
<dependency> <groupId>com.github.ulisesbocchio</groupId> <artifactId>jasypt-spring-boot-starter</artifactId> <version>3.0.4</version> </dependency>
添加配置类
package com.KSF.confg; import org.jasypt.encryption.StringEncryptor; import org.jasypt.encryption.pbe.PooledPBEStringEncryptor; import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * <p> * jasypt自定义加密器 * </p> * * @author KSF * @since 2022/7/11 15:28 */ @Configuration public class MyJasyptConfig { private String ps = "ceshi"; @Bean(name = "CodeEncrypBean") public StringEncryptor CodeEncrypBean() { PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); SimpleStringPBEConfig config = new SimpleStringPBEConfig(); config.setPassword(key); config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256"); config.setKeyObtentionIterations("1000"); config.setPoolSize("1"); config.setProviderName("SunJCE"); config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator"); config.setStringOutputType("base64"); encryptor.setConfig(config); return encryptor; } //测试 public static void main(String[] args) { PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor(); SimpleStringPBEConfig config = new SimpleStringPBEConfig(); config.setPassword("ceshi"); config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256"); config.setKeyObtentionIterations("1000"); config.setPoolSize("1"); config.setProviderName("SunJCE"); config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator"); config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator"); config.setStringOutputType("base64"); encryptor.setConfig(config); //=================================== String encrypt = encryptor.encrypt("需要加密的密码"); String decrypt = encryptor.decrypt("加密后的密码"); System.out.println(encrypt); System.out.println(decrypt); } }
替换配置文件的密码
spring: application: name: ksf-api datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://ip地址:端口号/数据库名称?characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true&allowMultiQueries=true&zeroDateTimeBehavior=convertToNull username: root password: ENC(加密后的密码) jasypt: encryptor: bean: CodeEncrypBean
评论区