Open tomoya06 opened 4 years ago
HTTP 有以下安全性问题:
HTTPS 并不是新协议,而是让 HTTP 先和 SSL(Secure Sockets Layer)通信,再由 SSL 和 TCP 通信,也就是说 HTTPS 使用了隧道进行通信。
通过使用 SSL,HTTPS 具有了加密(防窃听)、认证(防伪装)和完整性保护(防篡改)。
对称密钥加密(Symmetric-Key Encryption),加密和解密使用同一密钥。
常见的对称加密算法有AES、ChaCha20、3DES、Salsa20、DES、Blowfish、IDEA、RC5、RC6、Camellia。
非对称密钥加密,又称公开密钥加密(Public-Key Encryption),加密和解密使用不同的密钥。公开密钥所有人都可以获得,消息可以用公钥加密,只有密钥拥有者能解开。
非对称密钥除了用来加密,还可以用来进行签名。因为私有密钥无法被其他人获取,因此通信发送方使用其私有密钥进行签名,通信接收方使用发送方的公开密钥对签名进行解密,就能判断这个签名是否正确。
常见的非对称加密算法有:椭圆曲线数字签名算法
数字签名技术是将原文通过特定HASH函数得到的摘要信息,然后用发送者的私钥加密,与原文一起传送给接收者。接收者只有用发送者的公钥才能解密被加密的摘要信息,然后用HASH函数对收到的原文提炼出一个摘要信息,与解密得到的摘要进行对比。
简而言之,数字签名 = 私钥加密过的原文哈希
数字证书认证机构(CA,Certificate Authority)是客户端与服务器双方都可信赖的第三方机构。通信双方通过使用CA办法的 证书 来对通信方进行认证,证书上面包含公钥以及公钥签名。
CA也有一套自己的公钥密钥,浏览器会内置各大CA的公钥。服务器向 CA 提出公开密钥的申请,CA生成一对公钥密钥之后,会用自己的密钥对公开密钥做数字签名,然后将这个已签名的公开密钥放入证书,发给服务器。
进行 HTTPS 通信时,服务器会把证书发送给客户端。客户端取得其中的公开密钥之后,先使用数字签名进行验证。
SSL 提供报文摘要功能来进行完整性保护。
HTTP 也提供了 MD5 报文摘要功能,但不是安全的。例如报文内容被篡改之后,同时重新计算 MD5 的值,通信接收方是无法意识到发生了篡改。
HTTPS 的报文摘要功能之所以安全,是因为它结合了加密和认证这两个操作。试想一下,加密之后的报文,遭到篡改之后,也很难重新计算报文摘要,因为无法轻易获取明文。
详细参考这里
过程叙述参考知乎专栏
参考Google博客
HTTP/2.0 将报文分成 HEADERS 帧和 DATA 帧,它们都是二进制格式的。
定义:如果两个 URL 的 protocol、port (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。
定义:跨域资源共享(cross-origin resource sharing)是一种机制,它使用额外的 HTTP 头来告诉浏览器,让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。
CORS 请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)。只要同时满足以下两大条件,就属于简单请求:
凡是不同时满足上面两个条件,就属于非简单请求。
@font-face
使用跨域字体资源)。因此,网站就可以发布 TrueType 字体资源,并只允许已授权网站进行跨站调用。本段参考阮一峰的博客
对于简单请求,浏览器直接发出 CORS 请求,并在头信息之中增加一个Origin
字段。
如果Origin在许可范围内,服务器返回的相应会多出以下响应头:
Access-Control-Allow-Origin: *
或指定特定域名,来限制可访问的域名Access-Control-Allow-Credentials
,它的值是一个布尔值,表示是否允许发送 Cookie。Access-Control-Expose-Headers
,表示可从报文中读取的响应头字段浏览器如果发现,回应的头信息没有包含Access-Control-Allow-Origin
字段、或不在允许Origin范围内,就会抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。
非简单请求的 CORS 请求,会在正式通信之前,增加一次 OPTIONS方法的 HTTP 查询请求,称为“预检”请求。
预检请求头包含以下字段:
Access-Control-Request-Method
,列出浏览器的 CORS 请求会用到哪些 HTTP 方法Access-Control-Request-Headers
,一个逗号分隔的字符串,指定浏览器 CORS 请求会额外发送的头信息字段预检请求的响应头包含以下字段:
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers
Access-Control-Allow-Credentials
Access-Control-Max-Age
,指定本次预检请求的有效期,单位为秒同上,如果预检时Origin或其他请求设置不合法,浏览器也会报错。如果合法,就发送正常的非简单请求,当然也会带上Origin字段。
Egg框架文档中详细地提供了各种攻击方式的简介和Egg的防范方式,可以参考阅读。
恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
案例:通过输入框往html中插入<script>alert(“hey!you are attacked”)</script>
防御:输入文本过滤、输出文本转义或编码
攻击者通过一些技术手段欺骗用户的浏览器去访问一个自己曾经认证过的网站并运行一些操作(如发邮件,发消息,甚至财产操作如转账和购买商品)。由于浏览器曾经认证过,所以被访问的网站会认为是真正的用户操作而去运行。
防御:接口引入token验证、检查请求头Referer判断请求来源
如果只用公私钥对来进行加密,没有证书或者公钥签名,攻击者可以介入server和client中间拦截,用自己的公私钥匙分别与双方通信,让对方都正在跟对方正常通信。HTTPS协议中CA的介入就可以解决这个问题。
拒绝服务攻击(英语:denial-of-service attack,简称DoS攻击)亦称洪水攻击,是一种网络攻击手法,其目的在于使目标电脑的网络或系统资源耗尽,使服务暂时中断或停止,导致其正常用户无法访问。
更多攻击方式参考维基百科
一 、基础概念
概述
超文本传输协议(英语:HyperText Transfer Protocol,缩写:HTTP)是一种用于分布式、协作式和超媒体信息系统的应用层协议。HTTP是万维网的数据通信的基础。
设计HTTP最初的目的是为了提供一种发布和接收HTML页面的方法。通过HTTP或者HTTPS协议请求的资源由统一资源标识符(Uniform Resource Identifiers,URI)来标识。
HTTP协议工作于客户端-服务端架构为上。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。Web服务器根据接收到的请求后,向客户端发送响应信息。
主要特点
HTTP协议有以下特点:
URI
统一资源标识符(英语:Uniform Resource Identifier,缩写:URI)在电脑术语中是一个用于标识某一互联网资源名称的字符串。
该种标识允许用户对网络中(一般指万维网)的资源通过特定的协议进行交互操作。URI的最常见的形式是统一资源定位符(Uniform Resource Locator,URL),经常指定为非正式的网址。更罕见的用法是统一资源名称(Uniform Resource Name,URN),其目的是通过提供一种途径。用于在特定的名字空间资源的标识,以补充网址。
统一资源定位符URL的标准格式如下: `[协议类型]://[服务器地址]:[端口号]/[资源层级UNIX文件路径][文件名]?[查詢]#[片段ID]` URN的标准格式如下: `urn:
### 2. 响应报文
# 二、HTTP 方法 客户端发送的 **请求报文** 第一行为请求行,包含了方法字段。 ## GET > 获取资源 当前网络请求中,绝大部分使用的是 GET 方法。 ## HEAD > 获取报文首部 和 GET 方法类似,但是不返回报文实体主体部分。 主要用于确认 URL 的有效性以及资源更新的日期时间等。 ## POST > 传输实体主体 POST 主要用来传输数据,而 GET 主要用来获取资源。 ### 更多 POST 与 GET 的比较 #### 作用 GET 用于获取资源,而 POST 用于传输实体主体。 #### 参数 GET 和 POST 的请求都能使用额外的参数,但是 GET 的参数是以查询字符串出现在 URL 中,而 POST 的参数存储在实体主体中。不能因为 POST 参数存储在实体主体中就认为它的安全性更高,因为照样可以通过一些抓包工具(Fiddler)查看。 因为 URL 只支持 ASCII 码,因此 GET 的参数中如果存在中文等字符就需要先进行编码。例如 `中文` 会转换为 `%E4%B8%AD%E6%96%87`,而空格会转换为 `%20`。POST 参数支持标准字符集。 ``` GET /test/demo_form.asp?name1=value1&name2=value2 HTTP/1.1 ``` ``` POST /test/demo_form.asp HTTP/1.1 Host: w3schools.com name1=value1&name2=value2 ``` #### 安全 安全的 HTTP 方法不会改变服务器状态,也就是说它只是可读的。 GET 方法是安全的,而 POST 却不是,因为 POST 的目的是传送实体主体内容,这个内容可能是用户上传的表单数据,上传成功之后,服务器可能把这个数据存储到数据库中,因此状态也就发生了改变。 安全的方法除了 GET 之外还有:HEAD、OPTIONS。 不安全的方法除了 POST 之外还有 PUT、DELETE。 #### 幂等性 幂等的 HTTP 方法,同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的。换句话说就是,幂等方法不应该具有副作用(统计用途除外)。 所有的安全方法也都是幂等的。 在正确实现的条件下,GET,HEAD,PUT 和 DELETE 等方法都是幂等的,而 POST 方法不是。 GET /pageX HTTP/1.1 是幂等的,连续调用多次,客户端接收到的结果都是一样的: ``` GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 GET /pageX HTTP/1.1 ``` POST /add_row HTTP/1.1 不是幂等的,如果调用多次,就会增加多行记录: ``` POST /add_row HTTP/1.1 -> Adds a 1nd row POST /add_row HTTP/1.1 -> Adds a 2nd row POST /add_row HTTP/1.1 -> Adds a 3rd row ``` DELETE /idX/delete HTTP/1.1 是幂等的,即使不同的请求接收到的状态码不一样: ``` DELETE /idX/delete HTTP/1.1 -> Returns 200 if idX exists DELETE /idX/delete HTTP/1.1 -> Returns 404 as it just got deleted DELETE /idX/delete HTTP/1.1 -> Returns 404 ``` #### 可缓存 如果要对响应进行缓存,需要满足以下条件: - 请求报文的 HTTP 方法本身是可缓存的,包括 GET 和 HEAD,但是 PUT 和 DELETE 不可缓存,POST 在多数情况下不可缓存的。 - 响应报文的状态码是可缓存的,包括:200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501。 - 响应报文的 Cache-Control 首部字段没有指定不进行缓存。 #### XMLHttpRequest 为了阐述 POST 和 GET 的另一个区别,需要先了解 XMLHttpRequest: > XMLHttpRequest 是一个 API,它为客户端提供了在客户端和服务器之间传输数据的功能。它提供了一个通过 URL 来获取数据的简单方式,并且不会使整个页面刷新。这使得网页只更新一部分页面而不会打扰到用户。XMLHttpRequest 在 AJAX 中被大量使用。 - 在使用 XMLHttpRequest 的 POST 方法时,浏览器会先发送 Header 再发送 Data。但并不是所有浏览器会这么做,例如火狐就不会。 - 而 GET 方法 Header 和 Data 会一起发送。 ## PUT > 上传文件 由于自身不带验证机制,任何人都可以上传文件,因此存在安全性问题,一般不使用该方法。 ```html PUT /new.html HTTP/1.1 Host: example.com Content-type: text/html Content-length: 16
New File
``` ## PATCH > 对资源进行部分修改 PUT 也可以用于修改资源,但是只能完全替代原始资源,PATCH 允许部分修改。 ```html PATCH /file.txt HTTP/1.1 Host: www.example.com Content-Type: application/example If-Match: "e0023aa4e" Content-Length: 100 [description of changes] ``` ## DELETE > 删除文件 与 PUT 功能相反,并且同样不带验证机制。 ```html DELETE /file.html HTTP/1.1 ``` ## OPTIONS > 查询支持的方法 查询指定的 URL 能够支持的方法。 会返回 `Allow: GET, POST, HEAD, OPTIONS` 这样的内容。 ## CONNECT > 要求在与代理服务器通信时建立隧道 使用 SSL(Secure Sockets Layer,安全套接层)和 TLS(Transport Layer Security,传输层安全)协议把通信内容加密后经网络隧道传输。 ```html CONNECT www.example.com:443 HTTP/1.1 ```## TRACE > 追踪路径 服务器会将通信路径返回给客户端。 发送请求时,在 Max-Forwards 首部字段中填入数值,每经过一个服务器就会减 1,当数值为 0 时就停止传输。 通常不会使用 TRACE,并且它容易受到 XST 攻击(Cross-Site Tracing,跨站追踪)。 # 三、HTTP 状态码 服务器返回的 **响应报文** 中第一行为状态行,包含了状态码以及原因短语,用来告知客户端请求的结果。 | 状态码 | 类别 | 含义 | | :---: | :---: | :---: | | 1XX | Informational(信息性状态码) | 接收的请求正在处理 | | 2XX | Success(成功状态码) | 请求正常处理完毕 | | 3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 | | 4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 | | 5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 | ## 1XX 信息 - **100 Continue** :表明到目前为止都很正常,客户端可以继续发送请求或者忽略这个响应。 - **101 Switching Protocol** :表示服务器应客户端升级协议的请求( Upgrade 请求头)正在切换协议。 服务器会发送一个 Upgrade 响应头来表明其正在切换过去的协议。(eg. : WebSocket协议[握手时](https://github.com/tomoya06/web-developer-guidance/issues/31)会返回) ## 2XX 成功 - **200 OK** - **204 No Content** :请求已经成功处理,但是返回的响应报文不包含实体的主体部分。一般在只需要从客户端往服务器发送信息,而不需要返回数据时使用。 - **206 Partial Content** :表示客户端进行了范围请求,响应报文包含由 Content-Range 指定范围的实体内容。 ## 3XX 重定向 - **301 Moved Permanently** :永久性重定向 - **302 Found** :临时性重定向 - **303 See Other** :和 302 有着相同的功能,但是 303 明确要求客户端应该采用 GET 方法获取资源。 > 注:虽然 HTTP 协议规定 301、302 状态下重定向时不允许把 POST 方法改成 GET 方法,但是大多数浏览器都会在 301、302 和 303 状态下的重定向把 POST 方法改成 GET 方法。 > 301和302对SEO的影响:301永久重定向之后,搜索引擎只对新网址进行索引,同时又会把旧地址下原有的外部链接如数转移到新地址下,从而不会让网站的排名因为网址变更而收到丝毫影响;对302,目前Google会把其他域名的链接成绩计入主域,但其他搜索引擎只会把链接成绩向多个域名分摊,从而削弱主站的链接总量。 - **304 Not Modified** :如果请求报文首部包含一些条件,例如:If-Match,If-Modified-Since,If-None-Match,If-Range,If-Unmodified-Since,如果不满足条件,则服务器会返回 304 状态码。 - **307 Temporary Redirect** :临时重定向,与 302 的含义类似,但是 307 要求浏览器不会把重定向请求的 POST 方法改成 GET 方法。 ## 4XX 客户端错误 - **400 Bad Request** :请求报文中存在语法错误。 - **401 Unauthorized** :该状态码表示发送的请求需要有认证信息(BASIC 认证、DIGEST 认证)。如果之前已进行过一次请求,则表示用户认证失败。 - **403 Forbidden** :请求被拒绝。 - **404 Not Found** ## 5XX 服务器错误 - **500 Internal Server Error** :服务器正在执行请求时发生错误。 - **503 Service Unavailable** :服务器暂时处于超负载或正在进行停机维护,现在无法处理请求。 # 四、HTTP 首部 有 4 种类型的首部字段:通用首部字段、请求首部字段、响应首部字段和实体首部字段。
各种首部字段及其含义如下(不需要全记,仅供查阅):
## 通用首部字段 | 首部字段名 | 说明 | | :--: | :--: | | 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 | 资源的最后修改日期时间 |