防止跨站脚本攻击XSS之Antisamy

目录

一、什么是跨站脚本攻击(XSS)

二、通常有哪些解决方案

三、常见的XSS攻击例子有哪些

3.1 存储型XSS攻击(黑产恶意截流,跳转不法网站)

3.2反射型XSS攻击:

四、什么是跨站请求伪造?

五、常用跨站请求伪造解决方案有哪些

六、Springboot3.x整合Antisamy解决存储型XSS攻击

6.0 需求描述

6.1 Antisamy和Jsoup选型

6.2 Antisamy整合Springboot3.x详细步骤

第一步:引入pom.xml

第二步:根据源码中的xml文件,自定义自己需要的

第三步:将xml文件加载进Spring容器中

第四步:因Antisamy处理过文本后,会默认在标签最后加入\n ,所以加入这步骤去除\n

 第五步:方法调用

第六步:方法调用中的后处理


一、什么是跨站脚本攻击(XSS)

XSS攻击是指攻击者将恶意脚本注入到Web页面中,当用户访问被注入的页面时
恶意脚本会在用户浏览器中执行从而窃取用户的敏感信息或进行其他恶意操作。

二、通常有哪些解决方案

对用户输入进行有效的过滤和验证,特别是在展示用户输入内容时。

使用安全的编码机制,如HTML编码和URL编码。

对Cookie设置HttpOnly属性,限制脚本访问敏感信息。

阻止不受信任的域名或URL的内容插入到页面中

三、常见的XSS攻击例子有哪些

3.1 存储型XSS攻击(黑产恶意截流,跳转不法网站)

攻击者将恶意脚本存储在目标网站的数据库中,当其他用户访问包含该恶意脚本的页面时,脚本会被执行

这种攻击利用了网站对用户输入的不当处理,比如某个商品的评论列表,用户进入这个页面则自动跳去其他页面

<script>
  var maliciousCode = 'alert("你的账户信息已被攻击,请输入密码并发送给攻击者:")';
  // 假设这里是漏洞存在的页面,用户的输入没有进行过滤或转义
  var userInput = 'Hello, ' + maliciousCode;
  document.getElementById('content').innerHTML = userInput; // 恶意脚本被存储并执行
</script>

3.2反射型XSS攻击

攻击者通过诱使受害者点击包含恶意脚本的特制链接,将恶意脚本作为参数传递给目标网站

网站在返回响应时会将恶意脚本包含在其中,并被浏览器执行

<!-- 假设这里是漏洞存在的搜索页面,用户的输入没有进行过滤或转义 -->
<form action="/search" method="GET">
  <input type="text" name="query" value="">
  <button type="submit">搜索</button>
</form>

<!-- 攻击者构造的恶意链接 -->
<a href="/search?query=<script>alert('你的账户信息已被攻击,请输入密码并发送给攻击者:')</script>">点击此处获取免费礼品</a>


四、什么是跨站请求伪造?

跨站请求伪造(Cross-Site Request Forgery,CSRF),是一种利用受信任的用户身份执行未经授权的操作的攻击方式。
攻击者通过伪造请求,利用用户在目标网站中的登录状态来执行恶意操作或窃取用户的敏感信息

五、常用跨站请求伪造解决方案有哪些

引入CSRF令牌(token),并将其包含到表单或请求中,校验Referer头部,确保请求来自合法的来源。

String csrfToken = UUID.randomUUID().toString();

response.addCookie(CookieUtil.generateCookie("_csrf_", csrfToken));

使用验证码、双因素身份验证、HTTPS等也是增加安全性的有效措施,以确保用户与目标网站的交互是安全和可信的

启用SameSite属性,限制Cookie的发送,防止未经用户许可的跨站请求。


六、Springboot3.x整合Antisamy解决存储型XSS攻击

6.0 需求描述

支持对输入的文本内容支持自定义标签属性拦截(比如 输入的内容中不可以包含BUTTON、INPUT)

支持对输入内容进行正则过滤(比如 img标签中 文件地址只可以是jpg后缀结尾的)

6.1 Antisamy和Jsoup选型

Antisamy是什么?

AntiSamy是一个开源的Java库,主要用于防止跨站脚本攻击(XSS)和CSS注入攻击。它通过对用户输入的HTML和CSS进行验证和清理,确保其中不包含恶意代码

Jsoup是什么? 


Jsoup是一个用于处理HTML的Java库,它提供了非常方便的API,允许用户解析、修改和清理HTML文档。Jsoup专注于HTML的解析和操作,而不直接涉及安全性验证。

单纯从标签的转义拦截上,2者都是可以的,当前需求中包含正则过滤等要求,使用Jsoup实现比较麻烦,需要二次代码覆盖开发,固调研后采用Antisamy。 

6.2 Antisamy整合Springboot3.x详细步骤

Antisamy源码地址:https://github.com/nahsra/antisamy/tree/v1.7.5

第一步:引入pom.xml

   <dependency>
                <groupId>org.owasp.antisamy</groupId>
                <artifactId>antisamy</artifactId>
                <version>1.7.5</version>
 </dependency>

