文章目录
1. 概述
安全通信需要具有下列特性:
机密性
:通过加密手段,希望仅有发送发和接收方能够理解传输报文的内容。报文完整性
:希望通信内容在传输过程中未被改变或者恶意篡改。端点鉴别
:发送方和接收方都应该能证实通信过程所涉及的另一方,以确信通信的另一方确实具有其所声称的身份。运行安全性
:通过诸如防火墙和入侵检测系统等运行设备反制对机构网络的攻击。
2. 机密性
密码技术使得发送方可以伪装数据、使人侵者不能从截取到的数据中获得任何有效信息。当然,接收方必须能够从伪装的数据中恢复出初始数据。
2.1 对称密钥密码体制
加密和解密使用相同的密钥叫做对称加密方式。
对称密钥加密主要有两种宽泛的类型:
流密码(stream cipher)
:例如无线LAN的安全性。块密码(block cipher)
:例如PGP(安全电子邮件)、SSL(安全TCP)和IPsec(安全网络层传输)。
对称加密方式包括AES(Advanced Encryption Standard)、DES(Data Encryption Standard)等加密标准。
2.2 公开密钥加密(非对称加密)
在加密和解密过程中分别使用不同的密钥(公钥和私钥)叫做公钥加密方式。
在对称加密方式中,最大的挑战就是如何传递安全的密钥。而公钥加密方式中,仅有一方的密钥是无法完成解密的,还必须严格管理私钥。通过邮件发送公钥、通过Web公开发布公钥、或通过PKI 分配等方式,才得以在网络上安全地传输密钥。
公钥加密方法中包括 RSA、DH(Diffie-Hellman)、椭圆曲线(ECDHE)等加密算法。
RSA和DH需要做大量的指数和乘法运算,是相当耗时的操作,对比DES用软件实现要慢100倍,用硬件实现则要快1000~10000倍。所以,在对较长的消息进行加密时往往采用两者结合的方式。
3. 报文完整性和数字签名
报文完整性指的是希望报文在传输的过程中不会受到篡改等。
3.1 报文鉴别码
- 在传输之前,通信双方会分享一个秘密的鉴别密钥(authentication key)。
- 发送方生成报文 m,和鉴别密钥 k,一起通过散列函数(例如MD5或者SHA-1)计算散列 H(m + k)。这个计算出来的数就称为报文鉴别码(Message Authentication Code,MAC)。
- 发送方将该报文鉴别码,附加到报文上,并发送给接收端。
- 接收端通过同样的散列函数计算 H(m + k),如果计算的值和发送来的报文鉴别码相同,则说明没有被篡改。
3.2 数字签名
数字签名就是一种在数字领域实现证明身份的密码技术。
采用公开密钥加密的方式,因为对于发送方私钥是鉴别身份特有的东西。
过程如下:
- 发送方将报文 m 通过散列函数计算一个值 H(m),通过自己的私钥对该值进行数字签名(加密)。因为如果对于整个报文进行签名则开销太大,所以对计算出的散列值进行签名。
- 将报文的明文和已经被签名的报文摘要一起发送给接收端。
- 接收方得到之后,将加密的H(m)通过自己的公钥解密获得一个散列值。再将报文经过同样的散列函数计算得到一个散列值,如果两个散列值相同则可以保证报文没有被篡改。
3.3 公钥认证
将公钥与特定的实体绑定通常是由认证中心(Certification Authority,CA)完成的,CA的职责就是使识别和发行证书合法化。CA主要包括以下作用:
- CA证实一个实体的真实身份。
- 一旦CA验证了某个实体身份,这个CA会生成一个将其身份和实体的公钥绑定起来的证书(certificate)。
CA签发证书的过程:
- 首先 CA 会把持有者的公钥、用途、颁发者、有效时间等信息打成⼀个包 p ,然后对这些信息通过散列函数计算一个散列值H(p)。
- 然后CA使用自己的私钥对该散列值进行一个数字签名。
- 然后将该数字签名添加到证书(包含发送方身份标识信息)上,则形成数字证书。
接收方验证数字证书过程:
- 接收方使用同样的散列函数对原证书进行散列计算出一个散列值H1。
- 通常浏览器和操作系统中集成了 CA 的公钥信息,浏览器收到证书后可以使用 CA 的公钥解密数字签名内容,得到另一个散列值H2。
- 判断H1 和 H2,如果相同则是可信赖的证书。
证书链
事实上,证书的验证过程中还存在⼀个证书信任链的问题,因为我们向 CA 申请的证书⼀般不是根证书签发的,而是由中间证书签发的。
证书链验证过程如下:
- 接收方收到了C 的证书后,发现这个证书的签发者不是根证书,就无法根据本地已有的根证书中的公钥去验证C证书是否可信,所以就根据签发者找到签发机构,再向该机构请求它的证书B。
- 得到证书B之后发现他也有签发者机构,则继续向上查找他的证书。知道找到没有上级签发机构的证书,说明它是根证书,也就是自签证书。
- 得到该证书之后,通过本地的公钥对其进行验证,如果通过说明该证书是可信的,再依次向下验证是否可信。
简答来说就是逐级向上请求到根证书,再通过公钥逐级向下验证是否可信。
需要一条证书链是为了确保根证书的绝对安全性,将根证书隔离地越严格越好,不然根证书如果失守了,那么整个信任链都会有问题。
4. 端点鉴别
端点鉴别(end-point authentication) 就是一个实体经过计算机网络向另一个实体证明身份的过程。
- 发送端和接收端进行通信,发送端发送消息之后。
- 接受端向发送端传递一个不重数(一个协议生存期只使用一次的数)。
- 发送端通过两端共享的密钥进行加密,传回该数。
- 接受端进行解密验证对方身份。
5. 安全电子邮件:PGP
电子邮件希望的安全包括:
机密性
:传输的邮件不希望有别的人看到。发送方鉴别
:接收方可以确认是否是目标发送方发来的邮件。接收方鉴别
:发送方可以确认接受方身份。
PGP软件的不同版本使用MD5或使用SHA来计算报文摘要。使用CAST、三重DES或IDEA进行对称密钥加密。使用RSA进行公开密钥加密。
安装PGP时,软件为用户产生一个公开密钥对,公钥能被张贴到用户的网站或者放着在某台公钥服务器上,私钥则使用用户口令进行保护。
安全电子邮件流程:
- 发送方将报文经过散列函数得到一个报文摘要(即散列值)。再使用自己的私钥对该摘要进行一个签名得到一个数字签名。然后将数字签名和原报文生成一个数据包。
- 发送方选择一个对称密钥对第一步生成的包进行加密。然后用发送方的公钥对对称密钥进行加密。将加密的包和密钥组成一个包一起发送给接收方。
- 接受方收到数据包后,使用私钥对会话对称密钥进行解密。再使用该密钥将数字签名与原报文的包进行解密,就能得到数字签名以及原报文。
- 接受方使用发送方的公钥对数字签名进行解密得到一个散列值H1,再将原报文经过同样的散列函数计算得到一个散列值H2,如果H1等于H2,说明报文没有被篡改以及可以证实对方身份。
6. 使TCP连接安全:SSL
以下文章已经对SSL两种握手方式做了一定程度的介绍。本博客只对于椭圆算法ECDHE握手过程进行一个总结。
SSL记录如下所示:
类型
:指出该字段是握手报文还是包含用户数据的报文,也用作关闭SSL连接。版本
:SSL版本号。长度
:SSL报文长度。数据
:传输的具体数据。MAC
:报文鉴别码(Message Authentication Code,MAC),用来检测报文是否被篡改。
6.1 ECDHE算法 TLS 握手过程
第一次握手
客户端会发送⼀个「Client Hello」消息记录,是握手类型报文,包括了使用TLS的版本号、它支持的密码算法列表(TLS并不强制使用某种加密算法,而是通过协商取得一致)和客户端生成的随机数(Client Random)。
第二次握手
服务器收到客户端的消息之后会返回「Server Hello」消息记录,也是握手类型报文,包括了确认的TLS版本号、从算法列表选择的对称算法,非对称算法以及MAC算法等。并且也向客户端返回一个生成的随机数(Server Random)。
之后为了验证身份,发送「Certificate」消息,把证书也发给客户端。
另外,由于采用的是ECDHE密钥协商算法,所以还会发送「Server Key Exchange」消息进行以下操作并把以下内容发送给客户端:
- 选定一个椭圆曲线,相当于也定好了椭圆曲线的基点。
- 生成一个随机数作为私钥,保存在服务器本地。
- 通过私钥和椭圆曲线计算出公钥。
为了防止公钥被第三方篡改,所以对公钥做了数字签名。
最后发送「Server Hello Done」消息,表明消息已经发送完毕。
第三次握手
客户端验证该证书,通过CA的公钥对数字证书进行解密,得到一个散列值H1,再将原证书内容使用一样的散列函数得到一个散列值H2,如果H1 等于 H2,则可以确认服务端身份,再使用服务端的公钥对数字签名做一个认证,检查公钥是否被篡改。
之后客户端也生成一个随机数作为私钥,保存在本地。
再通过公开的椭圆曲线计算出公钥并发送「Client Key Exchange」消息,把公钥经过服务器公钥加密后发送给服务器端。
至此,通过 ① 双方生成的随机数;② 椭圆曲线以及基点;③ 对方的公钥;④ 自己的私钥 。计算出最终的会话密钥(双方通过该算法可以计算出一样的会话密钥)。
算好会话密钥后,客户端会发⼀个「Change Cipher Spec」消息,告诉服务端后续改用对称算法加密通信。
最后后,客户端会发送「Encrypted Handshake Message」消息,使用MAC对之前的报文做一个摘要,发送给服务器端,验证之前的内容是否被篡改。
第四次握手
服务端同样计算出会话密钥,发「Change Cipher Spec」和「Encrypted Handshake Message」消息对客户端的MAC进行验证以及发送一个自己的MAC让客户端验证,如果验证都通过则建立TLS连接。
7. 网络层安全:IPsec 和 虚拟专用网
以前,为了防止信息泄露,对机密数据的传输一般不使用互联网等公共网络(Public Network),而是使用由专线连接的私有网络(Private Network)。从而在物理上杜绝了窃听和篡改数据的可能。然而,专线的造价太高是一个不可回避的问题。
为了解决此类问题,人们想出了在互联网上构造一个虚拟的私有网络。即VPN(Virtual Private Network,虚拟专用网)。
在构建VPN时,最常被使用的是IPsec。它是指在IP首部的后面追加“封装安全有效载荷”(ESP,Encapsulating Security Payload。)和“认证首部”(AH,Authentication Header。) ,从而对此后的数据进行加密,不被盗取者轻易解读。
在发包的时候附加上述两个首部,可以在收包时根据首部对数据进行解密,恢复成原始数据。
8. 运行安全性:防火墙和入侵检测系统
组织机构(域)内部的网络与互联网相连时,为了避免域内受到非法访问的威胁,往往会设置防火墙(使用NAT(NAPT)的情况下,由于限定了可以从外部访问的地址,因此也能起到防火墙的作用。) 。
防火墙的种类和形态有很多种。例如,专门过滤(不过滤)特定数据包的包过滤防火墙、数据到达应用以后由应用处理并拒绝非法访问的应用网关。这些防火墙都有基本相同的设计思路,那就是“暴露给危险的主机和路由器的个数要有限”。
数据包符合安全策略,防火墙才会让其通过。即只要与策略相符,就无法判断当前访问是否为非法访问,所以全部允许通过。而IDS(入侵检测系统) 正是检查这种已经侵入内部网络进行非法访问的情况,并及时通知给网络管理员的系统。
反病毒和个人防火墙是继IDS和防火墙之后的另外两种安全对策,它们往往是用户使用的计算机或服务器上运行的软件。既可以监控计算机中进出的所有包、数据和文件,也可以防止对计算机的异常操作和病毒入侵。
扩展:系统的认证鉴权
1. Token
对于现在的系统鉴权认证,一般都是采用基于 JWT 的实现,使用 Token 对比 Session 和 Cookie 的优劣有一下几点:
优点
:
- 支持跨域访问: Cookie是不允许垮域访问的,token支持。
- Token 是无状态的,只需要存储在请求头中,Session 需要 sessionId 来标识。
- Token 更适用于移动应用: Cookie不支持手机端访问的。
- 服务可以自己对 token 进行解析,而不需要去调用其他授权认证的服务。
- 性能: 在网络传输的过程中,性能更好
- 基于标准化: 你的API可以采用标准化的 JSON Web Token (JWT)
缺点
- 主要缺点还是在于性能方面,往往会在 JWT 中存储大量的信息。
- JWT 是一次性的,一旦签发,无法进行失效,并且有泄漏的风险,所以Token的时间不建议设置的很长,一般大型网站貌似都是设置的一个小时左右。
2. SSO
对于同域下的单点登陆,可以将 Cookie 设置为顶级域名作用域,这样就可以在二级域名中获取 Cookie 中的 SessionID ,进而获取 Session 中用户登陆的信息。
对于不同域名的系统间的单点登录流程如下:
- 用户访问 Application1 系统,需要登陆,则重定向到 SSO 登陆系统进行登陆。
- SSO 系统中通过用户名和密码进行登录,登陆成功之后,给SSO系统的分布式 Session 中存储对应用户的信息,并且将对应的键作为 Cookie 存储在浏览器。
- 之后给 Application1 系统颁发一个 Token 并且重定向回 Application1。
- Application1 系统通过该 token 向 SSO 系统取得用户信息存在自己的 Session 中,或者直接使用 JWT 包含在 token 中,表示已经登陆成功,并且获取了用户信息资源。
这样对于一个系统的登陆已经完成,这时候,如果要访问另一个不同域名的 Application2 ,则单点登陆的实现如下:
- 访问 Application2 还是需要登陆,会重定向到 SSO 系统,但是由于之前存储的 Cookie ,SSO 系统并不需要重新登陆,可以直接获取到对应的用户信息。
- 这样就会直接重定向回到 Application2,并颁发一个 token。
- Application2 就可以通过该 token 直接向SSO 系统获取用户信息状态,然后存储到自己的Session 中,或者通过 JWT 生成 token 保存在首部。
- 这样不同域名的 Application2 也不需要重新的登陆,从而实现了单点登录。
3. OAuth2
OAuth 2.0 是一个行业标准的授权协议,其主要目的就是为第三方应用颁发一个实效性的 Token ,通过该 Token 进行权限控制。
OAuth2 的主要角色:
resource owner
,资源所有者:也就是能够访问受保护资源的实体,例如,用户(则被称为 end-user)。resource server
,资源服务器,托管受保护资源的服务器。client
,客户端,使用资源所有者的授权代表资源所有者发起对受保护资源的请求的应用程序。如:web网站,移动应用等。authorization server
,授权服务器,能够向客户端颁发令牌。
OAuth2 工作流程:
- 客户端得到资源所有者的授权之后,向授权服务器申请访问令牌。
- 客户端得到授权服务器的令牌之后,通过令牌向资源服务器获取受保护的资源。
- 资源服务器对令牌进行校验和鉴权,返回对应的合法资源。
OAuth2 的授权模式:
授权码模式
:最完整安全的流程,只在客户端的后端和授权服务器进行交互。- 首先客户端将资源所有者重定向到授权服务器,资源所有者同意授权,返回客户端,并且获取授权码。
- 客户端带着授权码去授权服务器获取令牌,授权服务器对授权码进行校验然后颁发令牌。
- 客户端得到令牌就能去资源服务器获取受保护的资源(这一步用户不可见,减少被盗窃的风险)。
隐式模式
:适用没有后端的前端项目,直接将 token 通过 URL 返回给前端,不安全。密码模式
:允许客户端直接拿资源所有者的账号密码去获取令牌。凭证模式(客户端模式)
:这种模式只需要提供 client_id 和 client_secret 即可获取授权。一般用于后端 API 的相关操作。
4. CSRF
CSRF(Cross-site request forgery),中文名称:跨站请求伪造,也被称为:one click attack/session riding,缩写为:CSRF/XSRF。
通俗的来说,就是攻击者盗用你的身份,以你的名义发送恶意的请求,例如,你登陆了某个网址,浏览器保存了对应的 Cookie,然后在没有登出,即 Cookie 没有过期的情况下访问另一个危险网站,该网站带着你的 Cookie 访问对应网站进行一些有害操作。
目前最普遍的解决方法是,使用一个 Token,在自己访问的时候请求会带上这个 Token 进行访问,而危险网站的访问并不存在该 Token 则为非法操作,Token 可以在一个 hidden 的表单中提交等,不存在与 Cookie 中,所以危险网站一般情况无法获取。
5. XSS
XSS是跨站脚本攻击(Cross Site Scripting),即恶意攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。
XSS 攻击主要分为两种:
- 反射型XSS:即需要通过用户访问特定的连接,才能对Web页面插入非法脚本,从而进行一些恶意操作。攻击相当于是一次性的。
- 存储型XS:把对应的恶意脚本存储到数据库中,每当访问页面都会从数据库中取出执行,例如在留言中插入恶意脚本,每次访问留言板都会执行。
XSS 防御的方法是:
- 对于 URL 请求进行过滤,阻止恶意脚本的插入。
- 对于网页展示的形式进行编码,使得特殊写入的脚本无法执行。