0%

HTTP协议复习

HTTP 请求

  • GET 用于获取数据,无请求body

  • POST 用于添加数据

    其content-type不同,body中的格式也不同

  • PUT 用于添加或更新数据

    Request:

    1
    2
    3
    4
    5
    6
    PUT /new.html HTTP/1.1
    Host: example.com
    Content-type: text/html
    Content-length: 16

    <p>New File</p>

    Response:

    若资源不存在需要创建,那么服务器需响应201表明内容已创建:

    1
    2
    HTTP/1.1 201 Created
    Content-Location: /new.html

    若资源存在则返回200204:

    1
    2
    HTTP/1.1 204 No Content
    Content-Location: /existing.html
  • PATCH 用于更新数据

    Request:

    1
    2
    3
    4
    5
    6
    7
    PATCH /file.html HTTP/1.1 
    Host: www.example.com
    Content-Type: application/example
    If-Match: "e0023aa4e"
    Content-Length: 100

    {"op":"move", "from":"/a/b/c", "to":"/a/b/d"}

    Response:

    正确回应应该为204因为200会带返回body

    1
    2
    3
    HTTP/1.1 204 No Content
    Content-Location: /file.txt
    ETag: "e0023aa4f"
  • DELETE 用于删除数据

    Request:

    1
    DELETE /file.html HTTP/1.1

    Response:

    202已经接受但操作未执行完,204或者200(需返回body)

    1
    2
    3
    4
    5
    6
    7
    8
    HTTP/1.1 200 OK 
    Date: Wed, 21 Oct 2015 07:28:00 GMT

    <html>
    <body>
    <h1>File deleted.</h1>
    </body>
    </html>
  • HEAD 用于获取GET请求的响应头,无请求body

  • OPTIONS 用于描述通信选项,如CORS使用或者获取服务器所支持的方法

  • TRACE 回显服务器收到的请求

19/08/28更新:经过大佬纠正,RFC72303.3节明确指出任何请求都可以带body,而developer.mozilla那边写错了。

对比

幂等性:不论进行多少次操作,都返回相同的结果。

安全性(Safe):方法不改变资源,可以理解为只读性。

GET POST PUT PATCH DELETE HEAD OPTIONS TRACE
请求含body N Y Y Y May N N N
回应含body Y Y N Y May N Y N
安全性 Y N N N N Y Y N
幂等性 Y N Y May Y Y Y N
可缓存 Y Y N N N Y N N
可以被表单使用 Y Y N N N N N N

POST、PUT和PATCH的区别

用法区别:

  • POST用于创建资源
  • PUT用于创建或更新资源
  • PATCH用于更新资源(与PUT不同的是PATCH的body部分必须包含对象需要更新的属性新的值并且可能包含旧的值,而PUT需要包含对象的所有必须(包括新的和旧的)属性)注意这决定了PATCH不能保证幂等性,下文会详细讨论。

