# 跨站请求伪造(CSRF,Cross Site request forgery),也称为XSRF

# 概念

  • 攻击者利用技术手段欺骗用户的浏览器去访问曾经认证过的网站,并触发一些操作
  • 由于浏览器曾经认证过,所以被访问的网站,会认为是真正的用户操作而去运行

# 本质

  • 攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来说,这个请求是完全合理合法的,但是却完成了攻击者所期望的操作。
  • 有两个关键点,一,用户需要知道你的业务接口二,浏览器主流方案通过cookie实现会话机制

# 解决方案-CSRF防护

  • 每个session需要有一个与之相绑定的CSRF-TOKEN
  • 理论上来说,这个CSRF-TOKEN的存储不应该使用浏览器的cookie机制,但某框架并没有遵循这个原则;

# springSecurity的CsrfFilter

  • 该过滤器允许配置白名单
  • 该过滤器要求,白名单外的每个访问链接都必须具有cookie,否则不允许放行
  • 该过滤器默认情况下,先于AbstractAuthenticationProcessingFilter、FilterSecurityInterceptor生效

# 跨站脚本攻击(XSS,Cross Site Scripting)

# 概念

  • 本应该缩写为CSS,为了与层叠样式表区分,故取为XSS
  • 此类攻击的核心为 脚本

# 分类

  • 反射型XSS攻击
    • 通过特定手法,诱导用户去点击含有恶意代码的URL
    • 常用来窃取客户端cookie以及 钓鱼欺骗
  • DOM-based型XSS攻击
    • 客户端的脚本程序,可以动态的检查和修改页面内容,而不依赖服务端的数据
    • 如富文本输入,并预览;
  • 存储型XSS攻击
    • 攻击者事先将恶意代码上传,或储存到漏洞服务器中
    • 受害者浏览包含恶意代码的页面,就会执行恶意代码

# 防护(主要针对存储型XSS攻击)

  • 转码
    • 程序层面 (StringUtils.htmlEscape,StringUtils.htmlUnescape)
    • 基础设施层面 Filer将所有的半码字符转为全码字符
  • 替换
    • 通过Filter,替换关键字
import org.apache.commons.lang3.StringUtils;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author automannn
 * @Date 2022/6/23
 */
public class XssCleanUtil {
    private static List<Pattern> patterns = null;


    private static List<Object[]> getXssPatternList() {
        List<Object[]> ret = new ArrayList();
        ret.add(new Object[]{"<(no)?script[^>]*>.*?</(no)?script>", 2});
        ret.add(new Object[]{"eval\\((.*?)\\)", 42});
        ret.add(new Object[]{"expression\\((.*?)\\)", 42});
        ret.add(new Object[]{"(javascript:|vbscript:|view-source:)*", 2});
        ret.add(new Object[]{"(window\\.location|window\\.|\\.location|document\\.cookie|document\\.|alert\\(.*?\\)|window\\.open\\()*", 42});
        ret.add(new Object[]{"<+\\s*\\w*\\s*.*\\s*(oncontrolselect|oncopy|oncut|ondataavailable|ondatasetchanged|ondatasetcomplete|ondblclick|ondeactivate|ondrag|ondragend|ondragenter|ondragleave|ondragover|ondragstart|ondrop|onerror|onerroupdate|onfilterchange|onfinish|onfocus|onfocusin|onfocusout|onhelp|onkeydown|onkeypress|onkeyup|onlayoutcomplete|onload|onlosecapture|onmousedown|onmouseenter|onmouseleave|onmousemove|onmousout|onmouseover|onmouseup|onmousewheel|onmove|onmoveend|onmovestart|onabort|onactivate|onafterprint|onafterupdate|onbefore|onbeforeactivate|onbeforecopy|onbeforecut|onbeforedeactivate|onbeforeeditocus|onbeforepaste|onbeforeprint|onbeforeunload|onbeforeupdate|onblur|onbounce|oncellchange|onchange|onclick|oncontextmenu|onpaste|onpropertychange|onreadystatechange|onreset|onresize|onresizend|onresizestart|onrowenter|onrowexit|onrowsdelete|onrowsinserted|onscroll|onselect|onselectionchange|onselectstart|onstart|onstop|onsubmit|onunload|ontoggle|onshow|onbeforeonload|onhashchange|onmessage|onoffline|ononline|onpagehide|onpageshow|onpopstate|onredo|onstorage|onundo|onformchange|onforminput|oninput|oninvalid|oncanplay|oncanplaythrough|ondurationchange|onemptied|onended|onloadeddata|onloadedmetadata|onloadstart|onpause|onplay|onplaying|onprogress|onratechange|onseeked|onseeking|onstalled|onsuspend|ontimeupdate|onvolumechange|onwaiting)+\\s*=+", 42});
        return ret;
    }

