# Android sqlite load_extension漏洞解析

Author: 乌云历史资料库 (@wooyun_archive)
Published: 2015-09-25T06:54:00Z
Canonical: https://wepostx.com/topics/1074

> 乌云历史资料归档
>
> **原始作者：** 路人甲
> **原始编号：** superkieran-wooyundrops:795
> **原始发布时间：** 2015-09-25 14:54
> **声明：内容仅用于技术研究和个人使用，版权归 wooyun.org。**

---

# 0x01 sqlite load_extension

SQLite从3.3.6版本（http://www.sqlite.org/cgi/src/artifact/71405a8f9fedc0c2）开始提供了支持扩展的能力，通过sqlite_load_extension API（或者load_extensionSQL语句），开发者可以在不改动SQLite源码的情况下，通过动态加载的库（so/dll/dylib）来扩展SQLite的能力。

![原文图片](/media/2016/06/cf0b7f3d1d309d13ed115d4436ccffb2)

便利的功能总是最先被黑客利用来实施攻击。借助SQLite动态加载的这个特性，我们仅需要在可以预测的存储路径中预先放置一个覆盖SQLite扩展规范的动态库（Android平台的so库），然后通过SQL注入漏洞调用load_extension，就可以很轻松的激活这个库中的代码，直接形成了远程代码执行漏洞。国外黑客早就提出使用load_extension和sql注入漏洞来进行远程代码执行攻击的方法，如下图。

![原文图片](/media/2016/06/ae0d49a73198e31f9f669426387c29b9)

也许是SQLite官方也意识到了load_extension API的能力过于强大，在放出load_extension功能后仅20天，就在代码中（http://www.sqlite.org/cgi/src/info/4692319ccf28b0eb）将load_extension的功能设置为默认关闭，需要在代码中通过sqlite3_enable_load_extensionAPI显式打开后方可使用，而此API无法在SQL语句中调用，断绝了利用SQL注入打开的可能性。

![原文图片](/media/2016/06/4f70f41810c346d19b4d0500d6707cf5)

# 0x02 Android平台下的sqlite load_extension支持

出于功能和优化的原因，Google从 Android 4.1.2开始通过预编译宏SQLITE_OMIT_LOAD_EXTENSION，从代码上直接移除了SQLite动态加载扩展的能力,如下图。

![原文图片](/media/2016/06/bb00eff441db5ff81ffb7552373ed481)

可以通过adb shell来判断Android系统是不是默认支持load_extension，下图为Android4.0.3下sqlite3的.help命令：

![原文图片](/media/2016/06/ce34ad70afc75623c62cd19d8a13ee66)

可以看出支持load extension，而Android4.1.2上则没有该选项。

# 0x03 Android平台下的sqlite extension模块编译

sqlite extension必须包含sqlite3ext.h头文件，实现一个sqlite3_extension_init 入口。下图为一个sqlite extension的基本框架：

![原文图片](/media/2016/06/893ee2c260e38a2325e653d2df6985a6)

接着是Android.mk文件，如下图：

![原文图片](/media/2016/06/f7de230791a848b213290f64c4355326)

我们实现一个加载时打印log输出的一个sqlie extension：

![原文图片](/media/2016/06/2e2f6990900f3a160b41a15ef34969d0)

# 0x04 Android平台下sqlite load_extension实战

由于sqlite是未加密的数据库，会导致数据泄露的风险，Android App都开始使用第三方透明加密数据库组件，比如sqlcipher。由于sqlcipher编译时没移除load extension，如图，导致使用它的App存在被远程代码执行攻击的风险。

![原文图片](/media/2016/06/b940a7cff8af4309114e721c8b1422c3)

![原文图片](/media/2016/06/88624cc4145fa4abf6d773f8977179ab)

下面我们将通过一个简单的demo来展示sql注入配合load_extension的漏洞利用。
首先，实现一个使用sqlcipher的Android程序，下载sqlcipher包，将库文件导入项目，如下图：

![原文图片](/media/2016/06/dc8f0da326d3493a9612e14297e9006b)

将导入包换成sqlcipher的：

![原文图片](/media/2016/06/01675b8af558d73c0624ed5d98b36c4c)

加载sqlcihper的库文件，并且打开数据库时提供密钥：

![原文图片](/media/2016/06/14d1d6a36d7178294e8bae7e98e1f6a7)

编译的时候如果出错，则将jar包引入并导出，如下图：

![原文图片](/media/2016/06/3d7498b41368964fb41b7da624bc158a)

![原文图片](/media/2016/06/8903fcdabe6f7728481726c14cf43225)

实现一个存在sql注入的数据库查询语句，外部可控，如下图：

![原文图片](/media/2016/06/fa32bac828bcccb975d3aff6a53f230a)

该函数接收一个外部可控的参数，并将数据库查询语句进行拼接，导致可被外部植入恶意代码进行代码执行攻击，如下图：

![原文图片](/media/2016/06/566a433de9708ac571a1bd9a171c3cec)

执行之后，可以看到so加载成功，如下图：

![原文图片](/media/2016/06/6b9a2fd12ae1c718dbeb0bc0f3e0e1f1)

# 0x05 Android平台下sqlite load_extension攻防

攻击场景：存在漏洞的app可以接收文件，黑客可将文件通过目录遍历漏洞放到app私有目录下，再通过发消息触发sql注入语句，完美的远程代码执行攻击。
漏洞防御：

- 由于sqlcipher的扩展默认是开启的，如果需要sqlcipher，编译sqlcipher的时候通过SQLITE_OMIT_LOAD_EXTENSION宏来关闭sqlcipher的扩展功能。

- 进行数据库操作时，禁止将查询语句进行拼接，防止存在sql注入漏洞。

## Replies
