这本 HTTP 方面的小册子还蛮不错,已经二刷了 ?
这次做了一些笔记,方便自己和其他人翻阅和复习,因为这本书是 2014 年出的初版,所以有一些不怎么常用的技术,笔记中就省略了,只记一些比较常用的 ~
如果希望获取本书的 PDF 资源,可以关注文末二维码加微信群找群主要~
通常使用的网络(包括互联网)是在 TCP/IP 协议族的基础上运作,而 HTTP 属于它内部的一个子集。
按层次分为以下 4 层:应用层、传输层、网络层和数据链路层。
利用 TCP/IP 协议族进行网络通信时,会通过分层顺序与对方进行通信。发送端从应用层往下走,接收端则往应用层往上走。
以 HTTP 为例,一次通信的过程
发送端在层与层之间传输数据时,每经过一层时必定会被打上一个该层所属的首部信息。反之,接收端在层与层传输数据时,每经过一层时会把对应的首部消去。
这种把数据信息包装起来的做法称为封装(encapsulate)。
为了准确无误地将数据送达目标处,TCP 协议采用了三次握手(three-way handshaking)策略。握手过程中使用了 TCP 的标志(flag) —— SYN(synchronize) 和 ACK(acknowledgement)。
发送端首先发送一个带 SYN 标志的数据包给对方。接收端收到后,回传一个带有 SYN/ACK 标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK 标志的数据包,代表“握手”结束。
发送端首先发送一个带 SYN 标志的数据包给对方。接收端收到后,回传一个带有 SYN/ACK 标志的数据包以示传达确认信息。最后,发送端再回传一个带 ACK 标志的数据包,代表“握手”结束。
DNS(Domain Name System)服务是和 HTTP 协议一样位于应用层的协议。它提供域名到 IP 地址之间的解析服务。
通过这张图来了解下 IP 协议、TCP 协议和 DNS 服务在使用 HTTP 协议的通信过程中各自发挥了哪些作用。
了解一下 URI 的各部分
http:
或 https:
等协议方案名获取访问资源时要指定协议类型。不区分字母大小写,最后附一个冒号。也可使用 data:
或 javascript:
这类指定数据或脚本程序的方案名。hackr.jp
这种 DNS 可解析的名称,或是 192.168.1.1
这类 IPv4 地址名,还可以是 [0:0:0:0:0:0:0:1]
这样用方括号括起来的 IPv6 地址名。HTTP 是一种不保存状态,即无状态(stateless)协议。HTTP 协议自身不对请求和响应之间的通信状态进行保存。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把 HTTP 协议设计成如此简单的。
HTTP1.1 虽然是无状态协议,但为了实现期望的保持状态功能,于是引入了 Cookie 技术。
方法 | 说明 | 支持的 HTTP 协议版本 |
---|---|---|
GET | 获取资源 | 1.0、1.1 |
POST | 传输实体主体 | 1.0、1.1 |
PUT | 传输文件 | 1.0、1.1 |
HEAD | 获得报文首部 | 1.0、1.1 |
DELETE | 删除文件 | 1.0、1.1 |
OPTIONS | 询问支持的方法 | 1.1 |
TRACE | 追踪路径 | 1.1 |
CONNECT | 要求用隧道协议连接代理 | 1.1 |
LINK | 建立和资源之间的联系 | 1.0 |
UNLINE | 断开连接关系 | 1.0 |
LINK 和 UNLINK 已被 HTTP1.1 废弃,不再支持。
HTTP 协议的初始版本中,每进行一次 HTTP 通信就要断开一次 TCP 连接。
比如,使用浏览器浏览一个包含多张图片的 HTML 页面时,在发送请求访问 HTML 页面资源的同时,也会请求该 HTML 页面里包含的其他资源。因此,每次的请求都会造成无谓的 TCP 连接建立和断开,增加通信量的开销。
HTTP1.1 和一部分的 HTTP1.0 想出了持久连接(keep-alive)的方法。持久连接的特点是,只要任意一端没有明确提出断开连接,则保持 TCP 连接状态。
持久连接的好处在于减少了 TCP 连接的重复建立和断开所造成的额外开销,减轻了服务器端的负载。另外,减少开销的那部分时间,使 HTTP 请求和响应能够更早地结束,这样 Web 页面的显示速度也就相应提高了。
在 HTTP1.1 中,所有的连接默认都是持久连接,但在 HTTP1.0 内并未标准化。
持久连接使得多数请求以管线化(pipelining)方式发送成为可能。从前发送请求后需等待并收到响应,才能发送下一个请求。管线化技术出现后,不用等待响应亦可直接发送下一个请求。
这样就能够做到同时并行发送多个请求,而不需要一个接一个地等待响应了。
用持久连接可以让请求更快结束。而管线化技术则比持久连接还要快。请求数越多,时间差就越明显。
HTTP 是无状态协议,它不对之前发生过的请求和响应的状态进行管理。也就是说,无法根据之前的状态进行本次的请求处理。
假设要求登录认证的 Web 页面本身无法进行状态的管理(不记录已登录的状态),那么每次跳转新页面不是要再次登录,就是要在每次请求报文中附加参数来管理登录状态。
Cookie 技术通过在请求和响应报文中写入 Cookie 信息来控制客户端的状态。Cookie 会根据从服务器端发送的响应报文内的一个叫做 Set-Cookie
的首部字段信息,通知客户端保存 Cookie。当下次客户端再往该服务器发送请求时,客户端会自动在请求报文中加入 Cookie 值后发送出去。
HTTP 可以在传输过程中通过编码提升传输速率。
内容编码指明应用在实体内容上的编码格式,并保持实体信息原样压缩。
常用的内容编码有:gzip(GNU zip)、compress(UNIX 系统的标准压缩)deflate(zlib)、identity(不进行编码)
在 HTTP 通信过程中,请求的编码实体资源尚未全部传输完成之前,浏览器无法显示请求页面。在传输大容量数据时,通过把数据分割成多块,能够让浏览器逐步显示页面。这种把实体主体分块的功能称为分块传输编码(Chunked Transfer Coding)。
分块传输编码会将实体主体分成多个部分(块)。每一块都会用十六进制来标记块的大小,而实体主体的最后一块会使用“0(CR+LF)”来标记。
使用分块传输编码的实体主体会由接收的客户端负责解码,恢复到编码前的实体主体。
在 HTTP 报文中使用多部分对象集合时,需要在首部字段里加上 Content-type
:
如果下载过程中遇到网络中断的情况,那就必须重头开始。为了解决上述问题,需要一种可恢复的机制。所谓恢复是指能从之前下载中断处恢复下载。
要实现该功能需要指定下载的实体范围,指定范围发送的请求叫做范围请求(Range Request)。针对范围请求,响应会返回状态码 206。
比如:
Range: bytes=5001-10000
Range: bytes=5001-
Range: bytes=-3000, 5000-7000
内容协商机制是指客户端和服务器端就响应的资源内容进行交涉,然后提供给客户端最为适合的资源。内容协商会以响应资源的语言、字符集、编码方式等作为判断的基准。
包含在请求报文中的某些首部字段(如下)就是判断的基准:Accept
、Accept-Charset
、Accept-Encoding
、Accept-Language
、Content-Language
有以下几种类型:
状态码的职责是当客户端向服务器端发送请求时,描述返回的请求结果。借助状态码,用户可以知道服务器端是正常处理了请求,还是出现了错误。
数字中的第一位指定了响应类别,后两位无分类
类别 | 原因短语 | |
---|---|---|
1XX | Informational(信息性状态码) | 接收的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
请求被正常处理了。
浏览器需要执行某些特殊的处理以正确处理请求。
If-Match
、If-Modified-Since
、If-None-Match
、If-Range
、If-Unmodified-Since
中任一首部时,服务器端允许请求访问资源,但未满足条件的情况。304 状态码返回时,不包含任何响应的主体部分。304 虽然被划分在 3XX 类别中,但是和重定向没有关系。客户端发生了错误。
WWW-Authenticate
首部用以质询用户信息。当浏览器初次接收到 401 响应,会弹出认证用的对话窗口。服务器本身发生错误。
RetryAfter
首部字段再返回给客户端。一台 Web 服务器可搭建多个独立域名的 Web 网站,也可作为通信路径上的中转服务器提升传输效率。
HTTP1.1 规范允许一个服务器搭建多个 Web 站点,这是虚拟主机(Virtual Host,又称虚拟服务器)功能。
如果一台服务器内托管了两个域名,对应的同一个服务器 IP,当收到请求时就需要弄清楚究竟要访问哪个域名,由于虚拟主机可以寄存多个不同主机名和域名的 Web 网站,因此在发送 HTTP 请求时,必须在 Host
首部内完整指定主机名或域名的 URI。
这些应用程序和服务器可以将请求转发给通信线路上的下一站服务器,并且能接收从那台服务器发送的响应再转发给客户端。
缓存是指代理服务器或客户端本地保存的资源副本,是代理服务器的一种。
优势在于避免多次从源服务器转发资源,客户端可就近从缓存服务器上获取资源,而源服务器也不必多次处理相同请求。
客户端的缓存: 浏览器缓存如果有效,不必再向服务器请求,而直接从本地读取。当判定缓存过期后,会向源服务器确认资源的有效性。若判断浏览器缓存失效,浏览器会再次请求新资源。
HTTP 协议的请求和响应报文中必定包含 HTTP 首部,请求报文大约是下面的结构,响应报文类似
HTTP 首部字段将定义成缓存代理和非缓存代理的行为,分成 2 种类型。
下面列举了 HTTP1.1 中的逐跳首部字段。除这 8 个首部字段之外,其他所有字段都属于端到端首部。
HTTP 首部根据用途被分为 4 种 HTTP 首部字段类型,在 HTTP 协议通信交互中使用到的首部字段,不限于 RFC2616 中定义的 47 种。还有 Cookie、Set-Cookie 和 Content-Disposition 等在其他 RFC 中定义的,使用频率也很高。
请求报文和响应报文两方都会使用的首部。
首部字段名 | 说明 |
---|---|
Cache-Control | 控制缓存的行为 |
Connection | 逐跳首部、连接的管理 |
Date | 创建报文的日期时间 |
Pragma | 报文指令 |
Trailer | 报文末端的首部一览 |
Transfer-Encoding | 指定报文主体的传输编码方式 |
Upgrade | 升级为其他协议 |
Via | 代理服务器的相关信息 |
Warning | 错误通知 |
从客户端向服务器端发送请求报文时使用的首部。补充了请求的附加内容、客户端信息、响应内容相关优先级等信息。
首部字段名 | 说明 |
---|---|
Accept | 用户代理可处理的媒体类型 |
Accept-Charset | 优先的字符集 |
Accept-Encoding | 优先的内容编码 |
Accept-Language | 优先的语言(自然语言) |
Authorization | Web认证信息 |
Expect | 期待服务器的特定行为 |
From | 用户的电子邮箱地址 |
Host | 请求资源所在服务器 |
If-Match | 比较实体标记(ETag) |
If-Modified-Since | 比较资源的更新时间 |
If-None-Match | 比较实体标记(与 If-Match 相反) |
If-Range | 资源未更新时发送实体 Byte 的范围请求 |
If-Unmodified-Since | 比较资源的更新时间(与If-Modified-Since相反) |
Max-Forwards | 最大传输逐跳数 |
Proxy-Authorization | 代理服务器要求客户端的认证信息 |
Range | 实体的字节范围请求 |
Referer | 对请求中 URI 的原始获取方 |
TE | 传输编码的优先级 |
User-Agent | HTTP 客户端程序的信息 |
从服务器端向客户端返回响应报文时使用的首部。补充了响应的附加内容,也会要求客户端附加额外的内容信息。
首部字段名 | 说明 |
---|---|
Accept-Ranges | 是否接受字节范围请求 |
Age | 推算资源创建经过时间 |
ETag | 资源的匹配信息 |
Location | 令客户端重定向至指定URI |
Proxy-Authenticate | 代理服务器对客户端的认证信息 |
Retry-After | 对再次发起请求的时机要求 |
Server | HTTP服务器的安装信息 |
Vary | 代理服务器缓存的管理信息 |
WWW-Authenticate | 服务器对客户端的认证信息 |
针对请求报文和响应报文的实体部分使用的首部。补充了资源内容更新时间等与实体有关的信息。
首部字段名 | 说明 |
---|---|
Allow | 资源可支持的HTTP方法 |
Content-Encoding | 实体主体适用的编码方式 |
Content-Language | 实体主体的自然语言 |
Content-Length | 实体主体的大小(单位:字节) |
Content-Location | 替代对应资源的URI |
Content-MD5 | 实体主体的报文摘要 |
Content-Range | 实体主体的位置范围 |
Content-Type | 实体主体的媒体类型 |
Expires | 实体主体过期的日期时间 |
Last-Modified | 资源的最后修改日期时间 |
通用首部字段是指请求报文和响应报文都会使用的首部。
no-cache
,表示客户端将不会接收缓存过的响应,缓存服务器必须把客户端请求转发给源服务器。服务器响应中包含 no-cache
,那么缓存服务器不能对资源进行缓存,源服务器以后也将不再对缓存服务器请求中提出的资源有效性进行确认,且禁止其对响应资源进行缓存操作。从字面意思上很容易把 no-cache
误解成为不缓存,但 no-cache
代表不缓存过期的资源,缓存会向源服务器进行有效期确认后处理资源,no-store 才是真正地不进行缓存。
Connection
首部字段,可控制不再转发给代理的首部字段(即 Hop-by-hop 首部)。Connection
首部字段为 Close
。HTTP1.1 之前默认都是非持久连接。为此,如果想在旧版本 HTTP 协议上持续连接,则需设置 Connection
首部字段为 Keep-Alive
。表明创建 HTTP 报文的日期和时间。
用于检测 HTTP 协议及其他协议是否可使用更高的版本进行通信,其参数值可以用来指定一个完全不同的通信协议。
从客户端往服务器端发送请求报文中所使用的字段,用于补充请求的附加信息、客户端信息、对响应内容相关的优先级等内容。
通知服务器,用户代理能够处理的媒体类型及媒体类型的相对优先级。可使用 type/subtype
这种形式,一次指定多种媒体类型。
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
告知服务器,请求的资源所处的互联网主机名和端口号。Host 首部字段在 HTTP1.1 规范内是唯一一个必须被包含在请求内的首部字段。
请求被发送至服务器时,主机名会直接用 IP 地址。但如果这时,相同的 IP 地址下部署多个域名,那么服务器就会无法理解究竟是哪个域名对应的请求。因此,就需要使用首部字段 Host
来明确指出请求的主机名。若服务器未设定主机名,那直接设空值即可。
形如 If-xxx 这种,都可称为条件请求。服务器接收到后,只有判断指定条件为真时,才会执行请求。
首部字段 If-Match,属附带条件之一,它会告知服务器匹配资源所用的实体标记(ETag)值。这时的服务器无法使用弱 ETag 值。服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致时,才会执行请求。
可以用星号 *
,服务器会忽略 ETag
的值,只要资源存在就处理请求。
和 If-Match
作用相反,用于指定 If-None-Match
的实体标记 ETag
值与请求资源的 ETag
不一致时,它就告知服务器处理该请求。
如果在 If-Modified-Since
字段指定的日期时间后资源发生了更新,服务器会接受请求。
指定 If-Modified-Since
字段值的日期时间之后,请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200
,如果请求的资源没有更新,则返回状态码 304 Not Modified 的响应。
If-Unmodified-Since
和 If-Modified-Since
的作用相反。它的作用的是告知服务器,指定的请求资源只有在指定日期时间之后未发生更新,才处理请求。如果在指定日期时间后发生了更新,则以状态码 412 Precondition Failed 作为响应返回。
If-Range
字段如果跟 ETag 值或更新的日期时间一致,那么就作为范围请求处理。反之,则返回全体资源。
由服务器端向客户端返回响应报文中所使用的字段,用于补充响应的附加信息、服务器信息,以及对客户端的附加要求等信息。
实体标识,将资源以字符串形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag
值。当资源更新时,ETag
值也需要更新。
若在下载过程中出现连接中断、再连接的情况,都会依照 ETag
值来指定资源。
包含在请求报文和响应报文中的实体部分所使用的首部,用于补充内容的更新时间等与实体相关的信息。
通知客户端能够支持的所有 HTTP 方法。当服务器接收到不支持的 HTTP 方法时,会以状态码 405 Method Not Allowed 作为响应返回。与此同时,还会把所有能支持的 HTTP 方法写入首部字段 Allow
后返回。
告知客户端服务器对实体的主体部分选用的内容编码方式。内容编码是指在不丢失实体信息的前提下所进行的压缩。
主要有:gzip、compress、deflate、identity
表明了实体主体部分的大小(单位是字节)。对实体主体进行内容编码传输时,不能再使用 Content-Length
首部字段。
说明了实体主体内对象的媒体类型,用 type/subtype 形式赋值。
Content-Type: text/html; charset=UTF-8
Expires
会将资源失效的日期告知客户端。缓存服务器在收到有 Expires
的响应后,会以缓存来应答请求,在 Expires
字段值指定的时间之前,响应的副本会一直被保存。当超过指定的时间后,缓存服务器在请求发送过来时,会转向源服务器请求资源。
源服务器不希望缓存服务器对资源缓存时,最好在 Expires
字段内写入与 Date
相同的时间值。
但是,当首部字段 Cache-Control
有指定 max-age
时,比起 Expires
,会优先处理 max-age
指令。
包含源头服务器认定的资源做出修改的日期及时间。
首部字段名 | 说明 | 首部类型 |
---|---|---|
Set-Cookie | 开始状态管理所使用的Cookie信息 | 响应首部字段 |
Cookie | 服务器接收到的Cookie信息 | 请求首部字段 |
Set-Cookie: status=enable; expires=Tue, 05 Jul 2011 07:26:31 GMT; path=/; domain=.hackr.jp;
属性 | 说明 |
---|---|
NAME=VALUE | 赋予 Cookie 的名称和其值(必需项) |
expires=DATE | Cookie 的有效期(若不明确指定则默认为浏览器关闭前为止) |
path=PATH | 将服务器上的文件目录作为Cookie的适用对象(若不指定则默认为文档所在的文件目录) |
domain=域名 | 作为 Cookie 适用对象的域名 (若不指定则默认为创建 Cookie 的服务器的域名) |
Secure | 仅在 HTTPS 安全通信时才会发送 Cookie |
HttpOnly | 加以限制,使 Cookie 不能被 JavaScript 脚本访问 |
一旦 Cookie 从服务器端发送至客户端,服务器端就没有显式删除 Cookie 的方法。但可通过覆盖已过期的 Cookie,实现对客户端 Cookie 的实质性删除操作。
HttpOnly
属性是 Cookie 的扩展功能,它使 JavaScript 脚本无法获得 Cookie。其主要目的为防止跨站脚本攻击(Cross-site scripting,XSS)对 Cookie 的信息窃取。
Cookie: status=enable
当客户端想获得 HTTP 状态管理支持时,就会在请求中包含从服务器接收到的 Cookie。
是针对跨站脚本攻击(XSS)的一种对策,用于控制浏览器 XSS 防护机制的开关,可指定的字段值如下
HTTP 协议中有可能存在信息窃听或身份伪装等安全问题,使用 HTTPS 可以有效地防止这些问题。
把添加了加密及认证机制的 HTTP 称为 HTTPS(HTTP Secure)。HTTPS 并非是应用层的一种新协议,只是 HTTP 通信接口部分用 SSL(Secure Socket Layer)和 TLS(Transport Layer Security)协议代替而已。SSL 是独立于 HTTP 的协议,所以其他运行在应用层的 SMTP 和 Telnet 等协议均可配合 SSL 协议使用。
HTTPS 采用共享密钥加密和公开密钥加密两者并用的混合加密机制。若密钥能够实现安全交换,那么有可能会考虑仅使用公开密钥加密来通信。但是公开密钥加密与共享密钥加密相比,其处理速度要慢。
所以取长补短,在交换密钥环节使用公开密钥加密方式,之后的建立通信交换报文阶段则使用共享密钥加密方式。
数字证书认证机构(CA,Certificate Authority)和其相关机关颁发的公开密钥证书就是认证的可以信赖的公开密钥,服务器会将这份由数字证书认证机构颁发的公钥证书发送给客户端,以进行公开密钥加密方式通信。公钥证书也可叫做数字证书或直接称为证书。
HTTPS 通信的步骤:
在以上流程中,应用层发送数据时会附加一种叫做 MAC(Message Authentication Code)的报文摘要。MAC 能够查知报文是否遭到篡改,从而保护报文的完整性。
HTTPS 也存在一些问题,那就是当使用 SSL 时,它的处理速度会变慢。它慢分两种。一种是指通信慢。另一种是指由于大量消耗 CPU 及内存等资源,导致处理速度变慢。
和 HTTP 相比,HTTPS 网络负载可能会变慢 2 到 100 倍。除去和 TCP 连接、发送 HTTP 请求响应以外,还必须进行 SSL 通信,因此整体上处理通信量不可避免会增加。另外 SSL 必须进行加密处理,在服务器和客户端都需要进行加解密处理,比 HTTP 消耗更多硬件资源,导致负载增强。
针对速度变慢这一问题,并没有根本性的解决方案,一般会使用 SSL 加速器这种(专用服务器)硬件。能提高数倍 SSL 的计算速度,仅在 SSL 处理时发挥功效,分担负载。
与纯文本通信相比,加密通信会消耗更多的 CPU 及内存资源。如果每次通信都加密,会消耗相当多的资源,平摊到一台计算机上时,能够处理的请求数量必定也会随之减少。
如果是非敏感信息则使用 HTTP 通信,只有在包含个人信息等敏感数据时,才利用 HTTPS 加密通信。可以仅在那些需要信息隐藏时才加密,以节约资源。
除此之外,想要节约购买证书的开销也是原因之一。
一些页面只想让特定的人浏览,这就引入了认证功能。
HTTP1.1 常用的认证方式:
连接的发起方仍是客户端,一旦确立 WebSocket 通信连接,服务器与客户端任意一方都可向对方发送报文。
通信的建立:
Sec-WebSocket-Key
字段内记录着握手过程中必不可少的键值。Sec-WebSocket-Protocol
字段内记录使用的子协议。
Sec-WebSocket-Accept
的字段值是由握手请求中的 Sec-WebSocket-Key
的字段值生成的。
成功握手建立 WebSocket 连接之后,通信时不再使用 HTTP 的数据帧,而采用 WebSocket 独立的数据帧。
HTTP/2.0 的目标是改善用户在使用 Web 时的速度体验。特点:
HTML(HyperText Markup Language,超文本标记语言)是为了发送 Web 上的超文本(Hypertext)而开发的标记语言。
超文本是一种文档系统,可将文档中任意位置的信息与其他信息(文本或图片等)建立关联,即超链接文本。
Web 应用是指通过 Web 功能提供的应用程序。
CGI 每次接到请求,都要跟着启动一次,一旦访问量过大,Web 服务器要承担相当大的负载。而 Servlet 运行在与 Web 服务器相同的进程中,因此受到的负载较小。
Servlet 的运行环境叫做 Web 容器或 Servlet 容器。随着 CGI 的普及,每次请求都要启动新 CGI 程序的 CGI 运行机制逐渐变成了性能瓶颈。而 Servlet 常驻内存,在每次请求时,可启动相对进程级别更为轻量的 Servlet,程序的执行效率从而变得更高。
HTTP 协议本身并不存在安全性问题,服务器和客户端以及运行在服务器上的 Web 应用等资源才是攻击目标。
HTTP 就是一个通用的单纯协议机制,开发者需要自行设计并开发认证及会话管理功能来满足 Web 应用的安全,因此在运行的应用会隐藏着各种容易被攻击者滥用的安全漏洞。
从浏览器那接收到的 HTTP 请求的全部内容,都可以在客户端自由地变更、篡改。所以 Web 应用接受到的内容可能与预期数据不同。
在 HTTP 请求报文内加载攻击代码,就能发起对 Web 应用的攻击。通过 URL 查询字段或表单、HTTP 首部、Cookie 等途径把攻击代码传入,若这时 Web 应用存在安全漏洞,那内部信息就会遭到窃取,或被攻击者拿到管理权限。
对 Web 攻击的模式有主动攻击和被动攻击两种
指攻击者通过直接访问 Web 应用,把攻击代码传入的攻击模式。由于该模式是直接针对服务器上的资源进行攻击,因此攻击者需要能够访问到那些资源。
代表性的是 SQL 注入攻击和 OS 命令注入攻击。
指利用圈套策略执行攻击代码的攻击模式。在被动攻击过程中,攻击者不直接对目标 Web 应用访问发起攻击。
代表性的是跨站脚本攻击和跨站点请求伪造。
通常的攻击步骤
验证主要有两种:
一般验证数据是在客户端使用 JS,然而客户端的脚本是可以篡改的,所以不适合作为安全对策。
从数据库或文件系统、HTML、邮件等输出需处理的数据的时候,针对输出做值转义处理是一项至关重要的安全策略。当输出值转义不完全时,会触发攻击者传入的攻击代码。
跨站脚本攻击(Cross-Site Scripting,XSS)是指通过存在安全漏洞的客户端运行非法的 HTML 标签或 JavaScript 进行的一种攻击。动态创建的 HTML 部分有可能隐藏着安全漏洞。
如果用户填写的表单是直接作为 HTML 解析,那么换成 script
标签,就中招了。
SQL 注入(SQL Injection)是指针对 Web 应用使用的数据库,通过运行非法的 SQL 而产生的攻击。
如果在调用 SQL 语句的方式上存在疏漏,就可能被恶意注入(Injection)非法的 SQL 语句。
比如,如果把表单查询的字段直接拼接给 SQL 语句,那么可能会出现下面这个情况
上面一句查询的是 上野宣
,下面一句查询 上野宣'--
SELECT * FROM bookTbl WHERE author = '上野宣' and flag = 1;
SELECT * FROM bookTbl WHERE author = '上野宣'--' and flag = 1;
SQL 语句中的 --
之后全视为注释,因此 and flag=1
这个条件被自动忽略了,失去过滤条件,不想显示的内容也被显示出来了。
OS 命令注入攻击(OS Command Injection)是指通过 Web 应用,执行非法的操作系统命令达到攻击的目的。只要在能调用 Shell 函数的地方就有存在被攻击的风险。
HTTP 首部注入攻击(HTTP Header Injection)是指攻击者通过在响应首部字段内插入换行,添加任意响应首部或主体的一种攻击。属于被动攻击模式。
向首部主体内添加内容的攻击称为 HTTP 响应截断攻击(HTTP Response Splitting Attack)。
比如有时候 Web 应用有时会把从外部收到的值,赋给响应首部字段 Location
和 Set-Cookie
。如果攻击者发送 101%0D%0ASet-Cookie:+SID=123456789
这里的 %0D%0A
代表的是换行符,那么就会导致结果返回:
Location: http://example.com/?cat=101(%0D%0A :换行符)
Set-Cookie: SID=123456789
这里攻击者就可以修改任意的 Cookie
信息了。
这个例子中,原本应该属于首部字段 Location
的查询值部分,攻击者输入的 %0D%0A
成了换行符,结果插入了新的首部字段,实际上攻击者可以在响应中插入任意的首部字段。
HTTP 响应截断攻击是用在 HTTP 首部注入的一种攻击。
攻击顺序相同,但是要将两个 %0D%0A%0D%0A
并排插入字符串后发送。利用这两个连续的换行就可作出 HTTP 首部与主体分隔所需的空行了,这样就能显示伪造的主体,达到攻击目的。
Set-Cookie: UID=(%0D%0A :换行符)
(%0D%0A :换行符)
<HTML><HEAD><TITLE>之后,想要显示的网页内容 <!-- (原来页面对应的首部字段和主体部分全视为注释)
利用这个攻击,已触发陷阱的用户浏览器会显示伪造的 Web 页面,再让用户输入自己的个人信息等,可达到和跨站脚本攻击相同的效果。
邮件首部注入(Mail Header Injection)是指 Web 应用中的邮件发送功能,攻击者通过向邮件首部 To 或 Subject 内任意添加非法内容发起的攻击。利用存在安全漏洞的 Web 网站,可对任意邮件地址发送广告邮件或病毒邮件。
目录遍历(Directory Traversal)攻击是指对本无意公开的文件目录,通过非法截断其目录路径后,达成访问目的的一种攻击。这种攻击有时也称为路径遍历(Path Traversal)攻击。
通过 Web 应用对文件处理操作时,在由外部指定文件名的处理存在疏漏的情况下,用户可使用 .../ 等相对路径定位到 /etc/passed 等绝对路径上,因此服务器上任意的文件或文件目录皆有可能被访问到。这样一来,就有可能非法浏览、篡改或删除 Web 服务器上的文件。
http://example.com/read.php?log=0401.log
http://example.com/read.php?log=../../etc/passwd
远程文件包含漏洞(Remote File Inclusion)是指当部分脚本内容需要从其他文件读入时,攻击者利用指定外部服务器的 URL 充当依赖文件,让脚本读取之后,就可运行任意脚本的一种攻击。
对那些原本不愿公开的文件,为了保证安全会隐蔽其 URL。可一旦知道了那些 URL,也就意味着可浏览 URL 对应的文件。比如
http://www.example.com/entry/entry_081202.log
这样一个路径,就很容易推测出下一个文件是 entry_081203.log,从而被访问。
不正确的错误消息处理(Error Handling Vulnerability)的安全漏洞是指,Web 应用的错误信息内包含对攻击者有用的信息。与 Web 应用有关的主要错误信息如下所示:
开放重定向(Open Redirect)是一种对指定的任意 URL 作重定向跳转的功能。而于此功能相关联的安全漏洞是指,假如指定的重定向 URL 到某个具有恶意的 Web 网站,那么用户就会被诱导至那个 Web 网站。比如:
http://example.com/?redirect=http://www.tricorder.jp
http://example.com/?redirect=http://hackr.jp
可信度高的 Web 网站如果开放重定向功能,则会被攻击者用来作为钓鱼攻击的跳板。
会话劫持(Session Hijack)是指攻击者通过某种手段拿到了用户的会话 ID,并非法使用此会话 ID 伪装成用户,达到攻击的目的。
攻击者在得知该 Web 网站存在可跨站攻击 XSS 的安全漏洞后,就设置好用 JavaScript 脚本调用 document.cookie
以窃取 Cookie 信息的陷阱,获取含有会话 ID 的 Cookie。
拿到用户的会话 ID 后,往自己的浏览器的 Cookie 中设置该会话 ID,即可伪装成会话 ID 遭窃的用户,访问 Web 网站。
对以窃取目标会话 ID 为主动攻击手段的会话劫持而言,会话固定攻击(Session Fixation)攻击会强制用户使用攻击者指定的会话 ID,属于被动攻击。
攻击者设置好强制用户使用该会话 ID 的陷阱,并等待用户拿着这个会话 ID 前去认证。一旦用户触发陷阱并完成认证,会话在服务器上的状态(用户 A 已认证)就会被记录下来,再利用之前这个会话 ID 访问网站。
跨站点请求伪造(Cross-Site Request Forgeries,CSRF)攻击是指攻击者通过设置好的陷阱,强制对已完成认证的用户进行非预期的个人信息或设定信息等某些状态更新,属于被动攻击。
比如这个留言板功能,只允许已认证并登录的用户发表内容。用户的 Cookie 持有已认证的会话 ID。用户如果点击了攻击者留下的恶意代码链接,则会利用用户的信息执行操作。
密码破解攻击(Password Cracking)即算出密码,突破认证。
通过网络进行密码试错主要有下面两种方式:
字典攻击中有一种利用其他 Web 网站已泄露的 ID 及密码列表进行的攻击,因为很多用户习惯随意地在多个 Web 网站使用同一套 ID 及密码。
对已加密密码的破解通常有下面几种方法:
点击劫持(Clickjacking)是指利用透明的按钮或链接做成陷阱,覆盖在 Web 页面之上。然后诱使用户在不知情的情况下,点击那个链接访问内容的一种攻击手段。这种行为又称为界面伪装(UI Redressing)。
已设置陷阱的 Web 页面,表面上内容并无不妥,但早已埋入想让用户点击的链接。当用户点击到透明的按钮时,实际上是点击了已指定透明属性元素的 iframe 页面。
DoS 攻击(Denial of Service attack)是一种让运行中的服务呈停止状态的攻击。有时也叫做服务停止攻击或拒绝服务攻击。DoS 攻击的对象不仅限于 Web 网站,还包括网络设备及服务器等。
后门程序(Backdoor)是指开发设置的隐藏入口,可不按正常步骤使用受限功能。利用后门程序就能够使用原本受限制的功能。
可通过监视进程和通信的状态发现被植入的后门程序。但设定在 Web 应用中的后门程序,由于和正常使用时区别不大,通常很难发现。