第二步:根据源码中的xml文件,自定义自己需要的

本博文中的xml是最基础的,仅作参考样例使用,需要了解配置详情的可以去其它博文或者官网查看,本文重点在整合SpringBoot3.x

<?xml version="1.0" encoding="ISO-8859-1"?>

<!-- W3C rules retrieved from: http://www.w3.org/TR/html401/struct/global.html -->

<!-- Slashdot allowed tags taken from "Reply" page: <b> <i> <p> <br> <a> <ol> <ul> <li> <dl> <dt> <dd> <em> <strong> <tt> <blockquote> <div>
    <ecode> <quote> -->

<anti-samy-rules xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="antisamy.xsd">

    <directives>
        <directive name="omitXmlDeclaration" value="true" />
        <directive name="omitDoctypeDeclaration" value="true" />
        <directive name="maxInputSize" value="5000" />
        <directive name="formatOutput" value="true" />
        <directive name="embedStyleSheets" value="false" />
    </directives>

    <common-regexps>
        <regexp name="imgTypes"
                value="^.*\.(gif|jpg|jpeg|png)$" />
        <regexp name="anything" value=".*" />

    </common-regexps>

    <common-attributes>
        <attribute name="abbr"><regexp-list><regexp name="anything" /></regexp-list></attribute>//除了abbr属性之外,其余都会被转义删除
     </common-attributes>

    <global-tag-attributes>
        <attribute name="abbr" />
    </global-tag-attributes>

    <tags-to-encode>
    </tags-to-encode>
<!-- tag-rules The configured label is allowed to pass-->
    <tag-rules>
        <tag name="a" action="validate" />//除这里面配置的标签之外,其余都会被转义删除
       
        <tag name="img" action="validate"> //img标签的src中 文件后缀只能是gif|jpg|jpeg|png配置之一
            <attribute name="src">
                <regexp-list>
                    <regexp name="imgTypes" />
                </regexp-list>
            </attribute>
        </tag>
    </tag-rules>

    <css-rules>

    </css-rules>
    <!-- allowed-empty-tags Allow the tag to be empty, allow the tag inside the attribute does not belong to the tag, this case will not be escaped and deleted-->
    <allowed-empty-tags>
        <literal-list>
            <literal value="a" />
        </literal-list>
    </allowed-empty-tags>

</anti-samy-rules>

第三步:将xml文件加载进Spring容器中

@Configuration
public class AntiSamyConfig {
    @Bean
    public AntiSamyContent antiSamyBean() throws  Exception{
        try (InputStream inputStream = getClass().getResourceAsStream("/antisamy175/antisamy_custom.xml")) {
            Policy policy = Policy.getInstance(inputStream);
            return new AntiSamyContent (policy);
        }
    }
}

注意文件存放路径,resources目录下建个 antisamy175 文件夹。再将xml放进去

第四步:因Antisamy处理过文本后,会默认在标签最后加入\n ,所以加入这步骤去除\n

public class AntiSamyOutputFormatter extends AntiSamySAXScanner {
    public AntiSamyOutputFormatter (Policy policy) {
        super(policy);
    }
    @Override
    protected OutputFormat getOutputFormat() {
        OutputFormat format = super.getOutputFormat();
        format.setLineSeparator("");//这是为了去除antisamy处理后在每行结尾自动匹配的\n
        return format;
    }

}

public class AntiSamyContent extends AntiSamy {
    private Policy policy = null;
    public AntiSamyContent (Policy policy) {
        super(policy);
        this.policy = policy;
    }
    public CleanResults scanMeetingAgenda(String taintedHTML) throws ScanException {
        return (new AntiSamyOutputFormatter (this.policy)).scan(taintedHTML);
    }
}

 第五步:方法调用

htmlSanitizerService.sanitizeHtml(str);

第六步:方法调用中的后处理

antisamy处理结果,在实际页面展示时,会存在换行 回车等问题,注重回显的需要对这块做额外的处理。

@Service
public class HtmlSanitizerService {
    private AntiSamyContent  antiSamy;
    @Autowired
    public HtmlSanitizerService(AntiSamyContent  antiSamy) {
        this.antiSamy = antiSamy;
    }

    public String sanitizeHtml(String sourceStr) {
        String cleanStr = sourceStr;
        try{

            CleanResults cr = antiSamy.scanMeetingAgenda(sourceStr);
            cleanStr =  cr.getCleanHTML();
        }catch (ScanException e){
        }
        return cleanStr;
    }
}

至此,本次分享已结束。提及的文本过滤方式,其最大的亮点在于其直观性和灵活性。我们无需编写冗长的Java代码逻辑,而是可以直接通过修改XML配置文件来实现文本内容的过滤。更值得一提的是,XML内部支持正则表达式的使用,这使得过滤规则的设置变得更加简洁高效。相较于传统的文本处理库(如jsoup),这种方式不仅减少了代码量,还提高了开发和维护的效率。

希望本次分享的内容能够为您在文本处理方面提供一些新的思路和方法。感谢您的阅读,期待与您共同探讨更多有趣的技术话题!

  • 12
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值