资讯专栏INFORMATION COLUMN

XSS攻击原理分析与防御技术

garfileo / 981人阅读

摘要:跨站脚本攻击,缩写为。这就是攻击最简单的一个案例。漏洞产生的原因是攻击者注入的数据反映在响应中。而且富文本攻击的防御相对比较麻烦。默认配置下不允许执行内联代码块内容,内联事件,内联样式,以及禁止执行和。

跨站脚本攻击(Cross Site Scripting),缩写为XSS。恶意攻击者往Web页面里插入恶意javaScript代码,当用户浏览该页之时,嵌入其中Web里面的javaScript代码会被执行,从而达到恶意攻击用户的目的。

一个简单的XSS攻击

代码:

async function(ctx, next){
    ctx.set("X-XSS-Protection",0);
    ctx.render("index",{from:ctx.query.from});
};

注意:插入X-XSS-Protection头部使浏览器XSS拦截器失效。

开始攻击:

大家发现网页执行了一段脚本,而且这段脚本是用户恶意输入的。这就是XSS攻击最简单的一个案例。把原本应该显示纯文本的地方,执行了一段黑客写入的脚本。

那XSS攻击有什么危害呢?

1、盗取各类用户帐号
2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马
7、控制受害者机器向其它网站发起攻击

XSS攻击的分类

1、反射型

又称为非持久性跨站点脚本攻击。漏洞产生的原因是攻击者注入的数据反映在响应中。非持久型XSS攻击要求用户访问一个被攻击者篡改后的链接,用户访问该链接时,被植入的攻击脚本被用户游览器执行,从而达到攻击目的。也就是我上面举的那个简单的XSS攻击案例,通过url参数直接注入。然后在响应的数据中包含着危险的代码。

当黑客把这个链接发给你,你就中招啦!

2、存储型

又称为持久型跨站点脚本,它一般发生在XSS攻击向量(一般指XSS攻击代码)存储在网站数据库,当一个页面被用户打开的时候执行。持久的XSS相比非持久性XSS攻击危害性更大,容易造成蠕虫,因为每当用户打开页面,查看内容时脚本将自动执行。

该网页有一个发表评论的功能,该评论会写入后台数据库,并且访问主页的时候,会从数据库中加载出所有的评论。

当我添加一个评论,并且暗藏一个脚本,如下图:

当别人访问主页的时候,刚刚黑客写入的评论里面的脚本被浏览器当成代码执行了,用户莫名其妙受到攻击:

上面就是两种XSS攻击的两种基本类型。当然黑客不会弹出一个框框给你,告诉你被攻击,黑客不会这么傻的~他可以在用户不知情的情况下,盗取用户的cookie,改变网页业务逻辑等等。

XSS攻击的注入点

1、HTML节点内容
这个其实就是我之前演示的,HTML节点中暗藏攻击脚本。

2、HTML属性
这里img的src属性是由用户传递过来的值,当用户把图片地址写成:1"%20onerror="alert(%27哈哈被攻击%27)
大家看下面发生了什么:

3、JavaScript代码 (字符串提前关闭)
当JavaScript代码中有一个变量是由用户提供的数据,这个数据也有可能之前被写入了数据库。如下图,当用户输入的内容为:
小柚子";alert(%27哈哈你被攻击了!%27);"

4、富文本
大家都知道,富文本其实就是一段HTML。既然它是一段HTML,那么就存在XSS攻击。而且富文本攻击的防御相对比较麻烦。

XSS攻击防御

chrome浏览器自带防御,可拦截反射性XSS(HTML内容和属性),js和富文本的无法拦截,所以我们必须得自己做一些防御手段。

1、HTML节点内容的防御

将用户输入的内容进行转义:

var escapeHtml = function(str) {
    str = str.replace(/");
    return str;
}
ctx.render("index", {comments, from: escapeHtml(ctx.query.from || "")});

2、HTML属性的防御

对空格,单引号,双引号进行转义

var escapeHtmlProperty = function (str) {
    if(!str) return "";
    str = str.replace(/"/g,"&quto;");
    str = str.replace(/"/g,"'");
    str = str.replace(/ /g," ");
    return str;
}
ctx.render("index", {posts, comments,
    from:ctx.query.from || "",
    avatarId:escapeHtmlProperty(ctx.query.avatarId || "")});

3、JavaScript的防御

对引号进行转义

var escapeForJS = function(str){
        if(!str) return "";
        str = str.replace(//g,"");
        str = str.replace(/"/g,""");
        return str;
}

4、富文本的防御
富文本的情况非常的复杂,js可以藏在标签里,超链接url里,何种属性里。



所以我们不能过用上面的方法做简单的转义。因为情况实在太多了。

现在我们换个思路,
提供两种过滤的办法:

1)黑名单
我们可以把

"));

大家可以看到:

阅读需要支付1元查看
<