项目安全问题及解决方法-----xss处理

XSS 问题的根源在于,原本是让用户传入或输入正常数据的地方,被黑客替换为了 JavaScript 脚本,页面没有经过转义直接显示了这个数据,然后脚本就被 执行了。更严重的是,脚本没有经过转义就保存到了数据库中,随后页面加载数据的时候,数据中混入的脚本又当做代码执行了。黑客可以利用这个漏洞 来盗取敏感数据,诱骗用户访问钓鱼网站等。


@RequestMapping("xss")
@Slf4j
@Controller
public class XssController {@Autowiredprivate UserRepository userRepository;//显示xss页面@GetMappingpublic String index(ModelMap modelMap) {//查数据库User user = userRepository.findById(1L).orElse(new User());//给View提供ModelmodelMap.addAttribute("username", user.getName());return "xss";}//保存用户信息@PostMappingpublic String save(@RequestParam("username") String username, HttpServletRequest request) {User user = new User();user.setId(1L);user.setName(username);userRepository.save(user);//保存完成后重定向到首页return "redirect:/xss/";}
}
//用户类,同时作为DTO和Entity
@Entity
@Data
public class User {@Idprivate Long id;private String name;
}

使用Thymeleaf 模板引擎来渲染页面

<div style="font-size: 14px"><form id="myForm" method="post" th:action="@{/xss/}"><label th:utext="${username}"/> <!--对于 Thymeleaf 模板引擎,需要注意的是,使用 th:utext 来显示数据是不会进行转义的,需要使用 th:text--><input id="username" name="username" size="100" type="text"/><button th:text="Register" type="submit"/></form>
</div>

 

解决方法可以使用 HTML 转码。既然是通过 @RequestParam 来获取请求参数,那我们定义一个 @InitBinder 实现数据绑定的时候,对字符串进行转码即 可。

@ControllerAdvice
public class SecurityAdvice {@InitBinderprotected void initBinder(WebDataBinder binder) {//注册自定义的绑定器binder.registerCustomEditor(String.class, new PropertyEditorSupport() {@Overridepublic String getAsText() {Object value = getValue();return value != null ? value.toString() : "";}@Overridepublic void setAsText(String text) {//赋值时进行HTML转义setValue(text == null ? null : HtmlUtils.htmlEscape(text));}});}
}

 

但是解决问题的方式不全面,@InitBinder 是 Spring Web 层面的处理逻辑,如果有代码不通过 @RequestParam 来获取数据,而是直接从 HTTP 请求 获取数据的话,这种方式就不会奏效。比如: user.setName(request.getParameter("username")); 最好的解决方式是,定义一个 servlet Filter,通过 HttpServletRequestWrapper 实现 servlet 层面的统一参数替换。

//自定义过滤器
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class XssFilter implements Filter {@Overridepublic void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletExceptio n {chain.doFilter(new XssRequestWrapper((HttpServletRequest) request), response);}
}
public class XssRequestWrapper extends HttpServletRequestWrapper {public XssRequestWrapper(HttpServletRequest request) {super(request);}@Overridepublic String[] getParameterValues(String parameter) {//获取多个参数值的时候对所有参数值应用clean方法逐一清洁return Arrays.stream(super.getParameterValues(parameter)).map(this::clean).toArray(String[]::new);}@Overridepublic String getHeader(String name) {//同样清洁请求头return clean(super.getHeader(name));}@Overridepublic String getParameter(String parameter) {//获取参数单一值也要处理return clean(super.getParameter(parameter));}//clean方法就是对值进行HTML转义private String clean(String value) {return StringUtils.isEmpty(value)? "" : HtmlUtils.htmlEscape(value);}} 

这种方式还是不够彻底,原因是无法处理通过 @RequestBody 注解提交的 JSON 数据。比如,有这样一个 PUT 接口,直接保存了客户端传入的 JSON User 对 象

@PutMapping
public void put(@RequestBody User user) {userRepository.save(user);
}

 

因此我们需要自定义一个json的反序列器进行处理:

