HTTP 请求
GET 用于获取数据
,无请求bodyPOST 用于添加数据
其content-type不同,body中的格式也不同
PUT 用于添加或更新数据
Request:
1
2
3
4
5
6PUT /new.html HTTP/1.1
Host: example.com
Content-type: text/html
Content-length: 16
<p>New File</p>Response:
若资源不存在需要创建,那么服务器需响应
201
表明内容已创建:1
2HTTP/1.1 201 Created
Content-Location: /new.html若资源存在则返回
200
或204
:1
2HTTP/1.1 204 No Content
Content-Location: /existing.htmlPATCH 用于更新数据
Request:
1
2
3
4
5
6
7PATCH /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
会带返回body1
2
3HTTP/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
8HTTP/1.1 200 OK
Date: Wed, 21 Oct 2015 07:28:00 GMT
<html>
<body>
<h1>File deleted.</h1>
</body>
</html>HEAD 用于获取GET请求的响应头
,无请求bodyOPTIONS 用于描述通信选项,如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 | HTTP/1.1 200 OK |
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,那么用户的访问是这样的:
因此攻击者可以展开中间人攻击:
使用HSTS防御后用户可以防御该攻击:
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
设置Cookie1
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)">
类似的标签还有
audio
、input
、select
、textarea
、keygen
等。
新属性
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 | var worker = new Worker("worker.js"); |
参考链接
- HTTP, https://developer.mozilla.org/zh-CN/docs/Web/HTTP
- Whitepaper: HTTP Security Headers and How They Work, https://www.netsparker.com/whitepaper-http-security-headers/#XFrameOptionsHTTPHeader
- HSTS详解,https://www.jianshu.com/p/caa80c7ad45c
- HTML5 安全问题解析, https://segmentfault.com/a/1190000003756563