SQLCipher之攻与防

在移动端,不管是iOS还是Android,开发人员用的最多的本地数据库非SQlite莫属了。SQLite是一个轻量的、跨平台的、开源的数据库引擎,它的在读写效率、消耗总量、延迟时间和整体简单性上具有的优越性,使其成为移动平台数据库的最佳解决方案。

但是,用SQLite保存一些不是很敏感的信息还可以接受,存储敏感信息就值得商榷了,免费版的SQLite中的信息是明文存放的,你甚至直接用文本编辑器打开都可以看到敏感内容,比如下面这个:

其实SQLite是提供了加密功能的,即SQLite Encryption Extension (SEE),但是,要收费!还不便宜,2000刀。码农们穷啊,于是大家寻找免费的解决方案,最终SQLCipher成了比较理想的选择,因为它免费、开源,而其它家的SQLiteEncrypt、SQLiteCrypt等还是要收费。

SQLCipher也有收费版本,但收费版本只是在集成、依赖等易用性方面有优势,功能和免费差不多,因此免费版的SQLCipher成了Coder们的选择对象。

SQLCipher采用的是数据库文件整体加密的策略,使用256-bit AES加密,从算法角度来看是相当强悍了。于是,加密后的文件看起来及时这样了:

完全是天书嘛,ok,可以洗洗睡了。但真的就安全了吗?呵呵。

001 谋攻篇

密码学中有一句比较经典的话:一切秘密寓于密钥之中。只要我们拿到了密钥,剩下的问题都不是问题了。下面我们就来分析一下SQLCipher的密钥和加密过程。 根据官方的描述,SQLCipher是整体加密方案:

Transparent – An application doesn’t require any special knowledge of the underlying database security. Applications use the standard SQLite API to manipulate tables using SQL. Behind the scenes the library silently manages the security.

On-the-fly – SQLCipher encrypts and decrypts in chunks called pages, as needed, so it doesn’t operate on the database all at one time. This means SQLCipher starts up and closes down quickly performs very well even with very large databases works with SQLite indexing (i.e. retrieving a single record using an indexed search can incur as little as 5% overhead above a standard SQLite database)

它并不是对表或者列进行加密,也就是说他的数据库密钥只有一个,拿下这一个密钥就成。

SQLCipher在iOS上是这样用的:

1)在项目中加入sqlite3.h和sqlite3.m;

2)使用下面代码连接数据库:

其中的key就是我们需要的密钥!然后通过sqlite3_key函数将该key与数据库关联起来,接下来就可以执行sql语句操作了。程序员肯定觉得好用啊,就增加了两行语句就完成了加密功能,直接拷贝官方的代码到自己的工程中,把“StrongPassword”换成自己的密钥就成。真实容易啊,那么我攻击也很easy啦。

一般来说,对付这种程度的加密,只需要使用静态分析即可。对于iOS程序,将程序拖到ida中,找到sqlite3_key函数相关引用地址,顺藤摸瓜,基本就搞定了。下面就是某应用中定位该函数在setKey方法中,该方法是在它的数据open方法中调用的,可以看到已经明文硬编码了数据库的密码(图中抹红部分)。

拿到密码后有个偷懒的方法可以直接打开加密数据库:使用SQLiteManager,它支持SQLCipher加密的数据库,会提示输入数据库密码,不需要自己写程序了,而且浏览数据也很方便。

对于Android版的程序,如果没加壳的话,也是很好分析的。Android调用SQLCipher使用下面的方式:

openOrCreateDatabase方法的第二个参数就是密钥了。在jeb反编译出来的代码中寻找相关的方法就可以摸到相应的数据库密钥。

到这儿程序员可能要想了,我不硬编码看你咋整,我在代码中经过加减乘除、异或后在算出key,或者更狠一点用用户口令等进行动态解密变换,密钥就不会在程序中出现了。

但攻击者还有n多招数还没上场了,比如动态调试,在输入key的方法入口打断点,对key的明文进行拦截。 还有就是hook技术,对于Android上的应用,我们可以使用CydiaSubstrate,使用MS.hookClassLoad 方法将openOrCreateDatabase进行hook处理:

public class Main {

static void hookCryptoKey() {

MS.hookClassLoad("net.sqlcipher.database.SQLiteDatabase",

new MS.ClassLoadHook() {

public void classLoaded(Class arg0) {

Log.d("MyHook", "##### Class Loaded ");

Method openOrCreateDatabase;

try {

openOrCreateDatabase = arg0.getMethod(

"openOrCreateDatabase",

new Class[] { File.class, String.class, SQLiteDatabase.CursorFactory.class });

} catch (NoSuchMethodException e) {

openOrCreateDatabase = null;

Log.d("MyHook",

"##### Unable to find method ");

}

if (openOrCreateDatabase != null) {

Log.d("MyHook", "##### Found method ");

try {

final MS.MethodPointer old = new MS.MethodPointer();

MS.hookMethod(arg0,

openOrCreateDatabase,

new MS.MethodHook() {

public Object invoked(Object arg0,

Object... args)

throws Throwable {

Log.d("MyHook", "##### Error: " + Thread.currentThread().getStackTrace());

Log.d("MyHook",

"###### Method hooked, stealing key: " + args[1]);

return old.invoke(arg0, args);

}

}, old);

} catch (Exception e) {

System.out

.println("#### Unable to find class ");

}

}

}

});

}

static void initialize() {

hookCryptoKey();

}

}

这段代码可以将openOrCreateDatabase方法钩住并将第二个参数key在日志中打印出来,无视你前期经过了多少隐藏、变换。至于Substrate的用法这里就不细讲了,各位看官可以参考网上的资料。当然,你也可以尝试其它hook框架,如Xposed。

程序员可能不服气,我还可以上加壳,在iOS端我也可以上混淆、lua动态网上加载等手段啊?不过这貌似超出了SQLCipher攻防的地盘了,是程序本地保护的大范畴,有机会再研究。

002 防

写到这儿,其实对本地数据库加密是感到沮丧的,这完全就是把门锁和钥匙放在一起的做法嘛,不管你在本地上任何软的手段(硬件另说,如果你的密钥、算法都放在硬件中,比如USBKey中,安全性应该是有本质上的提升),不管是简单变换还是混淆、加壳、反调试、反hook,都难保不被攻击者破解掉,不过是或多或少延缓找到钥匙的时间罢了。

因此,建议除了以下情况,不要使用SQLCipher之类的本地数据库加密:

非敏感数据,爱咋用咋用

用户自己的数据,可以采用用户口令、指纹等方式直接或间接保护,因为这种情况下key其实是随用户走的,可以做到key和算法、数据的分离

其它情况推荐数据放在APP的服务端,将客户端做瘦,将安全的防护重点放在通信和服务端的防护上。

时间: 2024-10-28 23:33:58

SQLCipher之攻与防的相关文章

智能家居网络安全攻与防

以下均内容均为博主原创.如转载,请注明出处.谢谢! 背景 物联网将会成为继互联网之后的下一个暴发点,目前以有不少公司已进入该领域. 智能家居作为物联网中最具有潜力的领域,网络安全是必须引起重视的课题.在互联网领域中,用户去安全性的敏感度并不是那个高.但是在智能家居领域中,如果系统被黑客攻击:半夜房门自动打开.无故解除安防系统.灯不亮等严重威胁到了用户的财产人身安全. 所以,智能家居想发展,安全性是决不可忽视的关键要素. 网络通信安全 任何信息在网络上传播能是能被第三者监听的.一个局域网就像是一间

高屋建瓴之WebMail攻与防

0x01:前言 随着互联网的快速发展,我们的生活与互联网的联系愈加的紧密.各种快捷方便的信息化通信工具渐渐取代了传统的通信方式.微博.QQ.MSN.微信.陌陌, …这样的社交软件和平台已经成为了我们生活必不可少的通讯和交友平台. 但是像上述的这些软件及平台都有一个共同的特征,那就是即时性.即时性的通信虽然有其独特的优点所在但是在企业级方面的安全性却得不到全方面的保障:电子邮件却恰恰相反,虽然即时通讯的能力不强,但是在企业级的安全性方面相对于即时通信还是略占优势的.根据一则报道显示: “有52%的

图片盗链的攻与防