    //注册自定义的Jackson反序列器@Beanpublic Module xssModule() {SimpleModule module = new SimpleModule();module.module.addDeserializer(String.class, new XssJsonDeserializer());return module;}
public class XssJsonDeserializer extends JsonDeserializer<String> {@Overridepublic String deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException {String value = jsonParser.getValueAsString();if (value != null) {//对于值进行HTML转义return HtmlUtils.htmlEscape(value);}return value;}@Overridepublic Class<String> handledType() {return String.class;}
}

 这样就实现了既能转义 Get/Post 通过请求参数提交的数据,又能转义请求体中直接提交的 JSON 数据。但是目前这种只能堵新漏,确保新数据进入数据 库之前转义。如果因为之前的漏洞,数据库中已经保存了一些 JavaScript 代码,那么读取的时候同样可能出问题。因此,我们还要实现数据读取的时候也 转义。

@GetMapping("user")
@ResponseBody
public User query() {return userRepository.findById(1L).orElse(new User());
}

 

修改之前的 SimpleModule 加入自定义序列化器,并且实现序列化时处理字符串转义

    //注册自定义的Jackson序列器@Beanpublic Module xssModule() {SimpleModule module = new SimpleModule();module.addDeserializer(String.class, new XssJsonDeserializer());module.addSerializer(String.class, new XssJsonSerializer());return module;}
public class XssJsonSerializer extends JsonSerializer<String> {@Overridepublic Class<String> handledType() {return String.class;}@Overridepublic void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {if (value != null) {//对字符串进行HTML转义jsonGenerator.writeString(HtmlUtils.htmlEscape(value));}}
}

 

还要考虑一种情况:如果需要在 Cookie 中写入敏感信息的话,我们可以开启 HttpOnly 属性。这样 JavaScript 代码就无法读取 Cookie 了,即便页面被 XSS 注 入了攻击代码,也无法获得我们的 Cookie。

//服务端读取Cookie
@GetMapping("readCookie")
@ResponseBody
public String readCookie(@CookieValue("test") String cookieValue) {return cookieValue;
}
//服务端写入Cookie
@GetMapping("writeCookie")
@ResponseBody
public void writeCookie(@RequestParam("httpOnly") boolean httpOnly, HttpServletResponse response) {Cookie cookie = new Cookie("test", "zhuye");//根据httpOnly入参决定是否开启HttpOnly属性cookie.setHttpOnly(httpOnly);response.addCookie(cookie);
}

 由于 test 和 _ga 这两个 Cookie 不是 HttpOnly 的。通过 document.cookie 可以输出这两个 Cookie 的内容:

为 test 这个 Cookie 启用了 HttpOnly 属性后,就不能被 document.cookie 读取到了,输出中只有 _ga 一项:

 

