整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

SpringBoot如何防止XSS脚本攻击?

么是XSS脚本攻击?

XSS(Cross-Site Scripting,跨站脚本攻击)是一种常见的 Web 攻击技术,攻击者通过在 Web 页面中插入恶意的脚本代码,使得用户在浏览页面时执行这些脚本,从而达到攻击的目的。通常被分为如下的三种类型。

存储型 XSS(Stored XSS)

攻击者将恶意脚本代码存储在服务器上的数据库或文件中,当用户访问包含这些恶意代码的页面时,会执行这些代码。

反射型 XSS(Reflected XSS)

攻击者将恶意脚本代码作为参数注入到URL中,当用户点击包含这些恶意参数的URL时,服务器端将参数反射回页面并执行,从而触发XSS攻击。

DOM 型 XSS(DOM-based XSS)

攻击者利用客户端脚本对DOM(Document Object Model,文档对象模型)进行操作的漏洞,通过修改页面的DOM结构来执行恶意代码。

常见的XSS攻击防御手段

  • 过滤和清理用户输入数据,移除或转义HTML标签和特殊字符
  • 使用 Content Security Policy(CSP)来限制页面资源加载和执行的范围。
  • 使用安全的编码函数来处理用户输入和输出,如HTML编码、URL编码等
  • 对于敏感操作和数据,使用HttpOnly标记和Secure标记来设置Cookie的属性,防止被窃取和劫持。
  • 对于存储型XSS,严格控制用户输入的内容,并对输入数据进行验证和过滤。
  • 对于反射型XSS,验证和过滤所有用户提交的数据,包括URL参数、表单数据等。
  • 对于DOM型XSS,避免直接使用用户输入的数据操作DOM,尽量使用安全的DOM操作方式。

如何实现?

SpringBoot可以通过使用过滤器或拦截器来对请求参数进行过滤和清理,防止恶意的XSS脚本注入。下面是一种通过过滤器实现防止XSS攻击的方法。

创建一个自定义的过滤器,用于过滤请求中的参数,并清理其中的HTML标签和特殊字符。

