分类
知识中心

Nginx实现OCSPStapling的方法

OCSP(OnlineCertificateStatusProtocol,在线证书状态协议)是用来检验证书合法性的在线查询服务,一般由证书所属CA提供。

在实际应用中,某些客户端会在TLS握手阶段进一步协商时,实时查询OCSP接口,并在获得结果前阻塞后续流程。OCSP查询本质是一次完整的HTTP请求—响应,这中间DNS查询、建立TCP、服务端处理等环节都可能耗费很长时间,导致最终建立TLS连接时间变得更长。

而OCSPStapling,是指服务端主动获取OCSP查询结果并随着证书一起发送给客户端,从而让客户端跳过自己去验证的过程,提高TLS握手效率。

那么,在我们常用的Nginx模式下,如何实现OCSPStaplin呢?小威将从四个方面为您讲述。

  一、要求

Nginxversion1.3.7以上

  二、自动OCSPStapling

1、在Nginx.conf添加如下到您的https配置下

ssl_staplingon;

ssl_stapling_verifyon;

resolver8.8.8.88.8.4.4valid=300s;

resolver_timeout5s;

ssl_trusted_certificateca.pem;

其中ca.pem为证书链中两张中级CA证书

2、验证OCSPStapling状态

openssls_client-connectlocalhost:443-tlsextdebug–status

已开启

OCSPresponse:

OCSPResponseData:

OCSPResponseStatus:successful(0x0)ResponseType:BasicOCSPResponse

……

未开启

OCSPresponse:noresponsesent

  三、手动OCSPStapling

1、获取OCSP地址

opensslx509-inserver.pem-noout-ocsp_uri

2、生成stapling.ocsp

opensslocsp-CAfile root.pem-issuer ca.pem-cert server.pem-urlhttp://ss.symcd.com-text-respout./stapling.ocsp

其中root.pem为两张中级CA证书和顶级根证书,ca.pem为两张中级CA证书,server.pem为服务器证书,顶级根证书请联系技术人员获取(下载连接:xx)。

注:stapling.ocsp需每次在update到期之前更新

3、在Nginx.conf添加如下内容到您的https配置下

ssl_staplingon;

ssl_stapling_verifyon;

resolver8.8.8.88.8.4.4valid=300s;

resolver_timeout5s;

ssl_trusted_certificateca.crt;

ssl_stapling_filestapling.ocsp;

其中ca.pem中为两张中级CA证书。

4、验证OCSPStapling状态

openssls_client-connectlocalhost:443-tlsextdebug–status

已开启

OCSPresponse:

OCSPResponseData:

OCSPResponseStatus:successful(0x0)ResponseType:BasicOCSPResponse

……

未开启

OCSPresponse:noresponsesent

  四、启用OCSPStapling的条件

在Nginx中配置ssl_staplingon并reload后,Nginx并不会马上获取OCSPResponse,它要等第一个请求过来,再发起异步OCSP请求,所以刚开始几个响应,很可能不带OCSPStapling。另外,有时候由于OCSP域名无法解析,或者服务器无法访问造成OCSPResponse获取失败,也会导致OCSPStapling无法生效。

分类
知识中心

Apache单IP配置多个HTTPS虚拟主机方案

在Apache文档中提到,不能在单个IP上同时有多个按名字识别的虚拟主机(“named virtual host”),其实不完全是这样,接下来我们就来演示下如何打破这一魔咒。

  使用SNI

SNI全称Server Name Indication(服务器名称指示),这个问题可以解决apache中的单IP多HTTPS虚拟主机,只有默认第一个站点的SSL生效的问题。但是这些技术需要浏览器的版本支持

  支持SNI的浏览器

*Mozilla Firefox 2.0 or later

*Opera 8.0 or later(the TLS 1.1 protocol must be enabled)

*Internet Explorer 7(Vista,not XP)or later

*Google Chrome(Vista,not XP)(NOT Chromium)

*Safari 3.2.1 Mac OS X 10.5.6

  支持SNI的web容器

*apache版本在2.2.12以上

*需要mod_gnutls或者mod_ssl模块的支持

*Openssl在0.9.8j后的版本也都支持了SNI的功能

  配置Apache

打开Apache/conf/extra/httpd-vhost.conf文件并找到以下参数进行配置。

Listen 443

NameVirtualHost*:443

<VirtualHost*:443>

ServerName www.test1.com

SSLOptions StrictRequire

DocumentRoot/path/to/ssl/enabled/site

SSLProtocol all-SSLv2-SSLv3

