HTTPS 协议降级攻击原理
ReaganBattl
8年前
<p style="text-align: center;"><img src="https://simg.open-open.com/show/466589c0dda2b575d199700c46184311.jpg"></p> <h2><strong>0x00 HTTPS</strong></h2> <p>在传统流行的web服务中,由于http协议没有对数据包进行加密,导致http协议下的网络包是明文传输,所以只要攻击者拦截到http协议下的数据包,就能直接窥探这些网络包的数据。</p> <p>HTTPS 协议就是来解决这个问题的,关于HTTPS协议的原理由于不是本文的主要讨论内容,所以大家可以到 <a href="http://www.open-open.com/lib/view/open1431006568476.html" rel="nofollow,noindex"> 大型网站的 HTTPS 实践(一)—— HTTPS 协议和原理 </a> 这里查看。</p> <p>简而言之,HTTPS协议在应用层的http协议和以及传输层TCP协议之间的会话层加入了 SSL/TLS协议,用作加密数据包。会话层的这个加密协议,在真正数据传输之前,进行握手通信,握手的信息交换主要包括:双方确认加密协议的版本,确认身份(其中浏览器客户端的身份有时是不需要确认的),确认传输真正数据的加密密码(对称加密)。</p> <p>在用作信息传输的加密密码确认之后,接下来的通信数据都会加密后再传输,从而达到防窃取的作用。</p> <h2><strong>0x01 HTTPS 协议降级</strong></h2> <p>那么使用了https就能确保安全传输了吗?</p> <p>可以说理想上是的,现实却不是。</p> <p>原因简单来说就是:设计和实现SSL/TLS协议出现了漏洞,导致攻击者同样可以攻击一些旧版本的SSL/TLS协议。当SSL/TLS加密协议漏洞爆出来之后,最新版本的SSL/TLS协议修复了已知漏洞,但旧版本的加密协议却变得不安全了。</p> <p>那么什么又是“HTTPS协议降级”?</p> <p>在上一小节我们提到SSL/TLS协议通过握手来确定通信信息,其中握手双方要统一加密协议版本。</p> <p>在握手过程中这样确认加密协议版本:</p> <ol> <li>由客户端(如浏览器)发送第一个数据包 ClientHello,这个数据包中保存着客户端支持的加密协议版本。</li> <li>服务器收到这个ClientHello数据包,查看里面客户端支持的加密协议版本,然后匹配服务器自己支持的加密协议版本,从而确认双方应该用的加密协议版本。</li> <li>服务器发送ServerHello数据包给客户端,告诉客户端要使用什么加密协议版本。</li> </ol> <p>在上述过程中,如果客户端发送给服务器的ClientHello数据包中说自己仅支持某个有漏洞的旧版本加密协议(比如仅支持SSLv3.0),服务器有两种可能:</p> <ol> <li>服务器支持很多版本,其中包括有漏洞的旧版本和新版本(包括了SSLv3.0协议),那么服务器会认可使用有漏洞的旧版本协议,从而告诉客户端使用有漏洞的旧版本(可以使用SSLv3.0)。</li> <li>服务器不支持有漏洞的旧版本,拒绝客户端的这次请求,握手失败。</li> </ol> <p>对于攻击者,作为中间人只能监听到加密过的数据,如果这些数据通过没有漏洞的加密版本加密,攻击者并不能做什么。</p> <p>但是,如果服务器提供有漏洞的旧版本加密协议的支持,而同时攻击者又能作为中间人控制被攻击者的浏览器发起漏洞版本的HTTPS请求,那虽然攻击者监听到的也是加密过的数据,但因为加密协议有漏洞,可以解密这些数据,所以数据就和明文传输没有什么差别了。</p> <p>这就是HTTPS协议降级。</p> <h2><strong>0x02 SSLv3.0 的AES加密原理</strong></h2> <p>攻击者通过握手将HTTPS通信协议降低到SSLv3.0之后,将会拦截到经过SSLv3.0加密过的数据,Padding Oracle攻击可以解密这些数据。</p> <p>为什么叫 Padding,我们从SSLv3.0的加密原理说起。</p> <p>也是在第一小节,HTTPS握手过程中,通信双方还确认了一个“加密密码”,这个密码是双方在握手过程中使用 非对称加密 的方式协商出来的 对称加密 密码。攻击者能拦截到的数据就是被这个密码加密的。</p> <p>这个对称加密使用 AES加密 ,AES块密码会把要加密的明文切分成一个个整齐的块(如将明文以16个字节为一块分成很多块),如果最后一块不足一块,则会填充(Padding)满一块,再进行加密。这个填充就是Padding Oracle攻击的关键。</p> <p>AES是典型的块密码,块密码的加密方式有很多种,如果你不了解,可以查看 块密码的工作模式 。</p> <p>SSLv3.0中使用AES-CBC模式加密,我们来看加密和解密流程:</p> <p>加密过程图示:</p> <p><img src="https://simg.open-open.com/show/58e228b82668e55ffb5cfc7c91f868ed.png"></p> <p>加密过程:</p> <ol> <li>明文首先被分成很多明文块,所有明文块的字节长度都一样,其中最后一个明文块经过了填充,若假设最后一个填充字节值为L,则填充内容为值为L的字节重复L次(不包括最后一个字节本身) 。</li> <li>加密从第一个明文块开始链式依次进行,其中,第一个明文块先和初始化的向量进行异或,之后使用加密key加密,生成第一个密文块。</li> <li>将第一个密文块与第二个明文块异或,然后使用加密key加密,生成第二个密文块。</li> <li>以此类推,第N个密文块,由第N-1个密文块和第N个明文块异或,然后使用加密key加密获得。</li> <li>将所有获得的密文块依次拼接起来,就得到了最后的加密数据,这个数据是暴露在网络流量中的数据,也是攻击者可能截获的数据。</li> </ol> <p>解密过程图示:</p> <p><img src="https://simg.open-open.com/show/6962febdc23696422536a047bf37ff0f.png"> 解密过程:</p> <ol> <li>将密文内容分为若干个密文块,每个密文块和加密时的明文块长度一样,此时由于加密时经过了填充,密文内容肯定能整齐的分割成整数个密文块。</li> <li>对于第一个密文块,使用加密key解密之后,与加密时的初始化响亮异或获得第一个明文块。</li> <li>对于其他的密文块,如第N个,使用加密key解密之后,与第N-1个密文块异或,获得相应的明文。</li> </ol> <p>这就是SSLv3.0的加密原理过程。</p> <h2><strong>0x03 CBC模式加密 的 Padding Oracle攻击</strong></h2> <p>上一节我们解释了CBC模式加密过程,这种模式使用不当会遭到针对于Padding的攻击。</p> <p>对于SSL协议,需要加密的数据包括信息本身和信息的MAC摘要值,在协议设计初期,由于大家考虑不周,使用了“先做信息摘要MAC DATA,再做加密”的方式(MAC-then-encrypt)。</p> <p>MAC-then-encrypt,这种方式可能遭到Padding Oracle攻击。SSL协议在这种方式下,数据格式如图:</p> <p><img src="https://simg.open-open.com/show/129090655811c56755c77dbbd96b96ee.png"> 这是一次请求要传递的数据结构示意,其中Data为最重要的数据,包括 cookie甚至用户名密码等信息,HMAC 如图示是Data以及其他一些序列数据的MAC摘要,最后是补充字节的Padding。</p> <p>在这种数据结构下,加密数据传输到接收者手里,会解密然后依次验证Padding数据和HMAC数据,来确认数据是正确的。</p> <p>因此,接收者解密验证时主要有三种可能发生的情况:</p> <ol> <li>Padding数据错误,拒绝,返回。</li> <li>HMAC数据错误,拒绝,返回。</li> <li>正确接收。</li> </ol> <p>这3种返回给予了攻击者启示,我们再来看解密过程:</p> <p><img src="https://simg.open-open.com/show/dcbe02b30beb30d3357a5c7c843b4c47.png" alt="HTTPS 协议降级攻击原理" width="550" height="301"> 留意最后一个密文块,这个密文块首先会用加密key进行解密,然后与倒数第二个密文块进行异或。</p> <p>攻击者是能够截获到所有的密文内容的。</p> <p>我们提到过Padding数据的规则是:若假设最后一个填充字节值为L,则填充内容为值为L的字节重复L次(不包括最后一个字节本身) 。而验证padding的过程也是按照规则来的:读取最后一个字节的值,并移除最后一个字节,然后验证剩下的padding为L个值为L的字节。</p> <p>也就是说,当最后一个字节值为 0x00 的时候,padding验证会直接通过。</p> <p>假设:</p> <ol> <li>倒数第二个密文块的最后一个字节值为 x(攻击者可见的)。</li> <li>最后一个密文块,解密后最后一个字节值为 a (攻击者不可见)。</li> <li>最后一个明文块最后一个字节为 m (攻击者不可见)。</li> </ol> <p><img src="https://simg.open-open.com/show/5dc70daa162d688538304632d467b84c.png"> 可知, a = x 异或 m 并且 m = x 异或 a。</p> <p>然后攻击者不断修改x的值,发送给接收者,那么m的值也会不断变化,并发生padding数据验证失败返回。除非 m 变成 0x00, 此时不会返回padding数据验证失败,而会返回HMAC数据验证失败。假设此时, m 的值被改为了 c,如图。</p> <p><img src="https://simg.open-open.com/show/daff5b6515b061fa1589140e971aa201.png"> 可知, a = c 异或 0x00。</p> <p>由于 a = x 异或 m 并且 m = x 异或 a。</p> <p>所以 m 也就是明文, m = x 异或 c 异或 0x00。其中, x攻击者已知, c通过不同的返回获知。 从而破解了明文中的最后一个字节。</p> <p>有了 m 的值,也同时得到了 a 的值, 可以通过修改 x 的值控制m,比如修改 x 的值使</p> <p>m = 0x01 = x 异或 a。</p> <p>将 m 设置成 0x01 的时候,遍历倒数第二个密文块的倒数第二个字节(最多256次),通过判断是否通过padding验证,就能同理求出另外一个字节了。</p> <p>以此类推可以解密整个数据包。</p> <h2><strong>0x04 Padding Oracle攻击的防范</strong></h2> <p>通过上一节可以看到攻击者是通过padding验证返回 和 mac验证返回结果不同来获得信息的,实际上,即使padding验证失败和mac验证失败都返回同样结果,攻击者也可以通过响应时间的不同通过 timing的方式获得信息。</p> <p>所以在协议中将验证失败的响应时间和响应结果统一,使攻击者不能区分能防范这种攻击。</p> <p>而对于SSL/TLS协议的使用者,我们可以响应号召在自己服务器的加密协议支持列表上去掉SSLv3.0 。</p> <h2><strong>0x05 参考资料</strong></h2> <ol> <li><a href="/misc/goto?guid=4959720746745789268" rel="nofollow,noindex">Padding oracles and the decline of CBC-mode cipher suites </a></li> <li><a href="/misc/goto?guid=4959720746834244010" rel="nofollow,noindex">The Cryptographic Doom Principle </a></li> <li><a href="/misc/goto?guid=4959720746921963562" rel="nofollow,noindex">POODLE attacks on SSLv3 </a></li> <li><a href="/misc/goto?guid=4959720747006497775" rel="nofollow,noindex">SSL v3 Poodle安全漏洞修复建议 </a></li> </ol> <p> </p> <p>来自:https://zhuanlan.zhihu.com/p/22917510</p> <p> </p>