幂等性区别:

  • POST是不幂等的,例如POST /api/create/user/a为创建一个用户a,再次POST则对再次创建(即使先前存在一个重复数据)。
  • PUT是幂等的,即存在则更新,不存在则创建。

  • PATCH的设计有可能幂等——body部分只包含更新后的值,比如({"name":"newname"}),也有可能是不幂等的——body部分包含了更新前的值和更新后的值,比如({"op":"rename","oldname":"Old",”newname","New"})第二次执行时,因为oldname已经不为”Old“,所以会抛出异常。

当然这只是规范的设计,在实际应用中,由于开发者素质和业务场景的不同,很可能打破这些请求的原有功能,比如很多情况下用POST代替了PUT和PATCH。

响应码

只列举常用的

信息响应

101 switching Protocol

服务器将用Upgrade通知客户端采用不同协议完成这个请求

成功

200 OK

请求成功

重定向

301 Moved Permanently

永久重定向

302 Found

请求的资源现在临时从不同的 URI 响应请求。

客户端问题

400 Bad Request

语意有错误或请求参数有误

401 Unauthorized

当前请求需要用户验证

403 Forbidden

服务器已经理解请求,但是拒绝执行它。与 401 响应不同的是,身份验证并不能提供任何帮助,而且这个请求也不应该被重复提交。

404 Not Found

请求失败,请求所希望得到的资源未被在服务器上发现。

408 Request Timeout

请求超时

服务器错误

500 Internal Server Error

服务器遇到了不知道如何处理的情况

502 Bad Gateway

上游服务器(如tomcat、php-fpm)的响应是无效的

503 Service Unavailable

服务器没有准备好处理请求。 常见原因是服务器因维护或重载而停机

504 Gateway Timeout

当服务器作为网关,不能及时得到响应时返回此错误代码。

HTTP 首部

HTTP的首部说不完,只列举与安全有关的,值得注意的是x-开头的头部为自定义头部,这在2012年6月已经被RFC废止。

Host

用于不同域名配置在同一个IP地址的服务器上,web容器(如nginx)通过该字段转发请求。

Content-Length

对于持续连接来说,使用Content-Lenght来定义http报文边界。

Transfer-Encoding: chunked

分块传输,将报文分块发送,这样发送方不需要一次性计算http长度。

每个分块包含一个十六进制数据表示数据长度和数据部分,用CLRF(\r\n)结尾;最后一个分块长度为0表示结束;;表示注释,可以用来绕过WAF

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
HTTP/1.1 200 OK
Content-Type: text/plain
Transfer-Encoding: chunked

25\r\n
This is the data in the first chunk\r\n

1C\r\n
and this is the second one\r\n

3;xxxx\r\n
con\r\n

8\r\n
sequence\r\n

0\r\n
\r\n
(两个换行)

X-Frame-Options

用于防御UI点击劫持,它是指攻击者改造网页,在网页前加入一个透明的iframe框诱惑攻击者点击,格式为:

1
X-Frame-Options: DENY | SAMEORIGIN | ALLOW-FROM URL

目前已经被CSP取代:

1
Content-Security-Policy: frame-ancestors 'none';

1
Content-Security-Policy: frame-ancestors 'self';

X-XSS-Protection

用于防御反射型XSS,默认配置为:

1
X-XSS-Protection: 1

表示开启XSS防御,0表示关闭。

HSTS

HSTS指示浏览器强制使用HTTPS,它的头部为Strict-Transport-Security

1
Strict-Transport-Security: <max-age=31536000>[; includeSubDomains][; preload]

max-age指HSTS的过期时间,通常是一年

includeSubDomains指当前域名和子域名均开启HSTS

preload指申请将该域名加入浏览器内置列表中,以后的所有访问都将使用https链接(可以在https://hstspreload.org/上看)

详细解释一下,若不加HSTS,那么用户的访问是这样的:

1549094565896

因此攻击者可以展开中间人攻击:

1549094607660

使用HSTS防御后用户可以防御该攻击:

1549094654080

HPKP

为了防止CA悄悄修改证书内容,服务器可以将自己公钥填在HTTP头中,让浏览器核对其与证书是否一致:

1
Public-Key-Pins: pin-sha256="base64=="; max-age=expireTime [; includeSubdomains][; report-uri="reportURI"]

Referrer-Policy

Referer: A.com 指跳转来自A.com
默认情况下,只要发生跳转,浏览器就会自动添加referer头,服务器可以用referer-prolicy指定为其他:

介绍
Policy未设置
no-referrer 任何情况下都不发送referer
no-referrer-when-downgrade https至http时不发送referer
origin 仅发送protocal://host部分
origin-when-cross-origin 跨域时发送origin
same-origin 同源时发送
strict-origin 双方origin相同且安全等级相同
unfafe-url 任何情况下都发送完整referer

关于请求IP

  • Client-IP

    1
    Client-IP: 127.0.0.1
  • X-Forwarded-For

    1
    X-Forwarded-For: client1, proxy1, proxy2, proxy3
  • X-Originating-IP:

    1
    X-Originating-IP: 127.0.0.1
  • X-Remote-Addr:

    1
    X-Remote-Addr: 127.0.0.1

可以看到这四个请求包头都是可以伪造的,所以还是通过源IP来直接获取主机IP为好,这里给出PHP的实现

1
$_SERVER['REMOTE_ADDR'] == '127.0.0.1'

Cookies

服务器使用Set-Cookie设置Cookie

1
Set-Cookie: id=a3fWa; [Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly]

  • Expires:指Cookie的过期时间

  • Domain=mozilla.org:Cookie作用于mozilla.org及其子域名

  • Secure:Cookie只能通过HTTPS发送给服务端

  • HttpOnly:Cookie不能被js调用

    注意Cookie的属性即是指键值对,过期时间和作用域。

CSP

与CSP有关的header请参考内容安全策略CSP学习笔记一文。

CORS

与CORS有关的头部有origin,access-control-等,详细我会另开一篇文章。

HTML5

http协议的body部分格式主要为HTML,而新引入的HTML5中同时引入了很多安全性问题:

CORS的安全性问题

详见另一篇文章

新标签带来新的XSS机会

  • video

    1
    <video> <source onerror="javascript:alert(1)">
  • 类似的标签还有audioinputselecttextareakeygen等。

新属性

  • onfocus

    1
    <input onfocus=alert(1) autofocus>
  • formaction

    1
    <form><button formaction="javascript:alert(1)">
  • onscroll

    1
    2
    3
    <body onscroll=alert(1)>
    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br><br> <br><br><br><br><br><br><br><br><br><br><br><br><br><br>
    <input autofocus>

    更多可查看:HTML5 标签安全

Web Worker

js的多线程支持为新的僵尸网络或挖矿脚本 提供机会:

1
var worker = new Worker("worker.js");

PostMessage

postmessage可能会导致新的XSS攻击:

1
2
3
4
5
var worker = new Worker("worker.js");
worker.postMessage("hello world");
worker.onmessage = function(e) {
document.getElementById("test").innerHTML = e.data;
}

参考链接