【SEED Labs】Public-Key Infrastructure (PKI) Lab
Lab Overview
公钥加密是当今安全通信的基础,但当通信的一方向另一方发送其公钥时,它会受到中间人的攻击。根本的问题是,没有简单的方法来验证公钥的所有权,即,给定公钥及其声明的所有者信息,如何确保该公钥确实属于声明的所有者?公钥基础设施(PKI)是解决这一问题的一种切实可行的方法。
通过这个实验,我们应该能够更好地了解PKI是如何工作的,PKI是如何用来保护网络,以及PKI如何打败中间人攻击。此外,我们将能够了解在公钥基础设施中信任的根源,以及如果这种根源信任被破坏会出现什么问题。本实验所涵盖的主题如下:
• Public-key encryption
• Public-Key Infrastructure (PKI)
• Certificate Authority (CA) and root CA
• X.509 certificate and self-signed certificate
• Apache, HTTP, and HTTPS
• Man-in-the-middle attacks
Lab Environment
这个实验在我kali VM和Ubuntu 16.04 VM上进行了测试.在这个实验中,我们将使用openssl命令和库。
Lab Tasks
Task1: Becoming a Certificate Authority(CA)
证书颁发机构(CA)是发布数字证书的受信任实体。数字证书通过证书的命名主体来验证公钥的所有权。一些商业性的CAs被视为根类CAs;在撰写本文时,VeriSign是最大的CA。想要获得商业核证机关发出的数字证书的用户需要向这些核证机关支付费用。
在这个实验室,我们需要创建数字证书,但是我们不会支付任何商业CA,我们自己会成为一个根CA,然后用这个CA为其他人(比如服务器)颁发证书。在这个任务中,我们将使自己成为一个根CA,并为这个CA生成一个证书。RootCA的认证通常预装在大多数操作系统、web浏览器和其他依赖于PKI的软件中。根CA的证书是无条件信任的。
The Configuration File openssl.conf
为了使用OpenSSL创建证书,必须有一个配置文件。配置文件通常有一个extension.cnf。它由三个OpenSSL命令使用:ca、req和x509。可以使用谷歌搜索找到openssl.conf的手册页。还可以从/usr/lib/ssl/openssl.cnf获得配置文件的副本。将此文件复制到当前目录后,需要按照配置文件中指定的方式创建子目录(查看[CA default]部分):
对于index.txt文件,只需创建一个空文件。对于serial文件,在文件中放入一个字符串格式的数字(例如1000)。设置好配置文件openssl.cnf之后,就可以创建和颁发证书了。
CertificateAuthority(CA).
如前所述,我们需要为我们的CA生成一个自签名证书,这意味着这个CA是完全可信的,它的证书将作为根证书。运行以下命令为CA生成自签名证书:
系统将提示您输入信息和密码。不要丢失此密码,因为每次要使用此CA为其他人签名证书时,都必须键入口令。您还将被要求填写一些信息,如国家名称、常用名称等。该命令的输出存储在两个文件中:ca.key和ca.crt。文件CA .key包含CA的私钥,而CA .crt包含公钥证书。
Task2: Creating a Certificate for SEEDPKILab2018.com
现在,我们成为一个根CA,我们准备为我们的客户签署数字证书。我们的第一个客户是一家名为SEEDPKILab2018.com的公司。该公司要从CA获得数字证书,需要经过三个步骤。
Step 1: Generate public/private key pair 。公司需要首先创建自己的公钥/私钥对。可以运行以下命令来生成RSA密钥对(私有和公共密钥)。您还需要提供一个密码来加密私钥(使用AES-128加密算法,在命令选项中指定)。密钥将存储在文件服务器中。
server.key是一个编码的文本文件(也是加密的),因此无法看到实际内容,例如模数、私有指数等。要查看这些,可以运行以下命令:
Step 2: Generate a Certificate Signing Request (CSR). 一旦公司拥有了密钥文件,它应该生成一个证书签名请求(CSR),它基本上包括公司的公钥。CSR将被发送到CA, CA将为密钥生成证书(通常在确保CSR中的身份信息与服务器的真实身份匹配之后)。使用SEEDPKILab2018.com作为证书请求的通用名称。
需要注意的是,上面的命令与我们为CA创建自签名证书时使用的命令非常相似,唯一的区别是使用了-x509选项。没有它,命令生成一个请求;使用它,该命令生成一个自签名证书。
Step 3: Generating Certificates . CSR文件需要有CA的签名才能形成证书。在现实世界中,CSR文件通常被发送到受信任的CA进行签名。在这个实验中,我们将使用我们自己的可信CA来生成证书。以下命令使用CA的CA .crt和CA .key将证书签名请求(server.csr)转换为X509证书(server.crt):
如果OpenSSL拒绝生成证书,您请求中的名称很可能与ca的名称不匹配。匹配规则在配置文件中指定(查看[policy match]部分)。您可以更改请求的名称以符合策略,也可以更改策略。配置文件还包括另一个限制较少的策略(称为任何策略)。您可以通过更改以下行来选择该策略:
“policy = policy_match” change to “policy = policy_anything”.
Task3: Deploying Certificate in an HTTPS Web Server
在这个实验中,我们将探索网站如何使用公钥证书来保护web浏览。我们将使用openssl的内置web服务器建立一个HTTPS网站。
Step1: Configuring DNS .我们选择SEEDPKILab2018.com作为我们的网站名称。为了让我们的计算机识别这个名称,让我们将下面的条目添加到/etc/hosts;这个条目基本上将主机名SEEDPKILab2018.com映射到本地主机(即127.0.0.1):
Step 2: Configuring the web server. 让我们使用在上一个任务中生成的证书启动一个简单的web服务器。OpenSSL允许我们使用s_server命令启动一个简单的web服务器:
默认情况下,服务器将监听端口4433。您可以使用-accept选项进行更改。现在,您可以使用以下URL访问服务器:https://SEEDPKILab2018.com:4433/。最有可能的是,您将从浏览器中得到一条错误消息。在Firefox中,您将看到如下消息:“seedpkilab2018.com:4433使用了无效的安全证书。该证书不受信任,因为发布者证书未知”.
Step3: Getting the browser to accept our CA certificate. 如果我们的证书是由VeriSign分配的,就不会出现这样的错误消息,因为VeriSign的证书很可能已经预加载到Firefox的证书存储库中了。很遗憾,SEEDPKILab2018.com的证书是由我们自己的CA,并且Firefox无法识别此CA。有两种方法可以让Firefox接受CA的自签名证书。
- 我们可以请求Mozilla将我们的CA证书包含在Firefox软件中,这样每个使用Firefox的人都可以识别我们的CA。不幸的是,我们自己的CA没有足够大的市场让Mozilla包含我们的证书,所以我们不会追求这个方向。
- 加载CA .crt到Firefox中:我们可以手动添加我们的CA证书到Firefox浏览器通过点击下面的菜单序列:
Edit -> Preference -> Privacy & Security -> View Certificates
您将看到一个已经被Firefox接受的证书列表。从这里,我们可以“导入”我们自己的证书。请导入CA .crt,并选择以下选项:“信任此CA识别网站”。您将看到我们的CA证书现在位于Firefox接受的证书列表中。
Step4. Testing our HTTPS website . 现在,将浏览器指向https://SEEDPKILab2018.com: 4433,可以正常访问
Task4: Deploying Certificate in an Apache-Based HTTPS Website
使用openssl的s_server命令设置HTTPS服务器主要用于调试和演示目的。在这个实验中,我们基于Apache建立了一个真正的HTTPS web服务器。Apache服务器(已经安装在我们的VM中)支持HTTPS协议。要创建一个HTTPS网站,我们只需要配置Apache服务器,这样它就知道从哪里获得私钥和证书。
一个Apache服务器可以同时托管多个网站。它需要知道网站文件存储的目录。这是通过它的VirtualHost文件完成的,该文件位于/etc/apache2/sites-available目录中。要添加一个HTTP网站,我们需要在文件000-default.conf中添加一个虚拟主机条目。而要添加一个HTTPS网站,我们则需要在同一个文件夹的default-ssl.conf文件中添加一个VirtualHost条目。
ServerName条目指定网站的名称,而DocumentRoot条目指定网站文件存储的位置。在设置中,我们需要告诉Apache服务器证书和私钥存储在哪里。
修改了default-ssl.conf文件之后,我们需要运行一系列命令来启用SSL。Apache将要求我们输入用于加密私钥的密码。一旦一切都设置好了,我们就可以浏览网站了,浏览器和服务器之间的所有流量都被加密了。
Task5: Launching a Man-In-The-Middle Attack
在这个任务中,我们将展示PKI如何击败中间人(MITM)攻击。下图描述了MITM攻击的工作原理。假设Alice想通过HTTPS协议访问example.com。她需要从example.com服务器获取公钥;Alice将生成一个密钥,并使用服务器的公钥对该密钥进行加密,然后将其发送到服务器。如果攻击者可以拦截Alice和服务器之间的通信,则攻击者可以用自己的公钥替换服务器的公钥。因此,Alice的秘密实际上是用攻击者的公钥加密的,因此攻击者将能够读取秘密。攻击者可以使用服务器的公钥将密钥转发给服务器。秘密用于加密Alice和服务器之间的通信,因此攻击者可以解密加密的通信。
Step 1: Setting up the malicious website. 在Task 4中,我们已经为SEEDPKILab2018.com建立了一个HTTPS网站。我们将使用相同的Apache服务器模拟example.com 。为此,我们将按照任务4中的指令向Apache的SSL配置文件添加一个VirtualHost条目:ServerName应该是example.com,但配置的其余部分可以与任务4中使用的相同。我们的目标如下:当用户试图访问example.com时,我们将让用户登陆我们的服务器,其中为example.com托管一个假网站。如果这是一个社交网站,虚假网站可以显示一个登录页面类似于目标网站。如果用户不能分辨出两者的区别,他们可能会在假网页中输入他们的帐户凭据,本质上就是向攻击者披露凭据。
Step2: Becoming the man in the middle 。有几种方法可以让用户的HTTPS请求到达我们的web服务器。一种方法是攻击路由,将用户的HTTPS请求路由到我们的web服务器。另一种方法是攻击DNS,当受害者的机器试图找到目标网络服务器的IP地址时,它会得到我们的网络服务器的IP地址。在此任务中,我们使用“攻击”DNS。我们只需修改受害者机器的/etc/hosts文件,以模拟DNS缓存设置攻击的结果,而不是启动实际的DNS缓存中毒攻击。
Step3: Browse the target website 。一切都设置好了,现在访问目标真实的网站。
可以看到,我们访问到的是kali攻击机的默认目录。
访问https服务的时候,由于kali攻击机的证书不被信任,所以会有安全警告
Task6: Launching a Man-In-The-Middle Attack with a Compromised CA
设计一个实验来证明攻击者可以在任何HTTPS网站上成功发起MITM攻击。可以使用在Task 5中创建的相同设置,但是这一次,需要演示MITM攻击是成功的。即,当受害者试图访问一个网站而进入MITM攻击者的假网站时,浏览器不会引起任何怀疑。