 但是服务端可以读取到这个 cookie:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/450256.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么样的性能测试工具才算是好的工具呢?

一、性能测试工具的特征 调度能力 因为性能测试不可能由一台压力机完成或者说大部分情况下&#xff0c;我们不能不可能由一台压力机来完成&#xff0c;凡是对压力真正有所要求的场景&#xff0c;往往是多台压力机共同施加压力完成性能测试&#xff1b;因此&#xff0c;性能测…

Autonomous_Exploration_Development_Environment的local_planner学习笔记

1.程序下载网址&#xff1a;https://github.com/HongbiaoZ/autonomous_exploration_development_environment 2.相关参考资料&#xff1a; https://blog.csdn.net/lizjiwei/article/details/124437157 Matlab用采样的离散点做前向模拟三次样条生成路径点-CSDN博客 CMU团队开…

探索设计模式的魅力:为什么你应该了解装饰器模式-代码优化与重构的秘诀

设计模式专栏&#xff1a;http://t.csdnimg.cn/nolNS 开篇 在一个常常需要在不破坏封装的前提下扩展对象功能的编程世界&#xff0c;有一个模式悄无声息地成为了高级编程技术的隐形冠军。我们日复一日地享受着它带来的便利&#xff0c;却往往对其背后的复杂性视而不见。它是怎样…

嵌入式中物联网核心技术有哪些

IoT军事技术 物联网军事技术是一项利用IoT感知技术在军事活动中获取人、装备、作战环境状态的信息特征&#xff0c;从而实现在军事活动中做出智能化决策和控制局势的军事方针。 据悉&#xff0c;早于2012年10月军方联合了社会研究机构合力创建了“军事物联网联合实验室”。 …

机器学习入门-----sklearn

机器学习基础了解 概念 机器学习是人工智能的一个实现途径 深度学习是机器学习的一个方法发展而来 定义:从数据中自动分析获得模型,并利用模型对特征数据【数据集:特征值+目标值构成】进行预测 算法 数据集的目标值是类别的话叫做分类问题;目标值是连续的数值的话叫做回…

R语言分析任务:

有需要实验报告的可CSDN 主页个人私信 《大数据统计分析软件&#xff08;R语言&#xff09;》 实 验 报 告 指导教师&#xff1a; 专 业&#xff1a; 班 级&#xff1a; 姓 名&#xff1a; 学 …

[office] excel表格怎么绘制股票的CCI指标- #媒体#学习方法#笔记

excel表格怎么绘制股票的CCI指标? excel表格怎么绘制股票的CCI指标&#xff1f;excel表格中想要绘制一个股票cci指标&#xff0c;该怎么绘制呢&#xff1f;下面我们就来看看详细的教程&#xff0c;需要的朋友可以参考下 CCI指标是一种在股票&#xff0c;贵金属&#xff0c;货…

基于Python的招聘网站爬虫及可视化的设计与实现

摘要&#xff1a;现在&#xff0c;随着互联网网络的飞速发展&#xff0c;人们获取信息的最重要来源也由报纸、电视转变为了互联网。互联网的广泛应用使网络的数据量呈指数增长&#xff0c;让人们得到了更新、更完整的海量信息的同时&#xff0c;也使得人们在提取自己最想要的信…

Python算法题集_旋转图像

Python算法题集_旋转图像 题目48&#xff1a;旋转图像1. 示例说明2. 题目解析- 题意分解- 优化思路- 测量工具 3. 代码展开1) 标准求解【矩阵复本】2) 改进版一【矩阵转置矩阵反转】3) 改进版二【四值旋转】 4. 最优算法 题目48&#xff1a;旋转图像 本文为Python算法题集之一…

Windows Server安装部署FTP服务

文章目录 建立FTP目录通过IIS在Server上安装FTP服务配置FTP站点配置身份验证和授权测试FTP服务FTP软件推荐FTP客户端软件FTP服务器软件适合Ubuntu的FTP软件 推荐阅读 在Windows操作系统中安装和配置FTP服务&#xff0c;主要是基于Internet Information Services (IIS)的FTP服务…

SQL sever2008中创建用户并赋权

一、创建数据库dream CREATE DATABASE dream; 二、创建登录用户XZS 法一&#xff1a;使用SSMS创建 通过查询 sys.syslogins 系统视图来确定当前登录是否具有系统管理员权限。执行以下查询语句&#xff1a; SELECT name, isntname FROM sys.syslogins WHERE sysadmin 1;选…

一款轻量级、高性能、功能强大的内网穿透代理服务器

简介 nps是一款轻量级、高性能、功能强大的内网穿透代理服务器。目前支持tcp、udp流量转发&#xff0c;可支持任何tcp、udp上层协议&#xff08;访问内网网站、本地支付接口调试、ssh访问、远程桌面&#xff0c;内网dns解析等等……&#xff09;&#xff0c;此外还支持内网htt…