近期要做入网安评,网站需要开启HTTPS,因此学习了一下HTTPS。
主要学习链接: 小茗的博客 阮一峰的网络日志
1. 什么是HTTPS
HTTPS全称是Hyper Text Transfer Protocol over Secure Socket Layer,直译过来就是通过SSL实现的超文本传输协议,简单来说就是加密版的HTTP,即HTTP+SSL/TLS。
为什么需要使用加密版的HTTPS呢?因为HTTP是明文传输,使用HTTP传输隐私信息非常不安全,很容易在传输过程中被别人窃取,或者通讯内容被别人篡改冒充,使用加密的HTTPS协议传输可以避免这些问题。
2. SSL/TLS
为了解决HTTP明文传输的风险性,网景公司设计了SSL(Secure Sockets Layer)协议用于对HTTP协议传输的数据进行加密,从而就诞生了HTTPS。SSL目前的版本是3.0,被IETF(Internet Engineering Task Force)定义在RFC 6101中,之后IETF对SSL 3.0进行了升级,于是出现了TLS(Transport Layer Security) 1.0,定义在RFC 2246。实际上我们现在的HTTPS都是用的TLS协议,但是由于SSL出现的时间比较早,并且依旧被现在浏览器所支持,因此SSL依然是HTTPS的代名词。
上面一大段话是转载的,简单而言就是TLS是SSL的升级版,现在浏览器一般用的都是TLS。
3. SSL协议的握手过程
开始加密通信之前,客户端和服务端必须建立连接和交换参数,这个过程叫做握手(HandShake)。
假设客户端为爱丽丝,服务器为鲍勃,整个握手过程可以用下图说明:
整个握手过程分为5步:
1、爱丽丝给出协议版本号、支持的加密算法和客户端生成的随机数(client random);
2、鲍勃从支持的加密算法中选一个加密密度最高的算法,也生成一个随机数(server random),并传送数字证书;
3、爱丽丝验证数字证书(是否是可信机构签订的证书、域名是否一致、证书是否过期),并且用数字证书的公钥加密新生成的随机数(premaster key);
4、鲍勃用自己证书的私钥解密随机数(premaster key);
5、爱丽丝和鲍勃根据之前约定的加密算法,用前面的三个随机数(客户端第一次生成的随机数、服务端生成的随机数、客户端第二次生成的加密随机数)生成对话密钥(session key该密钥不会进行传输),用来加密接下来的整个对话过程。
上面5步,画成一张图就是这样:
4. 私钥的作用
握手阶段有三个需要注意:
a.“对话密钥”需要3个随机数来生成;
b.客户端生成的第二个随机数(Premaster key)是使用公钥加密,服务器使用私钥解密的(非对称加密),至此无其他所用;握手之后的通话是使用“对话密钥”加密(使用的是对称加密,提高通话效率);
c.服务器的公钥放在数字证书中。
握手的整个过程都是明文传输的(也无法加密),因此如果有人窃听的话,可以知道客户端、服务器选择的加密算法,也可以获取三个随机数的其中两个。因此整个通话的安全取决于第三个随机数。
理论上,只要公钥的长度够长(如2048位),那么Premaster key就可以保证不被破解。
5. CA机构的作用
(以下是自我见解,如有错误,还请斧正)
数字证书是由CA机构(证书授权中心)颁发的,我们也可以自签证书,自签证书同样也可以加密通话,那自签证书和数字证书有什么区别呢?为什么需要CA机构呢?他们的区别在于“合法性”,CA机构给一个域名签订证书(DV SSL证书类型)会审核申请人的身份是否是该域名的拥有者,如果申请企业型OV SSL证书或者增强型EV SSL证书则验证会更加严格,还需要审核企业身份信息、证件等。这样就保证了只有拥有该域名所有权的人才能拿到该域名的数字证书。如果是自签证书或者山寨CA机构,不验证审核上面的那些信息就随便颁发了证书,即不是这个域名的拥有者也可以拿到该域名对应的证书。这样就会被有心之人恶意使用,把该证书挂在伪冒山寨的网站(跟真实正版的网站页面基本一样)上,误导用户填写信息,盗取用户的隐私,造成财产损失。或者用于https劫持,盗取用户信息(下面会模拟https劫持)。
因此浏览器在访问https网站时,只信任权威CA机构颁发的证书,自签证书或者山寨CA颁发的证书都无法通过浏览器的验证,直接显示隐私安全错误:
操作系统安装时就预装了几大机构的根证书,如Windows(输入命令certmgr.msc查看):
只有这些机构或者其子机构颁发的证书浏览器才会信任。比如百度就是GlobalSign机构颁发的证书:
除了审核域名拥有者的信息,保证了数字证书公钥的可靠性,CA机构还保证颁发证书的唯一性,不可伪造(通过数字签名保证,数字证书是使用CA机构的私钥进行加密的,然后通过操作系统保存的CA公钥进行解密,能解密通过则证明是该CA机构颁发的证书。因此想要伪造证书必须拿到CA机构的私钥,CA机构的私钥都是高度保密的,一般难以盗取);还保存了数字证书的申请使用日志,倘若该网站进行违法行为,可以锁定违法者;如果不小心泄露了数字证书的私钥,CA机构可以对证书进行注销,避免网站通话信息被破解泄露。
6. 数字证书的作用
一般数据证书包括以下这几个字段信息,如颁发者、有效期、使用者、公钥等,下面是百度证书的信息。验证证书是否有效,有三个重要的因素,一是颁发者是否是信任的权威机构,二是该证书签发的域名是否跟访问的域名一致,三是该证书是否在有效日期内。验证证书有效后,就可以使用证书的公钥进行SSL握手,加密通话了。
验证域名一致可以防止DNS域名劫持,如果访问的域名解析IP时被劫持到盗版服务器的IP,如果是一般的http访问就无法识别盗版网站,而https会验证访问的域名和证书的域名是否一致。因为浏览器只认权威机构颁发的证书,而向权威机构申请证书则必须是该域名的拥有者,而且证书无法伪造。因此盗版网站无法获得该域名的证书,也无法伪造,因为无法通过域名一致的验证,浏览器报安全隐私错误,提示用户不要连接,可以有效防止DNS域名劫持。
通过证书确保了域名一致正版网站,并且加密通话内容,这就保证了用户的隐私信息安全。但数字证书无法避免钓鱼网站的威胁,因为钓鱼网站使用的域名跟真实域名差不多,网站页面也基本一样,具有迷惑性,但他是这个域名的拥有者,他可以申请证书,浏览器不会报错,从而误导用户填写隐私信息进行盗取。对于此使用增强型EV SSL证书可以减低钓鱼网站的威胁,使用了EV SSL证书的网站浏览器地址栏显示为绿色,或者显示为企业名称,正版企业名称这是钓鱼网站不可伪造的。因此认准域名或者浏览器地址栏企业名称,对于需要输入隐私信息或者涉及金额的网站更要留意,可以进一步保护隐私安全。
7. HTTPS劫持
正常来说,https通话内容被监听或者修改,看到的都是乱码的密文或者无法通过数据校验,这都是盗取不了用户的信息的。
但存在一些特殊情况,如果你无意中添加了一些作恶的根证书到系统中,或者被别人恶意地添加了到系统中,比如之前12306网站的访问就需要手动添加其证书到系统中:
12306是我们中国铁路局的网站,源于我们对此信任,相信该局不会乱颁发证书,因此把该证书手动添加了到系统中。但这样手动添加是有安全漏洞的,如果一不小心访问了假了的12306网站,也是要手动添加证书的,这样就把作恶的根证书添加进去了,从此访问所有的https网站都有可能被劫持了(下面会通过Fiddler演示)。而且中铁信息工程集团本身是未经审计的证书签发机构,同时也没有 PKI 基础设施对证书进行管理或者吊销操作,如果 SRCA 根证书出现安全问题,例如泄露了私钥,那么中铁信息工程集团也没有办法及时吊销证书来防止伪造(来源蓝点网)。攻击者也可以伪造任意网站进行劫持了,例如支付宝、银行钓鱼网站,而浏览器不会拦截报错。
因此现在12306也是购买了正规证书,而不是自签证书了。
至于之前为什么用自签证书,肯定不是资金原因,我猜测是想成为一个CA机构吧,毕竟大部分买票的中国人都安装了该证书,那么大的一个体量,申请为CA机构也容易吧(纯属猜测哈)。或者作为一个国民网站,有更高的安全考虑吧。
另外一种被别人恶意添加到系统的情况,就比如安装的是盗版系统,一开始就把恶意的根证书和正规的根证书装在一起了,那安装该盗版系统的电脑都会有可能被劫持了。因此安装系统尽量找正规版本系统。
8. 使用Fiddler模拟HTTPS劫持
Fiddler是一个用于HTTP调试的代理服务器应用程序,可用于网络抓包,获取浏览器与服务器的通话内容。下面我们用Fiddler来模拟HTTPS劫持:
首先直接用Fiddler来监听浏览器与www.baidu.com的通话,由于百度使用了https协议,通话已使用https加密,因此直接监听是无法获取通话内容的,如下图所示:
接下来我们开启Fiddler的https解密功能,软件会提示生成一个唯一的根证书(应该Fiddler官方也无法知道和使用这个唯一的根证书,否则装了这个根证书的电脑所有https通话内容都有可能被监听),需要把该证书安装到系统中:
安装完成后,按WIN+R,输入certmgr.msc,查看受信任的根证书便可以看到DO_NOT_TRUST_FiddlerRoot证书已经安装到系统里了。
下面就可以使用Fiddler重新监听浏览器和www.baidu.com的通话了,这时我们可以看到www.baidu.com服务器返回给浏览器的内容已经被获取了。
再看下浏览器发现访问www.baidu.com使用的不是baidu自家公司签的证书了,反而用了DO_NOT_TRUST_FiddlerRoot颁发的证书。因此可知浏览器不是直接访问Baidu的服务器了,而是先访问Fiddler的代理服务器,再由代理服务器转发请求,因此使用的是Fiddler的证书。由于DO_NOT_TRUST_FiddlerRoot根证书已经安装,被系统信任了,因此浏览器不会报错。
至此就成功地进行https劫持,获取了用户与服务器的通话内容。使用Fiddler劫持https的主要原理如图8.7所示:
由此可见想要进行https劫持最关键的一步是在目标客户端安装根证书,然后攻击人就可以颁发任何域名的证书,而目标客户端不会提示任何安全错误,从而盗取用户与服务器的通话信息。因此只要不随意安装不明的根证书到系统中,使用https访问还是安全的。
9. 自签证书
为了方便本地开发调试,我们可以自签证书使用https,证书一般都是用openssl来生成,当然也可以用jdk自带的keytool来生成,但是最终还是要用openssl来转换格式,所以一般还是推荐用openssl来生成。
9.1下载openssl
首先到官网下载openssl,下载链接,按照电脑32或者64位下载安装即可。
为了使用方便,可将安装路径添加到环境变量Path中,然后就可以随时使用openssl命令了。
9.2生成CA根证书
生成一个自己的CA根证书ca.crt,然后再用这个根证书生成服务端证书server.crt。至于为什么不直接生成服务端证书呢?因为将来我们只要导入一个CA根证书,其它所有用它生成的证书都默认是可信任的,方便调试。
命令脚本为:
# 生成CA私钥
openssl genrsa -out ca.key 1024
# 生成CA根证书,-days指定证书有效期
openssl req -new -x509 -key ca.key -out ca.crt -days 365
运行命令后会在当前目录生成两个文件ca.key、ca.crt。
9.3生成服务端证书
和CA证书的生成不同的是,我们需要先生成一个csr证书请求文件文件(CSR,Cerificate Signing Request),有了这个文件之后再利用CA根证书生成最终的证书:
# 生成服务端私钥
openssl genrsa -out server.key 1024
# 生成证书请求文件
openssl req -new -key server.key -out server.csr
由于chrome还会检测是否指定了DNS Name或者IP地址,否则会报Subject Alternative Name missing错误:
因此我们先要准备一个名为openssl.cnf的文件,内容如下:
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
#IP.1 = 127.0.0.1
解释一下,这里的alt_names指的是最终可以访问的域名或者IP,所以其实一个证书是可以多个网站同时使用的。被访问域名只要满足DNS和IP中的一个,其证书就是合法的。然后再运行命令生成服务器证书文件:
# 生成最终证书文件,-days指定证书有效期
openssl x509 -req -days 365 -sha256 -CA ca.crt -CAkey ca.key -CAcreateserial -extfile openssl.cnf -extensions v3_req -in server.csr -out server.crt
操作截图如下,需要注意Common Name填的是服务器域名或者IP地址:
在当前目录就生成了server.crt证书了:
双击证书就可以看到颁发者、有效期、使用者、使用者可选名称(之前设置的alt_names):
10. 安装证书到Tomcat服务器
由于Tomcat使用证书的格式是jks的,因此需要将crt格式转换成jks格式:
#先将crt转成p12 -name指定证书别名
openssl pkcs12 -export -clcerts -inkey server.key -in server.crt -out server.p12 -name tomcat
#再将p12转成jks
keytool -importkeystore -srckeystore server.p12 -srcstoretype PKCS12 -deststoretype JKS -destkeystore server.jks
操作截图为:
完成后就可以看到当前目录生了server.jks的文件,然后把server.jks文件复制到Tomcat根目录下的conf文件夹下。如下图编辑conf/server.xml文档:
首先将8080 connector的redirectPort改成443,因为https默认使用443端口,方便以后将http的请求转发成https加密的请求:
<Connector connectionTimeout="20000" port="8080" protocol="HTTP/1.1" redirectPort="443"/>
然后增加https 443端口的connector:
<Connector port="443"
protocol="org.apache.coyote.http11.Http11NioProtocol"
SSLEnabled="true"maxThreads="150"
scheme="https" secure="true" maxHttpHeaderSize="81920"
clientAuth="false" sslProtocol="TLS"
ciphers="TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256"
sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2"
keystoreFile="conf/server.jks"
keystorePass="读取server.jks的密码"/>
scheme指定使用https协议,ciphers指定加密算法,keystoreFile指定jks证书路径,keystorePass指定读取jks证书的密码。
重启tomcat服务器就可以使用https://localhost访问tomcat主页了,但自签的证书并没有被系统信任,这时浏览器会报颁发机构无效的错误,提示当前网站不安全:
因此我们需要先将自签的CA根证书安装到系统中(这样是有安全漏洞的,仅做调试用):
安装完成后重启浏览器重新访问,这时就可以正常地使用https访问了。
11. 安装证书到Weblogic服务器
启动Weblogic控制台,选择需要安装的服务器,如AdminServer,然后双击进入服务器设置界面,在配置-一般信息中开启SSL监听端口,并将端口改成443。
然后点击配置-密钥库,按下图所示填写密钥信息,其中“密钥库密码短语”是第10节将证书p12格式转换成jks格式时设置的密码:
再进入配置-SSL页面按下图所示填写SSL证书信息,其中证书别名是第10节将证书crt格式转换成p12格式时设置的别名,私有密钥短语也是这时设置的密码:
配置好后保存,需要重启Weblogic才可以使SSL生效,之后就可以使用https访问Weblogic部署的应用了。
12. http请求转发到https请求
开启https后还是可以使用http访问的,为了把所有的http请求都转发到https请求,需要修改项目的web.xml:
<security-constraint>
<web-resource-collection>
<web-resource-name>SSL</web-resource-name>
<url-pattern>/*</url-pattern> <!-- 全站使用SSL -->
</web-resource-collection>
<user-data-constraint>
<description>SSL required</description>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
<!-- CONFIDENTIAL: 要保证服务器和客户端之间传输的数据不能够被修改,且不能被第三方查看到 -->
<!-- INTEGRAL: 要保证服务器和client之间传输的数据不能够被修改 -->
<!-- NONE: 指示容器必须能够在任一的连接上提供数据。(即用HTTP或HTTPS,由客户端来决定)-->
</user-data-constraint>
</security-constraint>
<login-config>
<auth-method>CLIENT-CERT</auth-method>
<realm-name>Client Cert Users-only Area</realm-name>
</login-config>
Tomcat服务器还要确保http的redirectPort和https的port都为https的默认端口443。
这样尽管浏览器客户端使用http访问也会自动转发使用https请求了。