跨站脚本攻击(Cross Site Scripting)本来的缩写为CSS,为了与层叠样式表(Cascading Style Sheets,CSS)的缩写进行区分,将跨站脚本攻击缩写为XSS。XSS 是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。攻击者利用XSS漏洞躲避访问控制——例如同源策略(same origin policy)。
XSS 攻击
XSS 攻击通常分为两种:
- 反射型
- 存储型
反射型即攻击脚本不需要存储,攻击脚本直接添加到 URL 参数里,未做 XSS 防范的服务器会解析参数并返回含有攻击脚本的页面给用户。
index.js
var express = require('express');
var router = express.Router();
var comment = null;
router.get('/', function(req, res, next) {
res.render('index');
});
router.get('/xss1', function(req, res, next) {
var xss = req.query.xss
res.render('index', { xss: xss });
});
router.get('/xss2', function(req, res, next) {
var xss = req.query.xss
res.set('X-XSS-Protection',0); // 关闭浏览器XSS拦截
res.render('index', { xss: xss });
});
router.post('/add', function(req, res, next) {
comment = req.body.comment;
res.render('index');
});
router.get('/get', function(req, res, next) {
res.render('index',{ comment: comment });
});
module.exports = router;
index.jade
extends layout
block content
h1 xss demo
//-'!='代表不转义
p!= xss
form(action="/add", method="post")
textarea(name="comment",rows=10,cols=50)
<br>
input(type="submit" value="提交评论")
<br>
p
a(href="/get") 获取评论
p!= comment
运行 express 并打开连接 http://localhost:3000/xss1?xss=<img src='null' onerror='alert(1)'>
结果:
可以看到,默认情况下,浏览器会拦截反射型 XSS 攻击,浏览器会判断待执行的脚本代码是否存在于浏览器的 URL 中,如果是,就不会执行,当然,可以通过设置 Header 强制执行。
运行http://localhost:3000/xss2?xss=<img src='null' onerror='alert(1)'>
结果:
以上是简单的反射型 XSS 攻击示例,在实际情况下,黑客会在攻击脚本里插入获取用户 cookie 的代码,获取成功后再将 cookie 信息通过链接发送到目标服务器。用户只要点击了该带有 XSS 攻击的链接,就有可能泄露自己的信息。
存储型 XSS 攻击一般需要服务器将黑客注入的脚本存储到服务器上,因为攻击脚本不在 URL 里,浏览器是无法拦截的,这种情况,只有在服务器端做防范。
打开连接 http://localhost:3000/
输入攻击脚本,点击添加按钮,然后再点击获取评论。此时,攻击脚本就执行了。
XSS 防范
明白原理,要防范 XSS 攻击就简单多了,防范主要是在后端进行,一般有如下几种方法:
- 将页面提交的内容进行转义。
- 如果需要处理标签,则将 script、link、style、iframe、frame 等标签过滤掉,另外 onerror、onclick 等事件属性也需要过滤掉。