互联网通信安全之终端数据保护_数据库



“xx 侦探,技术高超,轻松获取对方位置或通讯内容。”关注【融云全球互联网通信云】了解更多

你或许也在网上遇到过这类所谓“私家侦探”的违规小广告,抑或是在法制节目中看到过类似“假定位真诈骗”的普法故事。

这类事件频发,佐证着有不少人想通过非法途径窥探他人隐私达到不法目的事实。这就是在我们把生活、工作的方方面面转移到线上的过程中,每天都要面对的通信安全挑战。

在通信安全这个议题之下,我们此前已经与大家分享了​​链路安全​​​、​​WebRTC 传输安全机制​​​、​​端到端加密技术​​等主题。


随着 SSL/TLS 的普及和各种安全产品的应用,黑客直接通过链路或入侵服务器来获取用户的通讯消息已经是几乎不可能的事情了。

这种情况下,通过植入木马的方式来获取通讯内容就变成了他们行不法勾当的重要途径。

如何防止手机等终端被木马植入?在用户层面,就需要大家具备良好的安全意识,比如安装杀毒软件、不点击陌生链接、不越狱或 Root 系统等等。

而今天我们将要探讨的议题是,假设我们的设备已经被植入了木马,那如何从软件层面做最后的防护,以保证用户通信消息的安全性和私密性

需要注意的是,当系统被植入木马后,一般不会更改软件本体,而是通过本地网络代理或读取关键位置的文件来获取想要监听的内容。而本地网络代理我们在​​链路安全​​一文中已经分享过,可以通过开启 SSL/TLS 的方式防止信息被监听。


数据存储安全


即时通信系统一般都存在着终端消息存储的特性,以方便用户离线查看已经接收过的消息。而这些消息一般都会使用文件级数据库来进行存储。

使用数据库的优势在于,方便对数据进行增删改查,而且也不会出现太大的性能问题。

其中 SQLite 因其小巧、开源和高性能成为了众多终端软件数据存储的首选方案。

那么在 SQLite 中如何做消息的加密存储呢?


方案一  对要存储的消息进行加密

对要插入到数据库中的消息先进行 AES 加密,加密完成后再插入到数据中,使用的时候先从数据库中取出,然后再进行解密就可以正常使用了。

这种方法优势明显,但是劣势也非常致命——如果需要对消息进行模糊查询,那该消息就不能加密,这样一来产品需要安全需求就形成了矛盾体。所以,我们一般不会选取这样的方式


方案二  对数据进行加密

SQLite 3 的开源发布版没有提供加密功能,但是其导出头文件中有 sqlite3_key  和 sqlite3_rekey 的定义,可以用来实现数据库加密。

有加密实现的版本还需要在预编译中定义预处理宏 SQLITE_HAS_CODEC 才能开启这几个函数的功能。

sqlite3_key

sqlite3_key 是输入密钥,如果数据库已加密必须先执行此函数并输入正确密钥才能进行操作;如果数据库没有加密,执行此函数后进行数据库操作反而会出现“此数据库已加密或不是一个数据库文件”的错误。

// db 是指定数据库,pKey 是密钥,nKey 是密钥长度。
int sqlite3_key(sqlite3 *db, const void *pKey, int nKey)
// 例:
sqlite3_key(db, "abc", 3);

sqlite3_rekey

sqlite3_rekey 是变更密钥或给没有加密的数据库添加密钥或清空密钥,变更密钥或清空密钥前必须先正确执行 sqlite3_key。

在正确执行 sqlite3_rekey 之后在 sqlite3_close 关闭数据库之前可以正常操作数据库,不需要再执行  sqlite3_key。

// 参数同上 
int sqlite3_rekey(sqlite3 *db, const void *pKey, int nKey)

添加数据库密码:如果想要添加密码,可以在创建数据库文件之后,关闭数据库文件之前的任何时刻调用 sqlite3_key 函数即可。

读取数据库数据:打开数据文件后,调用 sqlite3_key 函数,即可。(如果数据库没有加密,执行此函数后进行数据库操作反而会出现“此数据库已加密或不是一个数据库文件”的错误;经测试,只能在新建数据库时设置密码!

修改数据库密码: 首先你需要使用当前的密码正确打开数据库,之后便可调用 sqlite3_rekey(db,"112233",6) 来更改数据库密码。

除了直接使用 SQLite 3 中的 sqlite3_key 外,还有很多其他语言的 SQLite 开源框架也提供了数据库加密能力,如:SQLCipher、wxSQLite3 等。

目前 SQLite 3 支持这两个接口的版本到 3.31.1, 其后版本不再支持,建议采用一些开源库。


数据库密码保护


数据库的密码应避免直接在代码或配置文件中保存。因为一旦程序被反编译后其保密性也就不存在了,所以数据库的密码也需要被保护起来

首先,最安全的做法是客户端完全不存储数据库的密码,每次打开终端软件时都必须保证网络正常,且可以完整地经过服务器的用户鉴权,才能返回数据库密码。

而服务器需要为每个用户的每个设备生成不同的密码,这样就可以有效防止以下两种情况:


①一个终端上有多个用户的场景下,一个密码泄露导致整个终端被破解;

②一个用户密码被破解后可以查看这个用户其他设备上的数据。

互联网通信安全之终端数据保护_数据_02

(数据库密码保存流程)

通过以上流程图我们可以简单了解数据库密码的保存方式。但该方法存在一个问题,即:如果客户端有离线打开需求,这种方案是无法满足的。

离线对数据库操作的需求存在安全隐患,都是可以被破解的,这就是安全便捷的冲突。


但是我们可以通过设置复杂规则使破解难度增大,在设计规则时我们至少保证遵守以下几条原则:

① 每个设备上的每个用户的密码不一样。

② 每次得到数据密码结果必须一致。

③ 密码结果不在终端存储。

④ 终端生成密码的代码必须进行安全加固。


例如:我们通过将设备标识与用户标识进行 Hash 得到数据库密码。


现在,信息安全问题日益严峻,在实际生活中,我们无法保证所使用的终端软件都采用加密数据存储方式。

因此,保持一个良好的使用习惯,不点击陌生链接,不安装非正规渠道的应用,并在终端上安装杀毒软件和其他的安全产品,才能最大限度保障我们信息及隐私不被不法之徒获得和利用。