XSS

0x00 概述

概述了XSS漏洞的主要类型和利用方式、防御手段

0x01 漏洞简介

Cross-Site Scripting(为了与CSS区别,安全领域叫做XSS)攻击是注入的一种,主要是将恶意脚本注入到可信站点的HTML页面等网页文件中,当攻击者将注入恶意脚本的网页连接发送给用户,用户打开链接,浏览器会认为恶意脚本来自可信站点而执行

XSS攻击发生在

  • 数据通过不可信源进入Web应用程序,最常见的是Web请求
  • 数据被包含在动态内容中,该动态内容被发送到Web用户而不被验证为恶意内容,发送到Web浏览器的恶意内容通常采用JS的一种形式,但也可以包括HTML、Flash或者浏览器可执行的任何其他类型代码

XSS的攻击效果

  • 基于XSS的攻击种类几乎是无限的
  • 它们通常包括向攻击者发送诸如Cookie或其他会话信息之类的私有数据,将受害者重定向到攻击者控制的Web内容,或者在用户的机器上执行其他恶意操作
  • 因为客户端JS等脚本语言的灵活性,XSS攻击可以和其他攻击方式在合适场景中相结合,造成更大的破坏

举个例子

服务端处理逻辑

@app.route("/")
def index():
    param = request.args.get("param", "")
    response = make_response("<p>Hello {}<p>".format(param))
    response.set_cookie("key", "value", httponly=False)  # 关闭框架自带的httponly=true
    response.headers["X-XSS-Protection"] = 0  # Chrome本身的XSS防御关闭
    return response

构造一个恶意URLhttp://test.com/param=<script>alert(document.cookie)</script>

浏览器打开后可以看到页面的反馈,弹出一个弹框,带有设置的key: value的Cookie

实际攻击可以将上述代码逻辑修改为,通过Ajax把Cookie信息发送到攻击者服务器,攻击者就可以盗取用户身份访问站点

0x02 威胁场景

Reflected XSS(反射型XSS)

反射型XSS是用户输入直接作为响应的一部分作为服务器输出,如用户提交的表单、URL作为错误信息、搜索结果返回给用户,攻击者构造恶意的URL,Web表单发送给用户,用户点击就会触发

比如上面漏洞介绍里举的例子就是反射型XSS

Stored XSS(存储型XSS)

存储型XSS会把用户输入的数据“存储”到服务端,往往是数据库,往往具有更强的稳定性和破坏性,产生这种漏洞的页面功能往往是 往往是论坛消息、访问者日志、评论字段等

举个例子

我们在类似QQ空间的Web系统中提交文章和评论,会被存储在服务器数据库中,我们可以根据文章ID查询到文章内容

文章的显示页面逻辑往往如下

@app.route("/")
def index():
    post_id = request.args.get("id", "")
    post = db.query(post_id=post_id).first()
    response = make_response("<textview> {}<textview>".format(post.content))
    response.set_cookie("key", "value", httponly=False)  # 关闭框架自带的httponly=true
    response.headers["X-XSS-Protection"] = 0  # Chrome本身的XSS防御关闭
    return response

可以看到逻辑和上面反射型XSS基本是一样的,当用户将<script>alert(document.cookie)</scirpt>一类的攻击脚本写入文章,其他用户访问时便会触发XSS

存储型XSS由于不用在URL中构造恶意脚本也更容易对用户进行钓鱼,不易被识别

DOM Based XSS(DOM型的XSS)

以上两种XSS是根据恶意脚本是否能持久化(保存在服务端)进行划分的,DOM Based XSS从效果上来说也是反射型XSS,但因为成因特别,就单独作为一类

我们把修改页面DOM节点形成的XSS,称为DOM Based XSS

比如前端页面的代码为

<p>Select your language:</p>
<select>
<script>
document.write("<OPTION value=1>"+document.location.href.substring(document.location.href.indexOf("default=")+8)+"</OPTION>");
document.write("<OPTION value=2>English</OPTION>");
</script>
</select>

普通情况下的正常请求是http://www.some.site/page.html?default=French

恶意请求http://www.some.site/page.html?default=<script>alert(document.cookie)</script>

我们发现上面这样的请求和反射型XSS差不多,那么为什么DOM型XSS要单独分为一类呢

还是上面的页面,假如我们的服务器对XSS有着非常好的过滤和编码方式,请求从服务器返回时类似<script>,document.cookie,alert这些字段都去掉了,那有什么办法再生成XSS攻击呢

我们把URL变成http://www.some.site/page.html#default=<script>alert(document.cookie)</script>,我们可以发现此时攻击仍然能够生效

