Introduction
本文介绍华南理工大学软件学院17级《数据库开发实训》的一个可选课题:CryptDB漏洞利用。
任务目标:
- 追踪CryptDB漏洞相关论文
- 详细介绍CryptDB漏洞与攻击方案,并演示之
环境要求:
- Ubuntu 12.04 LTS(可以从这里下载,如果使用华工校园网,可以从这里下载)。 笔者曾经在Ubuntu 19.04尝试过,并不能装
- 未在其他linux发行版下做过测试,debian系linux理论上应该都可行
- 攻击方案编程环境不作限制
CryptDB Installation
安装ubuntu 12.04 LTS映像,安装完成后进行软件源的设置。
1 sudo gedit /etc/apt/sources.list
删除(也可以备份)所有内容后粘贴以下内容,若不稳定可以自己找:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#网易 deb http://mirrors.163.com/ubuntu/ precise main universe restricted multiverse deb-src http://mirrors.163.com/ubuntu/ precise main universe restricted multiverse deb http://mirrors.163.com/ubuntu/ precise-security universe main multiverse restricted deb-src http://mirrors.163.com/ubuntu/ precise-security universe main multiverse restricted deb http://mirrors.163.com/ubuntu/ precise-updates universe main multiverse restricted deb http://mirrors.163.com/ubuntu/ precise-proposed universe main multiverse restricted deb-src http://mirrors.163.com/ubuntu/ precise-proposed universe main multiverse restricted deb http://mirrors.163.com/ubuntu/ precise-backports universe main multiverse restricted deb-src http://mirrors.163.com/ubuntu/ precise-backports universe main multiverse restricted deb-src http://mirrors.163.com/ubuntu/ precise-updates universe main multiverse restricted #中国科技大学 deb http://debian.ustc.edu.cn/ubuntu/ precise main restricted universe multiverse deb http://debian.ustc.edu.cn/ubuntu/ precise-backports restricted universe multiverse deb http://debian.ustc.edu.cn/ubuntu/ precise-proposed main restricted universe multiverse deb http://debian.ustc.edu.cn/ubuntu/ precise-security main restricted universe multiverse deb http://debian.ustc.edu.cn/ubuntu/ precise-updates main restricted universe multiverse deb-src http://debian.ustc.edu.cn/ubuntu/ precise main restricted universe multiverse deb-src http://debian.ustc.edu.cn/ubuntu/ precise-backports main restricted universe multiverse deb-src http://debian.ustc.edu.cn/ubuntu/ precise-proposed main restricted universe multiverse deb-src http://debian.ustc.edu.cn/ubuntu/ precise-security main restricted universe multiverse deb-src http://debian.ustc.edu.cn/ubuntu/ precise-updates main restricted universe multiverse
若安装中文输入法,可以看这里
安装必要的软件包,并在项目的git页面clone代码。为了方便,这里我们把代码clone到~下:
1 sudo apt-get update 2 sudo apt-get install git ruby lua5.1 3 cd ~ 4 git clone https://github.com/CryptDB/cryptdb.git
利用脚本安装CryptDB(脚本会自动安装一切依赖软件,包括mysql):
1 cd cryptdb 2 sudo ./scripts/install.rb ~/cryptdb
在安装mysql时会提示设置root登录口令,最好设置为"letmein"。因为之后启动代理服务时默认口令是letmein(也可以自行修改)。
执行完毕后要进行环境变量的设置:
1 sudo su (必需要有这句话!) 2 sudo vim ~/.bashrc 3 # 在文件最后一行加上下面这句,your_account_name替换为你的账户名 4 export EDBDIR=/home/your_account_name/cryptdb
接下来要启动mysql-proxy服务:
1 sudo su (如果上面获取过root权限则不需要) 2 cd /home/your_account_name/cryptdb/bins/proxy-bin/bin/ 3 ./mysql-proxy --plugins=proxy \ 4 --event-threads=4 \ 5 --max-open-files=1024 \ 6 --proxy-lua-script=$EDBDIR/mysqlproxy/wrapper.lua \ 7 --proxy-address=127.0.0.1:3307 \ 8 --proxy-backend-addresses=127.0.0.1:3306
在$EDBDIR/mysqlproxy/wrapper.lua中存放着数据库代理的相关设置,上文提到的letmein口令被明文存放其中,可根据实际情况修改。
至此,CryptDB安装工作结束。接下来进行CryptDB的功能测试。
启动新的terminal,连接到mysql:
1 mysql -u root -pletmein -h 127.0.0.1 -P 3307
再启动一个新的terminal,连接到mysql:
1 mysql -u root -pletmein -h 127.0.0.1 -P 3306
其中,使用3307端口的进程模拟客户(或应用)所在进程,使用3306端口的进程模拟数据库管理员所在进程。
接下来进行CryptDB功能测试。在端口为3307的terminal中输入以下命令(不要退出mysql,之后的3306端口terminal同理):
1 create database cryptdbtest; 2 use cryptdbtest; 3 create table user(id int, name varchar(10)); 4 insert into user values(2,"tom");
结果如下图所示:
然后通过3307端口查看数据库表数据:
1 select * from user;
可以看到3307通过mysql-proxy代理是可以看到明文数据的,即使表名被加密过,但使用明文的表名依然能查询得到明文的数据。
通过3306端口查看数据库表数据:
通过3306端口可以看到未加密的数据库名称,但表名和数据全部被加密,也无法使用明文表名。
测试到此结束。
CryptDB Principle Analysis
我们首先了解一下CryptDB的结构。
CryptDB包含两部分:一个数据库代理和一个未经修改的DBMS。CryptDB使用用户定义的函数(UDF)在DBMS中进行加密操作。矩形和圆角矩形代表过程和数据,阴影代表CryptDB添加的组件。虚线隔离了用户计算机、应用程序服务器以及运行CryptDB数据库代理和DBMS的服务器。
CryptDB被设计以应对两种威胁(见图):
- Thread 1:具有高权限的管理员在数据库数据未经加密时,可能试图获得或泄露数据库数据
- Thread 2:入侵者利用软件漏洞攻击软件及访问数据库数据
第一类威胁危险性没有第二类威胁大。攻击者一般只获取数据信息,但没有能力去修改数据。
对于第一类威胁,CryptDB的做法是:利用数据库代理(在CryptDB中,称为mysql-proxy)截取所有传入的SQL语句并对语句中的关键字段进行加密,同时确保符合SQL语句的语法要求,然后再将加密后的SQL请求发送给mysql-server;mysql-server负责处理SQL语句,并返回加密的处理结果给mysql-proxy;最后返回的处理结果在mysql-proxy处解密,返回给客户端。CryptDB的存在,使得数据库管理员在没有解密密钥的情况下,无法获知加密之后的数据。CryptDB的效率很高,因为它主要使用的是对称密钥加密,避免完全全同态加密。
对于第二类威胁,CryptDB的保密制度指定了链式加密的规则:将加密密钥和用户密码捆绑。而且CryptDB使用不同的密钥加密不同的数据项。当解密数据库中特定的某个数据项时,需要相关用户密码中所构造的一连串密钥。这使得数据项只有使用相应的用户的密码登录才可以进行解密。这种做法使得即使服务器被攻破,整个系统被入侵者控制的情况下,只要用户没有登录,攻击者也无法解密用户的数据。
CryptDB还采用了一种基于语句的加密方式:洋葱模型。这种模型使得每个洋葱之间存储着多种加密方式加密后的数据,避免开销大的重加密操作。
在CryptDB中处理查询的步骤为:
- application端向server端发送查询,中途被mysql-proxy拦下并改写查询语句。查询语句涉及的表或列的名字会被模糊处理,查询语句中的常量使用master-key加密处理。
- 在执行查询语句之前,mysql-proxy会检查DBMS server是否应获得密钥来调整加密层。如果可以,一条更新查询语句会在DBMS server端调用一个user-defined function来调整加密层。
- mysql-proxy将加密后的查询语句发给DBMS server,DBMS server执行查询语句,并将加密的查询结果发给mysql-proxy
- mysql-proxy解密从DBMS server发来的数据,并发给application端。
CryptDB采用的加密策略很多:
- Random(RND)策略。这种随机加密数据,加密后的数据几乎无法运算。实现方法有AES等。如果需要对被加密后的数据进行计算,需要调用一类UDF来解密数据。
- Deterministic(DET)策略。在该策略中,相同明文的数据加密后的密文也是相同的。虽然可以很方便地对密文进行操作,但这一点有可能会泄露数据库信息。
- Order-preserving encryption(OPE)策略。该策略允许数据的顺序查找。对于满足偏序性质的数据x和y,当x<y时满足OPE(x)<OPE(y)。因为该策略会暴露数据顺序关系,所以安全性比DET弱。
- Homomorphic encryption(HOM)策略。该策略满足某些数学运算,比如f(x)+f(y)=f(x+y)等。
- Join策略。该策略满足join运算。
- Word search策略。该策略满足对密文进行像like语句之类的操作。
但是,使用多种加密方式会一定程度上暴露关键信息,使得安全性降低。CryptDB采用了adjustable-query-based encryption的可调整的基于查询的方式,根据查询来确定对数据加密的方式。
以上的操作需要提前知道用户将要执行的所有操作才能完全被满足,所以不具有实用价值,但洋葱模型可以解决这个问题。我们把数据经过多层加密,包裹成一个洋葱,越外层的加密越安全,能提供的功能越少,越内层的加密越不安全,但能提供的功能越多。当当前层所拥有的密文无法满足操作需求时,通过一系列算法把洋葱剥开,提供相应的密文进行操作。而且这个过程实现记忆化操作来提高效率。
在第二类威胁中,当mysql-proxy和application端同时受到攻击时,需要保证泄露的数据尽量少。CryptDB向共享数据提供访问控制策略,通过ENC_FOR以及SPEAK_FOR语句提供注释功能,实现了限制共享数据的访问权限。CryptDB定义了两类主体:external principal和internal principal。对于external principal,需要提供密码给proxy才能得到相应principal的权限,而internal principal需要在系统中对其授权才能获得权限。
CryptDB使用的是自定义的principal而不是现有DBMS的principal,因其提供的定义细粒度不够,不足以满足开发需求。而且CryptDB在principal之间需要实现显式特权授予,现有的DBMS也无法满足此要求。当external主体登录系统后,系统会把该用户名以及密码放在一个表中,密码用于解密相应主体的key以读取相关数据。DBMS server端不会得到这个表,并且proxy拦截一切对该表的访问。即使proxy受到攻击,表的内容泄露,但由于用户未登录,用户密码也不会出现在其中,这样就保护了未登录用户的数据安全。
CryptDB Attack Program
Akin[1]给出了一个属于第二类威胁的攻击方案。他认为CryptDB的设计者没有考虑到数据的完整性和真实性,并把CryptDB保护的数据库分为两类:单用户数据库以及多用户数据库。攻击方案利用CryptDB缺少的数据和查询完整性保护措施来窃取其他用户的私有数据,甚至提高在web应用程序上的权限。该攻击方案在一个开源的公告板软件上运行,站点后端使用CryptDB。该攻击方案不以应用程序和代理服务器为目标,不从代理服务器窃取master-key,不以个人pc为目标窃取用户密码。攻击方案由在线攻击者启动,在线攻击者可以访问数据库服务器,也可以作为用户通过应用程序服务器来访问web应用。当mDBA(恶意的数据库管理员)管理数据库,并且作为web应用程序的注册用户时即可启动攻击;当一个无知的用户泄露信息给mDBA时也可以启动攻击。
攻击方案基于这样的假设:代理服务器和应用程序服务器在同一物理服务器上运行(拆分并不影响);并非所有洋葱都在RND层下,所以数据库可以执行查询操作。
考虑一个在phpBB上运行的在线论坛。站点管理员通过将启用CryptDB的数据库移动到廉价的云服务器来降低运营成本。CryptDB的代理服务器和应用程序服务器都运行在论坛管理员严格保护的物理服务器上。要获得对应用程序服务器的访问权限,mDBA首先以普通用户身份注册到网站。mDBA的第一个目标是识别phpbb_users表中的username_clean字段,但此时表名被加密。为了获得正确的表,mDBA启用MySQL的查询日志来验证表名。 完成这些步骤后,mDBA将登录到网站。 为了验证用户登录尝试,phpBB执行SQL查询,例如:
select user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts from phpbb_users where username_clean='mDBAs_FAKE_USER';
显然,代理服务器必须事先显示username_clean的洋葱的RND层才能执行查询操作。mDBA会事先在事件日志中检查读取查询,通过检查数据库日志的账户登录时间,mDBA可以识别出查询语句并得到其创建的账户用户名的加密版本,从而跟踪其创建的账户在数据库中的所有操作。而且,在当前版本的CryptDB中,创建表的时候,列名称顺序被保留了下来,由于phpBB和CryptDB的代码是开源的,这使得被加密的列名称和原来的列名称可以被一一匹配。此时,mDBA可以篡改存储在服务器上的CryptDB数据库里的表,并在mDBA创建的用户的帮助下,通过不同途经来危及CryptDB的安全:
- 找到特定目标。在phpBB中,用户可以在论坛上看到其他用户的用户名。对于特定目标,攻击者尝试使用目标名称登录几次,由于没有密码所以会失败。但在数据库中,攻击者会留意到对应的登录查询。通过这个查询,攻击者可以定位特定用户在phpbb_users表里的位置。
- 收集用户信息。mDBA把其他用户的加密字段复制到虚假账户的相应记录字段中,然后通过phpBB网站的账户信息页面来显示该虚假账户所包含的其他用户的信息。
- 账户劫持。mDBA可以复制其虚假账户的信息以覆盖其他用户的信息,比如账户密码等,然后登录其他用户的账号。这使得mDBA可以把虚假账户中的信息覆盖所有用户,然后登录特定用户并恢复其他用户的信息,以实现劫持特定用户的账号。
- 权限升级。典型的phpBB中,user表的第二行属于administrator管理。mDBA可以使用此信息将其虚假账户的权限级别提升为管理员权限级别。攻击者一旦成为管理员,就可以通过调整previalges来访问受限区域。
问题在于,具有多种原理的CryptDB尚未公开。所以我们使用MySQL的样例数据库来验证攻击。在实际实现中,把表中的每一列设置为最高级别的洋葱,并且没有以明文形式记录任何列。显然,要实现登录查询,用户名必须位于DET层中。为了证明在JOIN操作下我们的攻击方案依然有效,我们往数据库中添加了一个密码表,而且写来一个简单的网页登陆系统来展示个人信息和工资。我们编写了一些MySQL脚本来交换列,而且执行该脚本两次后不会在表中留下痕迹,攻击者可以删除相关的日志。在mDBA登录到站点并在云服务器上表示识别的行之后,mDBA在别的用户对应的行运行该脚本。注意,用户名属于DET加密。执行脚本后,mDBA刷新其个人信息页来访问泄露的信息。当我们把注意力转向phpBB时,查询告诉我们在RND层用户表中必须被移除的列所username_clean,这用于执行带有以下字句的登录点查询:
...WHERE username_clean = '0x784EB1A'
CryptDB旨在确保数据库的机密性,但确保机密性并不足以建立安全的系统。mDBA可以通过删除、插入、复制或交换数据库中的数据来更改查询结果。为了防止这种类型的攻击,无论行是否加密,数据库系统都需要确保数据和查询的完整性以及查询相应的完整性。更进一步,还需要确保这些数据的真实性和新鲜度。要强调的是,对策会显著降低CryptDB的性能。Merkle提出可以将哈希安排到二叉树结构中,仅验证存储已签名的根,这种方法的一个延伸是Devanbu使用平衡和I/O高效的B+树。Hacigmsetaluu提出了一种使用哈希函数确保行完整性的方案,该方案使用存储桶来显示查询结果的完整性。Narasimha和Tsudik提出了数字签名聚合和链接以提供完整性和身份验证,他们的想法所基于哈希链接和签名,哈希链接包括维度上的顺序关系的任何维度中的直接前导行。Mykletun使用精简RSA签名方案,允许将签名聚合为单个签名者的一个签名。Boneh等人为聚合签名提出了多个签名者。
More Powerful Attack Program
Reference
[1] Akin, I. H., & Sunar, B. (2014). On the Difficulty of Securing Web Applications Using CryptDB. international conference on big data and cloud computing, 745-752.
[2] Popa, R. A., Redfield, C. M., Zeldovich, N., & Balakrishnan, H. (2011). CryptDB: protecting confidentiality with encrypted query processing. symposium on operating systems principles.
[3] Zeng, B. (2019). 《极简密码学》.