    private static List<Pattern> getPatterns() {
        if (patterns == null) {
            List<Pattern> list = new ArrayList();
            Iterator var4 = getXssPatternList().iterator();

            while (var4.hasNext()) {
                Object[] arr = (Object[]) var4.next();
                String regex = (String) arr[0];
                Integer flag = (Integer) arr[1];
                list.add(Pattern.compile(regex, flag));
            }

            patterns = list;
        }

        return patterns;
    }

    public static String stripXss(String value) {
        if (StringUtils.isNotBlank(value)) {
            Iterator var2 = getPatterns().iterator();

            while (var2.hasNext()) {
                Pattern pattern = (Pattern) var2.next();
                Matcher matcher = pattern.matcher(value);
                if (matcher.find()) {
                    value = matcher.replaceAll("");
                }
            }
        }

        return value;
    }

    public static String clean(String originalContent) {
        String target = stripXss(originalContent);
        return target;
    }
}

# 跨域

# 同源

  • 同源指的是:协议,域名,端口相同
  • 浏览器出于安全方面的考虑,只允许本域名下的接口交互,不同源的客户端脚本,在没有明确授权的情况下,不能读写对方的资源

# 同源的分类

  • DOM同源策略: 禁止对不同源页面DOM进行操作。主要针对iframe
  • XHR同源策略: 禁止使用XHR对象,向不同源的服务器地址发起HTTP请求

# 同源策略造成的影响

  • Cookie、LocalStorage 和 IndexDB无法读取
  • DOM和JS对象无法获取
  • Ajax请求发送不出去

# 跨域的类型

  • 协议型跨域
  • 域名型跨域
  • 端口型跨域

# 跨域资源共享(Cross-Origin Resource Sharing)

# 概念

  • 它是由浏览器的同源策略造成的,是对 javaScript实施的安全限制
  • 一种允许当前域的资源被其他域的脚本请求访问的机制

# 何时触发跨域检查

  • Cors将请求分为简答请求与复杂请求
  • 简单请求满足的条件:
    • 使用方法为 GET、HEAD、POST
    • Content-Type的值为: text/plain、multipart/form-data、application/x-www-form-urlencoded
  • 不符合简单请求条件的便是复杂请求,复杂请求正式通信前,会进行cors预检

# springWeb的CorsFilter

  • springSecurity对其进行了原生支持
  • 可以通过参数的方式,指定allowed-origins、allowed-header、allowed-method
  • cors可配置白名单(理论上,所有基于Filter的功能都可配置白名单)

# 跨站

# 概念

  • 两个地址的**eTLD+1不同,则为跨站**
  • eTLD 为 effective top-level domain,有效顶级域名,如:.com,.cn,.top等等
  • eTLD+1为顶级域名+二级域名,如:.cnautomannn.cn

# 跨站与跨域的区别

  • 跨域分为三类:协议跨域,主机跨域,端口跨域
  • 跨站只考虑主机段(如果是ip的话),不考虑协议和端口