Spring Boot 防护 XSS + SQL 注入攻击

news/2024/5/10 2:57:54/文章来源:https://blog.csdn.net/Sgxlebron/article/details/137111609
  1. XSS跨站脚本攻击
    ① XSS漏洞介绍
    跨站脚本攻击XSS是指攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被解析执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!
    在这里插入图片描述

② XSS漏洞分类
存储型XSS: 存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie

图片
图片

反射型XSS: 非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面

DOM型XSS: 不经过后端,DOM-XSS漏洞是基于文档对象模型(Document Objeet Model,DOM)的一种漏洞,DOM-XSS是通过url传入参数去控制触发的,其实也属于反射型XSS。

③ 防护建议
限制用户输入,表单数据规定值得类型,例如年龄只能是int,name为字母数字组合。
对数据进行html encode处理。
过滤或移除特殊的html标签。
过滤javascript事件的标签。
2. SQL注入攻击
① SQL注入漏洞介绍
SQL注入(SQLi)是一种注入攻击,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加,修改和删除数据库中的记录;

SQL注入漏洞可能会影响使用SQL数据库(如MySQL,Oracle,SQL Server或其他)的任何网站或Web应用程序。犯罪分子可能会利用它来未经授权访问用户的敏感数据:客户信息,个人数据,商业机密,知识产权等。SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。

②防护建议
使用mybatis中#{}可以有效防止sql注入。

使用#{}时:

<select id="getBlogById" resultType="Blog" parameterType=int>select id,title,author,contentfrom blog where id=#{id}
</select>

打印出执行的sql语句,会看到sql是这样的:

select id,title,author,content from blog where id = ?

不管输入什么参数,打印出的sql都是这样的。这是因为mybatis启用了预编译功能,在sql执行前,会先将上面的sql发送给数据库进行编译,执行时,直接使用编译好的sql,替换占位符“?”就可以了。因为sql注入只能对编译过程起作用,所以像#{}这样预编译成?的方式就很好地避免了sql注入的问题。

mybatis是如何做到sql预编译的呢?

其实在框架底层,是jdbc中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的sql语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行一个sql时,能够提高效率,原因是sql已编译好,再次执行时无需再编译。

使用${}

<select id="orderBlog" resultType="Blog" parameterType=”map”>select id,title,author,contentfrom blog order by ${orderParam}
</select>

仔细观察,内联参数的格式由“#{xxx}”变为了${xxx}。如果我们给参数“orderParam”赋值为”id”,将sql打印出来,是这样的:

select id,title,author,contet from blog order by id

显然,这样是无法阻止sql注入的,参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“${}”这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。

其实,这些都在Java面试库小程序上都有答案,如果你近期准备面试跳槽,建议在上面刷题,涵盖 2000+ 道 Java 面试题,几乎覆盖了所有主流技术面试题。

  1. SpringBoot中如何防止XSS攻击和sql注入
    对于Xss攻击和Sql注入,我们可以通过过滤器来搞定,可根据业务需要排除部分请求

① 创建Xss请求过滤类XssHttpServletRequestWraper
在这里插入图片描述

代码如下:

public class XssHttpServletRequestWraper extends HttpServletRequestWrapper {Logger log = LoggerFactory.getLogger(this.getClass());public XssHttpServletRequestWraper() {super(null);}public XssHttpServletRequestWraper(HttpServletRequest httpservletrequest) {super(httpservletrequest);}//过滤springmvc中的 @RequestParam 注解中的参数public String[] getParameterValues(String s) {String str[] = super.getParameterValues(s);if (str == null) {return null;}int i = str.length;String as1[] = new String[i];for (int j = 0; j < i; j++) {//System.out.println("getParameterValues:"+str[j]);as1[j] = cleanXSS(cleanSQLInject(str[j]));}log.info("XssHttpServletRequestWraper净化后的请求为:==========" + as1);return as1;}//过滤request.getParameter的参数public String getParameter(String s) {String s1 = super.getParameter(s);if (s1 == null) {return null;} else {String s2 = cleanXSS(cleanSQLInject(s1));log.info("XssHttpServletRequestWraper净化后的请求为:==========" + s2);return s2;}}//过滤请求体 json 格式的@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ());return new ServletInputStream() {@Overridepublic int read() throws IOException {return bais.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) { }};}public   String inputHandlers(ServletInputStream servletInputStream){StringBuilder sb = new StringBuilder();BufferedReader reader = null;try {reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));String line = "";while ((line = reader.readLine()) != null) {sb.append(line);}} catch (IOException e) {e.printStackTrace();} finally {if (servletInputStream != null) {try {servletInputStream.close();} catch (IOException e) {e.printStackTrace();}}if (reader != null) {try {reader.close();} catch (IOException e) {e.printStackTrace();}}}return  cleanXSS(sb.toString ());}public String cleanXSS(String src) {String temp = src;src = src.replaceAll("<", "<").replaceAll(">", ">");src = src.replaceAll("\\(", "(").replaceAll("\\)", ")");src = src.replaceAll("'", "'");src = src.replaceAll(";", ";");//bgh 2018/05/30  新增/**-----------------------start--------------------------*/src = src.replaceAll("<", "& lt;").replaceAll(">", "& gt;");src = src.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41");src = src.replaceAll("eval\\((.*)\\)", "");src = src.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");src = src.replaceAll("script", "");src = src.replaceAll("link", "");src = src.replaceAll("frame", "");/**-----------------------end--------------------------*/Pattern pattern = Pattern.compile("(eval\\((.*)\\)|script)",Pattern.CASE_INSENSITIVE);Matcher matcher = pattern.matcher(src);src = matcher.replaceAll("");pattern = Pattern.compile("[\\\"\\'][\\s]*javascript:(.*)[\\\"\\']",Pattern.CASE_INSENSITIVE);matcher = pattern.matcher(src);src = matcher.replaceAll("\"\"");// 增加脚本src = src.replaceAll("script", "").replaceAll(";", "")/*.replaceAll("\"", "").replaceAll("@", "")*/.replaceAll("0x0d", "").replaceAll("0x0a", "");if (!temp.equals(src)) {// System.out.println("输入信息存在xss攻击!");// System.out.println("原始输入信息-->" + temp);// System.out.println("处理后信息-->" + src);log.error("xss攻击检查:参数含有非法攻击字符,已禁止继续访问!!");log.error("原始输入信息-->" + temp);throw new CustomerException("xss攻击检查:参数含有非法攻击字符,已禁止继续访问!!");}return src;}//输出public void outputMsgByOutputStream(HttpServletResponse response, String msg) throws IOException {ServletOutputStream outputStream = response.getOutputStream(); //获取输出流response.setHeader("content-type", "text/html;charset=UTF-8"); //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码byte[] dataByteArr = msg.getBytes("UTF-8");// 将字符转换成字节数组,指定以UTF-8编码进行转换outputStream.write(dataByteArr);// 使用OutputStream流向客户端输出字节数组}// 需要增加通配,过滤大小写组合public String cleanSQLInject(String src) {String lowSrc = src.toLowerCase();String temp = src;String lowSrcAfter = lowSrc.replaceAll("insert", "forbidI").replaceAll("select", "forbidS").replaceAll("update", "forbidU").replaceAll("delete", "forbidD").replaceAll("and", "forbidA").replaceAll("or", "forbidO");if (!lowSrcAfter.equals(lowSrc)) {log.error("sql注入检查:输入信息存在SQL攻击!");log.error("原始输入信息-->" + temp);log.error("处理后信息-->" + lowSrc);throw new CustomerException("sql注入检查:参数含有非法攻击字符,已禁止继续访问!!");}return src;}}

② 把请求过滤类XssHttpServletRequestWraper添加到Filter中,注入容器

@Component
public class XssFilter implements Filter {Logger log  = LoggerFactory.getLogger(this.getClass());// 忽略权限检查的url地址private final String[] excludeUrls = new String[]{"null"};public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) arg0;HttpServletResponse response = (HttpServletResponse) arg1;String pathInfo = req.getPathInfo() == null ? "" : req.getPathInfo();//获取请求url的后两层String url = req.getServletPath() + pathInfo;//获取请求你ip后的全部路径String uri = req.getRequestURI();//注入xss过滤器实例XssHttpServletRequestWraper reqW = new XssHttpServletRequestWraper(req);//过滤掉不需要的Xss校验的地址for (String str : excludeUrls) {if (uri.indexOf(str) >= 0) {arg2.doFilter(arg0, response);return;}}//过滤arg2.doFilter(reqW, response);}public void destroy() {}public void init(FilterConfig filterconfig1) throws ServletException {}
}

上述代码已经可以完成 请求参数、JSON请求体 的过滤,但对于json请求体还有其他的方式实现,有兴趣的请看下面的扩展!

扩展:还可以重写spring中的MappingJackson2HttpMessageConverter来过滤Json请求体

因为请求体在进出Contoroller时,会经过MappingJackson2HttpMessageConverter的一个转换,把请求体转换成我们需要的json格式,所以可以在这里边做一些修改!

@Configuration
public class MyConfiguration {@Beanpublic MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter(){//自定义转换器MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();//转换器日期格式设置ObjectMapper objectMapper = new ObjectMapper();SimpleDateFormat smt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");objectMapper.setDateFormat(smt);converter.setObjectMapper(objectMapper);//转换器添加自定义Module扩展,主要是在这里做XSS过滤的!!,其他的是其他业务,不用看SimpleModule simpleModule = new SimpleModule();//添加过滤逻辑类!simpleModule.addDeserializer(String.class,new StringDeserializer());converter.getObjectMapper().registerModule(simpleModule);//设置中文编码格式List<MediaType> list = new ArrayList<>();list.add(MediaType.APPLICATION_JSON_UTF8);converter.setSupportedMediaTypes(list);return converter;}}
真正的过滤逻辑类StringDeserializer//检验请求体的参数
@Component
public class StringDeserializer extends JsonDeserializer<String> {@Overridepublic String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {String str = jsonParser.getText().trim();//sql注入拦截if (sqlInject(str)) {throw new CustomerException("参数含有非法攻击字符,已禁止继续访问!");}return xssClean(str);}public boolean sqlInject(String str) {if (StringUtils.isEmpty(str)) {return false;}//去掉'|"|;|\字符str = org.apache.commons.lang3.StringUtils.replace(str, "'", "");str = org.apache.commons.lang3.StringUtils.replace(str, "\"", "");str = org.apache.commons.lang3.StringUtils.replace(str, ";", "");str = org.apache.commons.lang3.StringUtils.replace(str, "\\", "");//转换成小写str = str.toLowerCase();//非法字符String[] keywords = {"master", "truncate", "insert", "select", "delete", "update", "declare", "alert","alter", "drop"};//判断是否包含非法字符for (String keyword : keywords) {if (str.indexOf(keyword) != -1) {return true;}}return false;}//xss攻击拦截public String xssClean(String value) {if (value == null || "".equals(value)) {return value;}//非法字符String[] keywords = {"<", ">", "<>", "()", ")", "(", "javascript:", "script","alter", "''","'"};//判断是否包含非法字符for (String keyword : keywords) {if (value.indexOf(keyword) != -1) {throw new CustomerException("参数含有非法攻击字符,已禁止继续访问!");}}return value;}
}

使用这种形式也可以完成json请求体的过滤,但个人更推荐使用XssHttpServletRequestWraper的形式来完成xss过滤!!

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

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

相关文章

iptables添加端口映射,k8s主机查询不到端口但能访问。

研究原因&#xff1a;k8s内一台主机使用命令查询没有80端口。但通过浏览器访问又能访问到服务。 查询了资料是使用了hostport方式暴露pod端口。cni调用iptables增加了DNAT规则。访问时流量先经过iptables直接被NAT到具体服务去了。 链接: K8s罪魁祸首之"HostPort劫持了我…

单例模式如何保证实例的唯一性

前言 什么是单例模式 指一个类只有一个实例&#xff0c;且该类能自行创建这个实例的一种创建型设计模式。使用目的&#xff1a;确保在整个系统中只能出现类的一个实例&#xff0c;即一个类只有一个对象。对于频繁使用的对象&#xff0c;“忽略”创建时的开销。特点&#xff1a…

快速上手Spring Cloud 七:事件驱动架构与Spring Cloud

快速上手Spring Cloud 一&#xff1a;Spring Cloud 简介 快速上手Spring Cloud 二&#xff1a;核心组件解析 快速上手Spring Cloud 三&#xff1a;API网关深入探索与实战应用 快速上手Spring Cloud 四&#xff1a;微服务治理与安全 快速上手Spring Cloud 五&#xff1a;Spring …

基于PaddleNLP的深度学习对文本自动添加标点符号(二)

前言 基于PaddleNLP的深度学习对文本自动添加标点符号的源码版来了&#xff0c;本篇文章主要讲解如何文本自动添加标点符号的原理和相关训练方法&#xff0c;前一篇文章讲解的是使用paddlepaddle已经训练好的一些模型&#xff0c;在一些简单场景下可以通过这些模型进行预测&…

【Unity】调整Player Settings的Resolution设置无效

【背景】 Build时修改了Player Settings下的Resolution设置&#xff0c;但是再次Building时仍然不生效。 【分析】 明显是沿用了之前的分辨率设定&#xff0c;所以盲猜解决办法是Build相关的缓存文件&#xff0c;或者修改打包名称。 【解决】 实测修改版本号无效&#xf…

指针数组的有趣程序【C语言】

文章目录 指针数组的有趣程序指针数组是什么&#xff1f;指针数组的魅力指针数组的应用示例&#xff1a;命令行计算器有趣的颜色打印 结语 指针数组的有趣程序 在C语言的世界里&#xff0c;指针是一种强大的工具&#xff0c;它不仅能够指向变量&#xff0c;还能指向数组&#…

[机缘参悟-162/管理者与领导者-151] :受害者心态与受害者思维模式,如何克服受害者思维模式,管理者如何管理这种思维模式的人?

目录 一、受害者心态概述 1.1 什么是受害者心态 1.2 受害者心态的表现形式 1.3 受害者心态在职场上的表现 1.4 受害者思维模式 1.5 受害者心态的危害 二、受害者心态的成因 2.1 概述 2.2 神经网络与受害者心态 三、如何克服受害者心态 3.1 概述 3.2 职场 3.3 家庭…

verilog 从入门到看得懂---verilog 的基本语法各种语句

本篇文章主要介绍verilog里面常用的语句&#xff0c; 包括条件语句、循环语句块语句和生成语句。出了块语句和生成语句&#xff0c;其他的基本和c语言或者m语言一致。 1&#xff0c;if 语句&#xff0c;在需要判断逻辑的时候可以使用if语句&#xff0c;如 从输入a&#xff0c;…

《QT实用小工具·二》图片文字转base64编码

1、概述 源码放在文章末尾 base64编码转换类 图片转base64字符串。base64字符串转图片。字符转base64字符串。base64字符串转字符。后期增加数据压缩。Qt6对base64编码转换进行了重写效率提升至少200%。 下面是demo演示&#xff1a; 项目部分代码如下所示&#xff1a; #ifn…

解决npm init vue@latest证书过期问题:npm ERR! code CERT_HAS_EXPIRED

目录 一. 问题背景 二. 错误信息 三. 解决方案 3.1 临时解决办法 3.2 安全性考量 一. 问题背景 我在试图创建一个新的Vue.js项目时遇到了一个问题&#xff1a;npm init vuelatest命令出现了证书过期的错误。不过这是一个常见的问题&#xff0c;解决起来也简单。 二. 错误…

【aws】架构图工具推荐

碎碎念 以前以为日本冰箱论是个梗&#xff0c;结果居然是真的。用光盘传真其实还能理解&#xff08;毕竟我也喜欢电子古董2333&#xff09;&#xff0c;但是画架构图居然用的是excel&#xff0b;截图&#xff01;啊苍天呐&#xff0c;然后看到隔壁工位用excel画web原型又感觉释…

Python 从0开始 一步步基于Django创建项目(13)将数据关联到用户

在city_infos应用程序中&#xff0c;每个城市信息条目是关联到城市的&#xff0c;所以只需要将城市条目关联到用户即可。 将数据关联到用户&#xff0c;就是把‘顶层’数据关联到用户。 设计思路&#xff1a; 1、修改顶层数据模型&#xff0c;向其中添加‘用户’属性 2、根…

kubernetes K8s的监控系统Prometheus升级Grafana,来一个酷炫的Node监控界面(二)

上一篇文章《kubernetes K8s的监控系统Prometheus安装使用(一)》中使用的监控界面总感觉监控的节点数据太少&#xff0c;不能快算精准的判断出数据节点运行的状况。 今天我找一款非常酷炫的多维度数据监控界面&#xff0c;能够非常有把握的了解到各节点的数据&#xff0c;以及运…

「DevExpress中文教程」如何将DevExtreme JS HTML编辑器集成到WinForms应用

在本文中我们将演示一个混合实现&#xff1a;如何将web UI工具集成到WinForms桌面应用程序中。具体来说&#xff0c;我们将把DevExtreme JavaScript WYSIWYG HTML编辑器(作为DevExtreme UI组件套件的一部分发布的组件)集成到Windows Forms应用程序中。 获取DevExtreme v23.2正式…

数据分析之Power BI

POWER QUERY 获取清洗 POWER PIVOT建模分析 如何加载power pivot 文件-选项-加载项-com加载项-转到 POWER VIEW 可视呈现 如何加载power view 文件-选项-自定义功能区-不在功能区中的命令-新建组-power view-添加-确定 POWER MAP可视地图

2.4 比较检验 机器学习

目录 常见比较检验方法 总述 2.4.1 假设检验 2.4.2 交叉验证T检验 2.4.3 McNemar 检验 接我们的上一篇《性能度量》&#xff0c;那么我们在某种度量下取得评估结果后&#xff0c;是否可以直接比较以评判优劣呢&#xff1f;实际上是不可以的。因为我们第一&#xff0c;测试…

uniapp h5 touch事件踩坑记录

场景&#xff1a;悬浮球功能 当我给悬浮球设置了 position: fixed; 然后监听悬浮球的touch事件&#xff0c;从事件对象中拿到clientY和clientX赋值给悬浮球的left和top属性。当直接赋值后效果应该是这样子&#xff1a; 注意鼠标相对悬浮球的位置&#xff0c;应该就是左上角&a…

在 Windows 11 上安装 MongoDB

MongoDB 是一个流行的 NoSQL 数据库&#xff0c;它提供了灵活的数据存储方案&#xff0c;而 MongoDB Compass 则是一个可视化管理工具&#xff0c;可以更轻松地与 MongoDB 数据库交互和管理。在本文中&#xff0c;我们将介绍如何在 Windows 11 上安装 MongoDB&#xff0c;并配置…

Radio Silence for mac 好用的防火墙软件

Radio Silence for Mac是一款功能强大的网络防火墙软件&#xff0c;专为Mac用户设计&#xff0c;旨在保护用户的隐私和网络安全。它具备实时网络监视和控制功能&#xff0c;可以精确显示每个网络连接的状态&#xff0c;让用户轻松掌握网络活动情况。 软件下载&#xff1a;Radio…

B2902A是德科技B2902A精密型电源

181/2461/8938产品概述&#xff1a; Agilent B2902A 精密源/测量单元 (SMU) 是一款 2 通道、紧凑且经济高效的台式 SMU&#xff0c;能够源和测量电压和电流。它用途广泛&#xff0c;可以轻松、高精度地执行 I/V&#xff08;电流与电压&#xff09;测量。4 象限源和测量功能的集…