@WebFilter("/*")
public class XSSFilter implements Filter {
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        // 初始化操作,可以留空
    }
    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        chain.doFilter(new XSSRequestWrapper((HttpServletRequest) request), response);
    }
    @Override
    public void destroy() {
        // 销毁操作,可以留空
    }
    static class XSSRequestWrapper extends HttpServletRequestWrapper {
        XSSRequestWrapper(HttpServletRequest request) {
            super(request);
        }
        @Override
        public String getParameter(String name) {
            String value = super.getParameter(name);
            if (value != null) {
                value = cleanXSS(value);
            }
            return value;
        }
        private String cleanXSS(String value) {
            // 进行 XSS 过滤,清理 HTML 标签和特殊字符
            // 例如,可以使用正则表达式或者第三方库进行过滤
            // 这里只是简单示例,具体过滤规则需根据实际情况自行设计
            return value.replaceAll("<", "<")
                        .replaceAll(">", ">")
                        .replaceAll("\"", """)
                        .replaceAll("'", "'")
                        .replaceAll("&", "&");
        }
    }
}

在SpringBoot应用的配置类中注册该过滤器。

@Bean
public FilterRegistrationBean<XSSFilter> xssFilterRegistration() {
    FilterRegistrationBean<XSSFilter> registration = new FilterRegistrationBean<>();
    registration.setFilter(new XSSFilter());
    registration.addUrlPatterns("/*");
    registration.setName("xssFilter");
    registration.setOrder(1);
    return registration;
}

上述代码,我们创建了一个名为XSSFilter的过滤器,在doFilter方法中,对请求进行过滤,并在需要时使用XSSRequestWrapper对请求参数进行清理。清理过程中,我们简单地将 HTML 标签和一些特殊字符替换为相应的转义序列,以防止恶意脚本注入。

请注意,这只是一种简单的示例,实际场景中应根据具体情况制定更为严格的过滤规则。

互联网诞生起,安全威胁就--直伴随着网站的发展,各种Web攻击和信息泄露也从未停止。2011年中国互联网领域爆出两桩比较大的安全事故,一桩是新浪微博遭XSS攻击,另一桩是以CSDN为代表的多个网站泄露用户密码和个人信息。特别是后者,因为影响人群广泛,部分受影响网站涉及用户实体资产和交易安全,一时成为舆论焦点。



这里列举常用的几中攻击方式:

一、XSS攻击

xss攻击即跨站点脚本攻击( Cross Site Script), 指黑客通过篡改网页,注入恶意HTML脚本,保存在网站的服务器,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。

XSS攻击相对而言是一种“古老”的攻击手段,却又历久弥新,不断变化出新的攻击花样,许多以前认为不可能用来攻击的漏洞也逐渐被攻击者利用。因此XSS防攻击也是非常复杂的。主要手段有如下两种。

1、过滤消毒

xss攻击者一般都是通过在请求中嵌入恶意脚本达到攻击的目的,这些脚本是一般用户输入中不使用的,如果进行过滤和消毒处理,即对某些html 危险字符转义,如“>”转义为“>"、“<”转义为“<” 等,就可以防止大部分攻击。为了避免对不必要的内容错误转义,如“3<5”中的“<”需要进行文本匹配后再转义,如“<img src=”这样的上下文中的“<" 才转义。事实上,消毒几乎是所有网站最必备的XSS防攻击手段。

2、HttpOnly

最早由微软提出,即浏览器禁止页面JavaScript访问带有HttpOnly属性的Cookie。

HttpOnly并不是直接对抗XSS攻击的,而是防止XSS攻击者窃取Cookie。对于存放敏感

信息的Cookie,如用户认证信息等,可通过对该Cookie添加HttpOnly属性,避免被攻击

脚本窃取。


二、注入攻击

注入攻击主要有两种形式,SQL 注入攻击和OS注入攻击。SQL注入攻击的原理如下。攻击者在HTTP请求中注入恶意SQL命令( drop table users;),服务器用请求参数构造数据库SQL命令时,恶意SQL被一起构造,并在数据库中执行。


SQL注入攻击需要攻击者对数据库结构有所了解才能进行,攻击者获取数据库表结构信息的手段有如下几种:比如网站使用了开源的组件、错误提示返回数据结构信息等。常用防御方式有两种:

1、过滤

和防XSS攻击一样,请求参数消毒是一种比较简单粗暴又有效的手段。通过正则匹配,过滤请求数据中可能注入的SQL,如“ drop table" 、“ \b(?:updatelb.*?\bset|delete\b\W*?\bfrom)b"等。

2、参数绑定

使用预编译手段,绑定参数是最好的防SQL注入方法。目前许多数据访问层框架,如IBatis, Hibernate等,都实现SQL预编译和参数绑定,攻击者的恶意SQL会被当做SQL的参数,而不是SQL命令被执行。

除了SQL注入,攻击者还根据具体应用,注入OS命令、编程语言代码等,利用程序漏洞,达到攻击目的。


三、CSRF攻击

CSRF ( Cross Site Request Forgery,跨站点请求伪造),攻击者通过跨站请求,以合法用户的身份进行非法操作,如转账交易、发表评论等。CSRF的主要手法是利用跨站请求,在用户不知情的情况下,以用户的身份伪造请求。其核心是利用了浏览器Cookie或服务器Session策略,盗取用户身份。


相应地,CSRF的防御手段主要是识别请求者身份。主要有下面几种方法。

1、表单token

CSRF是一个伪造用户请求的操作,所以需要构造用户请求的所有参数才可以。表单Token通过在请求参数中增加随机数的办法来阻止攻击者获得所有请求参数:在页面表单中增加一个随机数作为Token,每次响应页面的Token都不相同,从正常页面提交的请求会包含该Token值,而伪造的请求无法获得该值,服务器检查请求参数中Token的值是否存在并且正确以确定请求提交者是否合法。

2、验证码

相对说来,验证码则更加简单有效,即请求提交时,需要用户输入验证码,以避免在用户不知情的情况下被攻击者伪造请求。但是输入验证码是一个糟糕的用户体验,所以请在必要时使用,如支付交易等关键页面。

3、Referer check

HTTP请求头的Referer域中记录着请求来源,可通过检查请求来源,验证其是否合法。很多网站使用这个功能实现图片防盗链(如果图片访问的页面来源不是来自自己网站的网页就拒绝)。


三、其他攻击和漏洞

以上只是列举常见的三种,还有一些其他的也常被黑客利用,比如错误堆栈信息直接返回敏感信息,HTML注释有敏感信息,文件上传只没有限制文件类型(黑客上传恶意脚本),路径遍厉等

天,从开发人员的角度,说说《如何防范常见的Web攻击》话题。

SQL注入攻击

SQL注入攻击,这个是最常聊到的话题,使用过Java的开发人员,第一个反应就是一定要使用预编译的PrepareStatement,是吧?

什么是SQL注入攻击

攻击者在HTTP请求中注入恶意的SQL代码,服务器使用参数构建数据库SQL命令时,恶意SQL被一起构造,并在数据库中执行。

用户登录,输入用户名 lianggzone,密码 ‘ or ‘1’=’1 ,如果此时使用参数构造的方式,就会出现

select * from user 
 where name = 'lianggzone' 
 and password = '' or '1'='1'

不管用户名和密码是什么内容,使查询出来的用户列表不为空。

现在还会存在SQL注入攻击么

这个问题在使用了预编译的PrepareStatement后,安全性得到了很大的提高,但是真实情况下,很多同学并不重视,还是会留下漏洞的。举个例子,看看,大家的代码中对 sql 中 in 操作,使用了预编译,还是仍然还是通过字符串拼接呢?

如何防范SQL注入攻击

使用预编译的PrepareStatement是必须的,但是一般我们会从两个方面同时入手。

Web端

  • 有效性检验。
  • 限制字符串输入的长度。

服务端

  • 不用拼接 SQL 字符串。
  • 使用预编译的 PrepareStatement。
  • 有效性检验。(为什么服务端还要做有效性检验?第一准则,外部都是不可信的,防止攻击者绕过Web端请求)
  • 过滤 SQL 需要的参数中的特殊字符。比如单引号、双引号。

XSS攻击

什么是XSS攻击

跨站点脚本攻击,指攻击者通过篡改网页,嵌入恶意脚本程序,在用户浏览网页时,控制用户浏览器进行恶意操作的一种攻击方式。

假设页面上有一个表单

<input type="text" name="name" value="梁桂钊"/>

如果,用户输入的不是一个正常的字符串,而是

"/><script>alert("haha")</script><!-

此时,页面变成下面的内容,在输入框input的后面带上了一段脚本代码。

<input type="text" name="name" value="梁桂钊"/><script>alert("haha")</script><!-"/>

这端脚本程序只是弹出一个消息框,并不会造成什么危害,攻击的威力取决于用户输入了什么样的脚本,只要稍微修改,便可使攻击极具攻击性。

XSS攻击有多可怕

蛮早之前,我曾经找了几个网站做个测试,其实大家对XSS攻击的防范还是不够,都成功的注入了测试脚本。

甚至,还有攻击者提交恶意的javascript代码的评论信息或者反馈信息(这些信息,正常客户端没有做xss校验,会存在客户端注入问题),所有访问者访问该内容时,都会执行这段恶意的javascript代码。

如何防范XSS攻击

  • 前端,服务端,同时需要字符串输入的长度限制。
  • 前端,服务端,同时需要对HTML转义处理。将其中的”<”,”>”等特殊字符进行转义编码。

CSRF攻击

什么是CSRF攻击

跨站点请求伪造,指攻击者通过跨站请求,以合法的用户的身份进行非法操作。可以这么理解CSRF攻击:攻击者盗用你的身份,以你的名义向第三方网站发送恶意请求。CRSF能做的事情包括利用你的身份发邮件,发短信,进行交易转账,甚至盗取账号信息。

如何防范CSRF攻击

  • 安全框架,例如Spring Security。
  • token机制。在HTTP请求中进行token验证,如果请求中没有token或者token内容不正确,则认为CSRF攻击而拒绝该请求。
  • 验证码。通常情况下,验证码能够很好的遏制CSRF攻击,但是很多情况下,出于用户体验考虑,验证码只能作为一种辅助手段,而不是最主要的解决方案。
  • referer识别。在HTTP Header中有一个字段Referer,它记录了HTTP请求的来源地址。如果Referer是其他网站,就有可能是CSRF攻击,则拒绝该请求。但是,服务器并非都能取到Referer。很多用户出于隐私保护的考虑,限制了Referer的发送。在某些情况下,浏览器也不会发送Referer,例如HTTPS跳转到HTTP。

文件上传漏洞

什么是文件上传漏洞

文件上传漏洞,指的是用户上传一个可执行的脚本文件,并通过此脚本文件获得了执行服务端命令的能力。

许多第三方框架、服务,都曾经被爆出文件上传漏洞,比如很早之前的Struts2,以及富文本编辑器等等,可能被一旦被攻击者上传恶意代码,有可能服务端就被人黑了。

如何防范文件上传漏洞

  • 文件上传的目录设置为不可执行。
  • 判断文件类型。在判断文件类型的时候,可以结合使用MIME Type,后缀检查等方式。因为对于上传文件,不能简单地通过后缀名称来判断文件的类型,因为攻击者可以将可执行文件的后缀名称改为图片或其他后缀类型,诱导用户执行。
  • 对上传的文件类型进行白名单校验,只允许上传可靠类型。
  • 上传的文件需要进行重新命名,使攻击者无法猜想上传文件的访问路径,将极大地增加攻击成本,同时向shell.php.rar.ara这种文件,因为重命名而无法成功实施攻击。
  • 限制上传文件的大小。
  • 单独设置文件服务器的域名。

访问控制

一般来说,“基于URL的访问控制”是最常见的。

垂直权限管理

访问控制实际上是建立用户与权限之间的对应关系,即“基于角色的访问控制”,RBAC。不同角色的权限有高低之分。高权限角色访问低权限角色的资源往往是被允许的,而低权限角色访问高权限的资源往往被禁止的。在配置权限时,应当使用“最小权限原则”,并使用“默认拒绝”的策略,只对有需要的主体单独配置”允许”的策略,这在很多时候能够避免发生“越权访问”。

例如,Spring Security, Apache Shiro都可以建立垂直权限管理。

水平权限管理

水平权限问题在同一个角色上,系统只验证了访问数据的角色,没有对角色内的用户做细分,由于水平权限管理是系统缺乏一个数据级的访问控制所造成的,因此水平权限管理又可以称之为“基于数据的访问控制”。

举个理解,比如我们之前的一个助手产品,客户端用户删除评论功能,如果没有做水平权限管理,即设置只有本人才可以删除自己的评论,那么用户通过修改评论id就可以删除别人的评论这个就存在危险的越权操作。

这个层面,基本需要我们业务层面去处理,但是这个也是最为经常遗落的安全点。

总结

上面列举的几个话题,都是我在开发过程中,遇到的比较常见的Web安全话题,以及一些防范方案,需要我们在开发过程中及时规避,而不是依靠安全人员或者真正用户,甚至恶意的攻击者帮我们去发现问题。当然,还有很多Web安全话题,例如远程执行漏洞、拒绝服务攻击、Session保持攻击等等

喜欢的小伙伴,点个关注吧!