URL有个特点,#被称为锚点,用于定位页面位置,#符号后的内容不会传输到服务器

再进一步思考,反射型和存储型XSS中,参数值为恶意脚本,服务器端没有经过检查和过滤将恶意脚本拼接到了HTML页面中,浏览器加载页面执行脚本造成了XSS攻击,而通过URL锚点触发的XSS没有经过服务器,浏览器充当服务器角色拼接脚本到HTML页面中

笔者认为在B/S构架中,越来越灵活的Web使得浏览器和JS充当了一个客户端里的小型服务器,对用户的部分响应不需要再经过真正服务端的处理,预置在页面JS脚本中的一部分函数和功能直接处理了用户输入输出,或者对服务器的返回进行再处理,因此DOM型XSS也是针对浏览器和JS这个小型服务器的攻击,才被单独作为一类

除了上面例子中href.location获取参数外,还要注意一些请求参数在服务器端经过一定的编码和过滤,但仍然可以通过DOM的改变对这些参数再一次进行处理,所以要注意防御XSS是防御最后浏览器显示的页面,而对DOM改变的操作相当于返回给用户的页面不用从真正服务端给出,而是浏览器和JS给出的

XSS的利用方式

基本上XSS能够做到事就是JS一类的脚本能做到的事,这里举一些XSS的利用方式,但不具体说明

  • 盗取用户Cookie(登录态)
  • 构造GET、POST等HTTP方法模拟网站逻辑以劫持用户身份执行(类似CSRF)
  • 盗取页面数据,如一下用户敏感信息
  • 识别用户浏览器
  • 识别用户访问历史
  • XSS蠕虫

0x03 修复方式

编码转换

这是防御XSS中最重要最有效的一步,服务端对要输出给用户的Web文件内容做以下编码转换(实体编码),同理,如果JS改变了DOM,也要在JS中对数据内容进行以下编码,对于用户的输入输出更要重点处理

& --> &amp;
< --> &lt;
> --> &gt;
" --> &quot;
/ --> &#x2F;
' --> &#x27;     单引号也有转换成&apos;的情况,但是不推荐,因为这种转换不在HTML的规范中,而是在XML和XHTML的规范中 

随着前端技术的发展,使用类似Angular JSVUE JS的框架,本身自带编码转换,了解相关模块的配置之后使用

使用Cookie的httponly标识

为Cookie字段带上httponly的标识,可以防止JS读取Cookie信息,因此可以有效防止XSS攻击中盗取用户Cookie的能力

但是这种方式不是防御了XSS漏洞,只是减少了XSS漏洞造成的损失,但依旧十分有效,前端页面不需要读取Cookie的话尽量为每个Cookie配置这个标识

使用X-XSS-Protection头部进行防御

浏览器本身内置了XSS的防御审计工具,可以通过X-XSS-Protection进行配置,但是浏览器的防御攻击也是人写的代码,本身具有安全隐患

X-XSS-Protection的安全隐患

建议在看明白上文后使用,建议按需求使用X-XSS-Protection: 1; mode=blockX-XSS-Protection: 0两种配置

XSS过滤

存在一些情况,比如富文本,不能使用HTML实体编码的方式进行XSS防御,因为富文本中需要用到HTML标签来显示,在了解需求的情况下使用白名单进行过滤,因为XSS攻击的灵活只推荐使用白名单

设置白名单需要对XSS的可以利用的HTML标签和位置有一定了解,参考OWASP的开源项目anti-samy

不使用Flash

Flash已淘汰,不推荐使用

0x04 深入攻防

无需讲解,靠手熟,熟了之后靠漏洞情报,推荐一些漏洞靶场(关卡)

靶场一:http://xss-quiz.int21h.jp/

靶场一的答案

靶场二:http://prompt.ml/0

靶场二的答案

靶场三:https://alf.nu/alert1

答案自己探索

0x05 总结

本文简介的XSS漏洞的类型、成因、修复方式等等

XSS的漏洞难点在系统越复杂、交互越多越容易发生问题,并且因为其灵活,容易绕过过滤手段

对于开发来说,对XSS有了解,有防御的意识,在非必要使用一些标签的情况下,对输出进行实体编码,一定要使用标签时,有考虑防御XSS的问题即可

0x06 参考资料

OWASP Cross-site_Scripting

[OWASP XSS_(Cross_Site_Scripting)Prevention_Cheat_Sheet](https://www.owasp.org/index.php/XSS(Cross_Site_Scripting)_Prevention_Cheat_Sheet)

OWASP DOM_based_XSS_Prevention_Cheat_Sheet

知道创宇技能表

坚持原创技术分享,您的支持将鼓励我继续创作!