注意,这里我们同时禁用了SSLv2、SSLv3不安全的协议。

SSLHonorCipherOrder on

SSLCipherSuite HIGH:!RC4:!MD5:!aNULL:!eNULL:!NULL:!DH:!EDH:!EXP:+MEDIUM

SSLCertificateFile conf/server.crt

SSLCertificateKeyFile conf/server.key

SSLCertificateChainFile conf/ca.crt

完成上述操作后,将CA证书ca.crt配置到该路径下。

<Directory/path/to/ssl/enabled/site/>

SSLRequireSSL

Order Deny,Allow

Allow from All

</Directory>

</VirtualHost>

“`

最后,保存httpd-vhost.conf文件并退出,使用https方式访问网站,测试证书配置是否成功。

分类
网络新闻

百度主域名及网盘开始支持HTTPS加密浏览了

有消息称百度开始提供HTTPS加密浏览了,简单来说,HTTPS就是安全版的HTTP,即在HTTP下加入SSL层(Secure Sockets Layer:安全套接层),而后逐渐演变为TLS(Transport Layer Security:传输层安全)。

 

实际上,普通的HTTP浏览方式存在很大的安全隐患,用户与搜索引擎服务器间的交互有可能会遭遇第三方监听、干扰、截断等危险。比如我们在使用百度搜索某个关键词时,可能会遭到第三方的拦截,甚至通过技术手段来阻止用户的搜索操作。

据了解,早在2010年5月末,谷歌便开始支持近HTTPS(超文本加密传输协议)加密技术的搜索方式。此外,谷歌还在今年8月初的月份公告中表示,谷歌搜索将会把“是否采用加密协议(HTTPS)”纳入网站搜索排名算法的参考因素范围。

如今,百度终于走出了支持HTTPS加密浏览模式这一步。下一步是否会开始主动抓取使用HTTPS协议的站点呢?

分类
知识中心

常见HTTPS攻击方法——解析

0x00 背景

研究常见的https攻击方法

Beast crime breach,并针对https的特性提出一些安全部署https的建议。

针对于HTTPS的攻击,多存在于中间人攻击的环境中,主要是针对于HTTPS所使用的压缩算法和CBC加密模式,进行side-channel-attack。这几类攻击的前置条件都比较苛刻,且都需要受害主机提交很多次请求来收集破译关键数据的足够信息。

常见的攻击方法,主要有,BEAST、Lucky-13、RC4 Biases、CRIME、TIME、BREACH等。主要对其中几种进行介绍。

  0x01 CRIME

Compression Ratio Info-leak Made Easy

攻击原理

攻击者控制受害者发送大量请求,利用压缩算法的机制猜测请求中的关键信息,根据response长度判断请求是否成功。

如下面的https头,攻击这可以控制的部分为get请求地址,想要猜测的部分为Cookie。那么攻击者只需要在GET地址处,不断变换猜测字符串,进行猜测。

GET /sessionid=a HTTP/1.1Host: bank.comUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0) Gecko/20100101 Firefox/16.0Cookie: sessionid=d3b0c44298fc1c149afbf4c8996fb924GET /sessionid=a HTTP/1.1Host: bank.comUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0)Gecko/20100101 Firefox/16.0Cookie: sessionid=d3b0c44298fc1c149afbf4c8996fb924

比如上面的情况Response长度为 1000byte。

GET /sessionid=d HTTP/1.1Host: bank.comUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:16.0)Gecko/20100101 Firefox/16.0Cookie: sessionid=d3b0c44298fc1c149afbf4c8996fb924

当攻击者猜对了cookie的第一个字母,Response的长度会缩小到9999byte。

当Response被SSL加密之后,如果使用RC4加密模式,长度并不会发生随机改变。使用BCB加密模式时,因为padding的原因,长度会有略微的改变。

受影响的加密算法

Deflate = LZ77 + HuffMan

GZip = Headers + Data Compressed using Deflate

攻击前提

攻击者可以获取受害者的网络通信包。(中间人攻击,ISP供应商)

浏览器和服务器支持均支持并使用压缩算法。

攻击这可以控制受害者发送大量请求并可以控制请求内容。

防御方法

客户端可以升级浏览器来避免这种攻击。

▪ Chrome: 21.0.1180.89 and above▪ Firefox: 15.0.1 and above▪ Opera: 12.01 and above▪ Safari: 5.1.7 and above

服务器端可以通过禁用一些加密算法来防止此类攻击。

Apache

• SSLCompression flag = “SSLCompression off”

• GnuTLSPriorities flag = “!COMP-DEFLATE”

禁止过于频繁的请求。

修改压缩算法流程,用户输入的数据不进行压缩。

随机添加长度不定的垃圾数据。

TLS 1.0.SPDY protocol (Google).Applications that uses TLS compression.Mozilla Firefox (older versions) that support SPDY.Google Chrome (older versions) that supported both TLS and SPDY.

POC

这个poc并不是模拟真实环境下的中间人攻击,只是在python中利用CRIME的思想验证了攻击的可行性。

import string import zlib import sys import random charset = string.letters + string.digits COOKIE = ”.join(random.choice(charset) for x in range(30)) HEADERS = (“POST / HTTP/1.1rn” “Host: thebankserver.comrn” “Connection: keep-alivern” “User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1rn” “Accept: */*rn” “Referer: https://thebankserver.com/rn” “Cookie: secret=”+COOKIE+”rn” “Accept-Encoding: gzip,deflate,sdchrn” “Accept-Language: en-US,en;q=0.8rn” “Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3rn” “rn”) BODY = (“POST / HTTP/1.1rn” “Host: thebankserver.comrn” “Connection: keep-alivern” “User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1rn” “Accept: */*rn” “Referer: https://thebankserver.com/rn” “Cookie: secret=”) cookie = “” def compress(data): c = zlib.compressobj() return c.compress(data) + c.flush(zlib.Z_SYNC_FLUSH) def getposset(perchar,chars): posset = [] baselen = len(compress(HEADERS+perchar)) for i in chars: t = len(compress(HEADERS+ perchar+i)) if (t<=baselen): posset += i return posset def doguess(): global cookie while len(cookie)<30: posset = getposset(BODY+cookie,charset) trun = 1 tem_posset = posset while 1<len(posset): body.find(?rn?)=”” while=”” true=”” return=”” posset[0]=”” print=”” +=”posset[0]” cookie=”” false=”” len(posset)=”=0:” if=”” +1=”” trun=”trun” posset=”getposset(tem_body+cookie,tem_posset)” tem_body=”BODY[trun:]”>=0: if not doguess(): print “(-)Changebody” BODY = BODY[BODY.find(“rn”) + 2:] print “(+)orign cookie”+COOKIE print “(+)Gotten cookie”+cookie

  0x02 TIME

Timing Info-leak Made Easy

攻击原理

攻击者控制受害者发送大量请求,利用压缩算法的机制猜测请求中的关键信息,根据response响应时间判断请求是否成功。其实TIME和CRIME一样都利用了压缩算法,只不过CRIME是通过长度信息作为辅助,而TIME是通过时间信息作为辅助。

Unable to render embedded object: File (1.jpg) not found.

如上图当数据长度,大于MTU时会截断为两个包发送,这样就会产生较大的相应时间差异。攻击者吧包长控制在MTU左右,不断尝试猜测COOKIE。 Unable to render embedded object: File (QQ图片20140724174303.jpg) not found.

如上图所示,我们通过添加Padding来吧数据包大小增加到和MTU相等,Case 1中我们添加的extraByte和需要猜测的数据重合,因为压缩算法的原因,并不会增加包的长度,而Case 2中extraByte和需要猜测的数据并不一致,导致了分包。攻击这可以通过响应时间的不同来区分Case1 Case2两种情况。

攻击前提

攻击这可以控制受害者发送大量请求并可以控制请求内容。

稳定的网络环境。

防御方法

在解密Response过程中加入随机的短时间延迟。

阻止短时间内的频繁请求。

  0x03 BEAST

Browser Exploit Against SSL/TLS

攻击原理

攻击者控制受害者发送大量请求,利用CBC加密模式猜测关键信息。

CBC模式工作的方法是当加密第i块的时候,和第i-1块的密文异或。更正式地表达如下:

Ci= E(Key, Ci-1 ? Mi)

很显然,当你加密第一块的时候,没有前一块的密文和它异或,因此,标准的做法是产生一个随机的初始化向量(IV),并且用它和第一块明文异或。第一块M0的加密如下:

C0= E(Key, IV ? M0).

然后,接着第一块M1加密如下:

C1= E(Key, C0 ? M1).

现在,除非C0 碰巧和IV一样(这是非常不可能的),那么,即使M0 = M1,对于加密函数来说,两个输入是不同的,因此,C0≠ C1。 CBC有两种的基本的使用方法:

1. 对于每条记录都认为是独立的;为每一个记录产生一个IV

2. 把所有的记录当作一个链接在一起的大对象,并且在记录之间继续使用CBC的状态。这意味着最后一条记录n的IV是n-1条记录的密文。

SSLV3和TLS1.0选择的是第二个用法。这好像本来就是个错误

CBC有两种的基本的使用方法:

1. 对于每条记录都认为是独立的;为每一个记录产生一个IV

2. 把所有的记录当作一个链接在一起的大对象,并且在记录之间继续使用CBC的状态。这意味着最后一条记录n的IV是n-1条记录的密文。

SSL 3.0和TLS1.0选择的是第二个用法。因此产生了加密算法的安全问题。

攻击者可以把想要猜测的数据段替换掉成:

X ? Ci-1 ? P

当这个注入的内容被加密,X会被异或,结果传给加密算法的明文块如下:

Ci-1 ? P

如果P==Mi , 新的密文块将和Ci一样,这意味着,你的猜测是正确的。

攻击前提

攻击者可以获取受害者的网络通信包。(中间人攻击,ISP供应商)

攻击者需要能得到发送敏感数据端的一部分权限。以便将自己的信息插入SSL/TLS会话中。

攻击者需要准确的找出敏感数据的密文段。

攻击这可以控制受害者发送大量请求并可以控制请求内容。

防御方法

使用RC4加密模式代替BCB加密模式。

部署TLS 1.1或者更高级的版本,来避免SSL 3.0/TLS 1.0带来的安全问题。

在服务端设置每传输固定字节,就改变一次加密秘钥。

影响范围

TLS 1.0.

SPDY protocol (Google).

Applications that uses TLS compression.

Mozilla Firefox (older versions) that support SPDY.

Google Chrome (older versions) that supported both TLS and SPDY.

POC

仅在python上模拟了攻击思想的实现,编码中只实现了第一个字母的猜测。

import sys import string import random from Crypto.Cipher import AES key = ‘lyp62/22Sh2RlXJF’ mode = AES.MODE_CBC vi = ‘1234567812345678’ charset = string.letters + string.digits cookie = ”.join(random.choice(charset) for x in range(30)) HEADERS = (“POST / HTTP/1.1rn” “Host: thebankserver.comrn” “Connection: keep-alivern” “User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1rn” “Accept: */*rn” “Referer: https://thebankserver.com/rn” “Cookie: secret=”+cookie+”rn” “Accept-Encoding: gzip,deflate,sdchrn” “Accept-Language: en-US,en;q=0.8rn” “Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3rn” “rn”) global pad_num def add_padding(plaintext): global pad_num pad_num = 16 – len(plaintext) % 16 for i in range(0,pad_num): plaintext += chr(pad_num) return plaintext def check_padding(plaintext): global pad_num for i in range(1,pad_num+1): if (plaintext[-i]!=chr(pad_num)): return False return True def encrypto(plaintext): global pad_num obj = AES.new(key,mode,vi) if (len(plaintext) % 16): plaintext = add_padding(plaintext) else: pad_num=0 ciphertext = obj.encrypt(plaintext) if (check_padding(ciphertext)): return ciphertext else: return 0 def decrypto(ciphertext): obj = AES.new(key,mode,vi) plaintext = obj.decrypt(ciphertext) return plaintext def findcookie(): global HEADERS return HEADERS.find(‘secret=’)+7 guess_cookie=” pos_cookie=findcookie() pos_block_s = pos_cookie + 16 – pos_cookie%16 HEADERS = HEADERS[:pos_cookie] + (16 – pos_cookie % 16 + 15)*’a’ +HEADERS[pos_cookie:] encry_head = encrypto(add_padding(HEADERS)) per_per_block = encry_head[pos_block_s – 16:pos_block_s] #Ci-1 per_block = encry_head[pos_block_s:pos_block_s+16] #x aft_block = encry_head[pos_block_s+16:pos_block_s+32] #Ci+1 for i in charset: guess_block = ‘a’ * 15 + i insert_block = ”.join(chr(ord(a) ^ ord(b) ^ ord(c)) for a,b,c in zip(per_block,per_per_block,guess_block)) temp_header = HEADERS[:pos_block_s+16] + insert_block + HEADERS[pos_block_s+16:] encry_temp_header = encrypto(add_padding(temp_header)) if (aft_block == encry_temp_header[pos_block_s+32:pos_block_s+48]): print “(+)first byte is:”+i print “(+)orign cookie:”+cookie

攻击者首先使用降级攻击,来让浏览器使用ssl v3.0,再通过ssl v3.0 CBC-mode 存在的缺陷,窃取到用户传输的明文。

  0x04 POODLE

降级攻击

ssl v3.0是一个存在了很久的协议了,现在大多数浏览器为了兼容性都会支持这个协议,但是并不会首先使用这个协议,中间人攻击者可以驳回浏览器协商高版本协议的请求,只放行ssl v3.0协议。

Padding Oracle攻击

针对于CBC的攻击之前已经有一些了,比如,Beast,Lucky17之类的,详细可以看这里

首先来看CBC-mod的加解密流程。

常见HTTPS攻击方法——解析-1

  解密流程

常见HTTPS攻击方法——解析-1

  加密流程

常见HTTPS攻击方法——解析-2

  校验流程

MAC1 = hash(明文)

密文 = Encode(明文+MAC1+Padding,K) 明文 = Decode(密文,k) – MAC1-Padding(padding的长度由最后一个字节标识)

MAC2 = hash(明文) 如果 MAC1 == MAC2 则校验成功 否则失败

知二求三

Padding Oracle 攻击一般都会满足一个知二求三的规律,如下图

(1) VI

(2) 解密后的数据,叫它 midText把

(3) Plaintext

这三个值我们得到其中两个就可以推出另外一个,因为他们在一起Xor了嘛。

/uploadImages/2015/001/4FR36E9F7YI0.jpg

在Poodle攻击中,我们会把最后一个数据块替换成我们想要猜测的数据块。如下图所示。

常见HTTPS攻击方法——解析-4

  这样导致的直接后果就是,CBC完整性验证失败,数据包被驳回。我们假设最后一个数据块均为padding组成(其实我们可以通过控制包的长度来达到这一目的,比如增加path的长度)

那么当且仅当Plaintext[7] == 7(block为16为时为15) 的时候CBC完整性校验才会通过。如果不为7,多删或者少删的padding,都会影响到MAC的正确取值,从而导致校验失败。

那么,我们只需要不断地更改(1) IV 最后一位的值 ,直到(3) Plaintext最后一位为 7 (CBC验证通过)的时候,我们就可以推出 (2) mid text 的最后一位。

常见HTTPS攻击方法——解析-3

  0x05 安全配置建议

此处的安全配置以nginx为例,主要在Nginx.conf中配置。

使用较为安全的SSL加密协议

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

使用严格的加密方法设置。

ssl_ciphers ‘ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES256-GCM-SHA384:AES128-GCM-SHA256:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4’;

优先依赖服务器密码。

ssl_prefer_server_ciphers on;

启用HSTS协议。

add_header Strict-Transport-Security max-age=15768000;

重定向的配置

server {

listen 80;

add_header Strict-Transport-Security max-age=15768000;

return 301 https://www.yourwebsite.com$request_uri;

}

使用2048位的数字证书

openssl dhparam -out dhparam.pem 2048

ssl_dhparam /path/to/dhparam.pem;

分类
知识中心

HTTPS与SNI扩展,一个IP绑定多个SSL证书

在搭建支持HTTPS的前端代理服务器时候,通常会遇到让人头痛的证书问题。根据HTTPS的工作原理,浏览器在访问一个HTTPS站点时,先与服务器建立SSL连接,建立连接的第一步就是请求服务器的证书。而服务器在发送证书的时候,是不知道浏览器访问的是哪个域名的,所以不能根据不同域名发送不同的证书。用过GoAgent的人都知道需要给浏览器导入证书才能使用HTTPS正常登录Twitter等网站。

SNI(Server Name Indication)是为了解决一个服务器使用多个域名和证书的SSL/TLS扩展。一句话简述它的工作原理就是,在连接到服务器建立SSL链接之前先发送要访问站点的域名(Hostname),这样服务器根据这个域名返回一个合适的证书。目前,大多数操作系统和浏览器都已经很好地支持SNI扩展,OpenSSL 0.9.8已经内置这一功能,据说新版的nginx也支持SNI。

HTTPS与SNI扩展,一个IP绑定多个SSL证书-1

Github上有一个小巧的支持SNI的代理服务器,https://github.com/dlundquist/HTTPS-SNI-Proxy

我down下来,在一个VPS上编译(需要安装pcre的开发库),写了一个简单的配置文件,把所有访问443端口的HTTPS请求都进行代理。启动sni_proxy之后,修改本地的hosts文件,把twitter.com映射为服务器的IP地址,比如我的是

184.82.206.107 twitter.com

然后,在浏览器里访问 https://twitter.com/。

HTTPS与SNI扩展,一个IP绑定多个SSL证书-2

看到木有,这是活生生的twitter的证书。

HTTPS与SNI扩展,一个IP绑定多个SSL证书-3