前言: 之前在整理nginx资料的时候, 里面谈到过防盗链的配置. 当时觉得有些新鲜(还是自己孤陋寡闻了), 毕竟很少接触这个概念或者说是名词. 大致的意思时, 防止他人的网站引用你的图片, 进而消耗你网络带宽资源的一种措施. 本文将讲述防盗链的原理, nginx如何配置防盗链, 以及如何反防盗链的一些思路. 笔者这是简单谈谈, 权当抛砖引玉. 科普: 他人网站未经你的允许, 引用你网站的资源链接(图片/文档). 不仅消耗你服务器的网络带宽, 甚至侵害你的利益, 间接盗取你的网站流量, 所以危害

攻与防的较量—信息化安全提升的源动力

信息化安全的提升,某种程度上,依赖于攻击与防护对抗的碰撞力度.攻击愈烈,防守意识愈能提升,安全防护的技术水平和能力愈加速发展:而防守越强,同时也刺激攻击手段不断"创新"与"求变". 本次社保行业信息泄露事件的集中报道,就是信息化安全攻与防较量的一个典型代表. 1.社保数据遭受泄露事件曝光绝不"纯属偶然": 7天连锁酒店的600万会员信息泄密: CSDN 1000多万客户信息被窃取: 12306网站被攻破,上百万人的信息泄露: "房叔房姐

DDos攻与防

DDos(Distributed Denial of Service),分布式拒绝服务,在游戏.在线业务等方面常会发现这样的攻击,一般是竞争对手所为.那DDOS攻击的方式有哪些呢? 1流量攻击(四层) 主要是针对网络带宽的攻击,即大量攻击包导致网络带宽被阻塞,合法网络包被虚假的攻击包淹没而无法到达主机. 1.1 SYN/ACK Flood攻击 这个是很古老的攻击方法了,不过前期还是挺凑效的,主要是通过向受害主机发送大量伪造源IP和源端口的SYN或ACK 包,导致主机的缓存资源被耗尽或忙于发送回应

SQL注入攻与防之代码层防御SQL注入

[目录] 0x0 前言 0x1 领域驱动的安全 1.1 领域驱动的设计 1.2 领域驱动的安全示例 0x2 使用参数化查询 2.1 参数化查询 2.2 Java中的参数化语句 2.3 .NET(C#)中的参数化语句 2.4 PHP中的参数化语句 2.5 PL/SQL中的参数化语句 0X3 移动应用中的参数化语句 3.1 iOS应用程序中的参数化语句 3.2 Android应用程序中的参数化语句 3.3 HTML浏览器中存储的参数化语句 0x4 输入验证 4.1 白名单 4.2 黑名单 4.3 J

前端江湖之攻与防

前端安全的话题再次被提及,深航东航系统被攻破,乘客信息泄露并被利用,这类例子比比皆是.在前端江湖中,攻击与防守更像是一场漫无硝烟的战争,悄无声息却无时无刻都在进行. 前端常见漏洞包括XSS.CSRF及界面操作劫持,服务端如SQL注入等. 前端使用的传输协议是http,不经过加密直接传输的.HTML中有很多地方可以内嵌脚本.及前端的存储,cookie,web storage.这些在一定程度上带来了一些安全风险. 同域:两个站点同协议,同域名,同端口. 出于防范跨站脚本攻击的同源安全策略,浏览器禁止

PHP 采集大全 采集原理分析 禁用采集 各种采集方法详解 采集的攻于防 采集性能 应用协议分析

//py by http://my.oschina.net/cart 做了N年的PHP,采集了N家数据,由初学者菜鸟,到现在的熟手,采集天猫.淘宝.腾讯.京东.敦煌.Lightinthebox.大龙.zencart.magento.prestashop.opencart.xcart.踏踏....对采集颇有诸多的理解. 现在给大家分析下,如有误,请指出. 我能想到的常用采集方法: 1. file 支持应用层协议,返回的数据是以数组形式返回,需要开启allow_url_fopen. 长处:擅长处理本

服务器的攻与防(firewall 禁止指定Ip)

今天上午登陆服务器,随手看了一下sshd 的状态 systemctl status sshd 结果发现大量异常的ip登陆 然后就没敢耽误,赶紧把 防火墙打开,(因为这服务器是我自己测试用的,平时都没有开过防火墙) systemctl start firewalld 将这个 陌生ip "58.218.92.32" 禁掉 firewall-cmd --permanent --add-rich-rule="rule family="ipv4" source ad