安卓应用安全指南 4.5.2 使用 SQLite 规则书
安卓应用安全指南 4.5.2 使用 SQLite 规则书
原书:Android Application Secure Design/Secure Coding Guidebook
译者:飞龙
协议:CC BY-NC-SA 4.0
使用 SQLite 时,遵循以下规则:
4.5.2.1 正确设置 DB 文件位置和访问权限(必需)
考虑到 DB 文件数据的保护,DB 文件位置和访问权限设置是需要一起考虑的非常重要的因素。 例如,即使正确设置了文件访问权,如果 DB 文件位于无法设置访问权的位置,则任何人可以访问 DB 文件,例如, SD 卡。 如果它位于应用目录中,如果访问权限设置不正确,它最终将允许意外访问。 以下是正确分配和访问权限设置的一些要点,以及实现它们的方法。 为了保护数据库文件(数据),对于位置和访问权限设置,需要执行以下两点。
1) 位置
位于可以由Context#getDatabasePath(String name)
获取的文件路径,或者在某些情况下,可以由Context#getFilesDir11
获取的目录。
2) 访问权限
设置为MODE_PRIVATE
(只能由创建文件的应用访问)模式。
通过执行以下2点,即可
创建其他应用无法访问的 DB 文件。 以下是执行它们的一些方法。
- 使用
SQLiteOpenHelper
- 使用
Context#openOrCreateDatabase
创建 DB 文件时,可以使用SQLiteDatabase#openOrCreateDatabase
。 但是,使用此方法时,可以在某些 Android 智能手机设备中创建可从其他应用读取的 DB 文件。 所以建议避免这种方法,并使用其他方法。 上述量种方法的每个特征如下 [11]
[11] 这两种方法都提供了(包)目录下的路径,只能由指定的应用读取和写入。
使用SQLiteOpenHelper
当使用SQLiteOpenHelper
时,开发人员不需要担心很多事情。 创建一个从SQLiteOpenHelper
派生的类,并为构造器的参数指定DB名称(用于文件名)[12],然后满足上述安全要求的 DB 文件会自动创建。
[12] (未在 Android 参考中记录)由于可以在
SQLiteOpenHelper
实现中,将完整文件路径指定为数据库名称,因此需要注意无意中指定不能控制访问权限的地方(路径)(例如 SD 卡)。
对于如何使用,请参阅“4.5.1.1 创建/操作数据库”的具体使用方法。
使用Context#openOrCreateDatabase
使用Context#openOrCreateDatabase
方法创建数据库时,文件访问权应由选项指定,在这种情况下,请明确指定MODE_PRIVATE
。
对于文件安排,数据库名称(用于文件名)可以像SQLiteOpenHelper
一样指定,文件将在满足上述安全要求的文件路径中自动创建。 但是,也可以指定完整路径,因此有必要注意指定 SD 卡时,即使指定MODE_PRIVATE
,其他应用也可以访问。
MainActivity.java(显式设定 DB 访问权的示例)
public void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);//Construct databasetry {//Create DB by setting MODE_PRIVATEdb = Context.openOrCreateDatabase("Sample.db", MODE_PRIVATE, null);} catch (SQLException e) {//In case failed to construct DB, log outputLog.e(this.getClass().toString(), getString(R.string.DATABASE_OPEN_ERROR_MESSAGE));return;}//Omit other initial process
}
访问权限有三种可能的设置:MODE_PRIVATE
,MODE_WORLD_READABLE
和MODE_WORLD_WRITEABLE
。 这些常量可以由或运算符一起指定。 但是,除API_PRIVATE
之外的所有设置,都将在 API 级别 17 和更高版本中被弃用,并且会在 API 级别 24 和更高版本中导致安全异常。 即使对于 API 级别 15 及更早版本的应用,通常最好不要使用这些标志 [13]。
[13]
MODE_WORLD_READABLE
和MODE_WORLD_WRITEABLE
的更多信息,以及其使用的注意事项,请参见“4.6.3.2 访问目录的权限设置”。
MODE_PRIVATE
只有创建者应用可以读写MODE_WORLD_READABLE
创建者应用可以读写,其他人只能读MODE_WORLD_WRITEABLE
创建者应用可以读写,其他人只能写
4.5.2.2 与其它应用共享 DB 数据时,将内容供应器用于访问控制(必需)
与其他应用共享 DB 数据的方法是,将 DB 文件创建为WORLD_READABLE
,WORLD_WRITEABLE
,以便其他应用直接访问。 但是,此方法不能限制访问或操作数据库的应用,因此数据可以由非预期的一方(应用)读或写。 因此,可以认为数据的机密性或一致性方面可能会出现一些问题,或者可能成为恶意软件的攻击目标。
如上所述,在 Android 中与其他应用共享数据库数据时,强烈建议使用内容供应器。 内容供应器存在一些优点,不仅从安全的角度来实现对 DB 的访问控制,而且从设计角度来看, DB 纲要结构可以隐藏到内容中。
4.5.2.3 在 DB 操作期间处理变量参数时,必需使用占位符(必需)
在防止 SQL 注入的意义上,将任意输入值并入 SQL 语句时,应使用占位符。 下面有两个方法用占位符执行 SQL。
- 使用
SQLiteDatabase#compileStatement()
,获取SQLiteStatement
,然后使用SQLiteStatement#bindString()
或bindLong()
等,将参数放置到占位符之后。 - 在
SQLiteDatabese
类上调用execSQL()
,insert()
,update()
,delete()
,query()
,rawQuery()
和replace()
时,使用具有占位符的 SQL 语句。
另外,通过使用SQLiteDatabase#compileStatement()
执行SELECT
命令时,存在“仅获取第一个元素作为SELECT
命令的结果”的限制,所以用法是有限的。
在任何一种方法中,提供给占位符的数据内容最好根据应用要求事先检查。 以下是每种方法的进一步解释。
使用SQLiteDatabase#compileStatement()
:
数据以下列步骤提供给占位符:
- 使用
SQLiteDatabase#compileStatement()
获取包含占位符的 SQL 语句,如SQLiteStatement
。 - 使用
bindLong()
和bindString()
方法为创建的SQLiteStatement
对象设置占位符。 - 通过
ExecSQLiteStatement
对象的execute()
方法执行 SQL。
DataInsertTask.java(占位符的用例):
//Adding data task
public class DataInsertTask extends AsyncTask<String, Void, Void> {private MainActivity mActivity;private SQLiteDatabase mSampleDB;public DataInsertTask(SQLiteDatabase db, MainActivity activity) {mSampleDB = db;mActivity = activity;}@Overrideprotected Void doInBackground(String... params) {String idno = params[0];String name = params[1];String info = params[2];//*** POINT 3 *** Validate the input value according the application requirements.if (!DataValidator.validateData(idno, name, info)) {return null;}// Adding data task//*** POINT 2 *** Use place holderString commandString = "INSERT INTO " + CommonData.TABLE_NAME + " (idno, name, info) VALUES (?, ?, ?)";SQLiteStatement sqlStmt = mSampleDB.compileStatement(commandString);sqlStmt.bindString(1, idno);sqlStmt.bindString(2, name);sqlStmt.bindString(3, info);try {sqlStmt.executeInsert();} catch (SQLException e) {Log.e(DataInsertTask.class.toString(), mActivity.getString(R.string.UPDATING_ERROR_MESSAGE));} finally {sqlStmt.close();}return null;}[...]
}
这是一种类型,它预先创建作为对象执行的 SQL 语句,并将参数分配给它。 执行的过程是固定的,所以没有发生 SQL 注入的可能。 另外,通过重用SQLiteStatement
对象可以提高流程效率。
使用SQLiteDatabase
提供的每个方法:
SQLiteDatabase
提供了两种类型的数据库操作方法。 一种是使用 SQL 语句,另一种是不使用 SQL 语句。 使用 SQL 语句的方法是SQLiteDatabase#execSQL()
/rawQuery()
,它以以下步骤执行。
1) 准备包含占位符的 SQL 语句。
2) 创建要分配给占位符的数据。
3) 传递 SQL 语句和数据作为参数,并为每个过程执行一个方法。
另一方面,SQLiteDatabase#insert()/update()/delete()/query()/replace()
是不使用 SQL 语句的方法。当使用它们时,数据应该按照以下步骤来准备。
1) 如果有数据要插入/更新到数据库,请注册到ContentValues
。
2) 传递ContentValues
作为参数,并为每个过程执行一个方法(例如,SQLiteDatabase#insert()
)
SQLiteDatabase#insert()
(每个过程的方法的用例):
private SQLiteDatabase mSampleDB;
private void addUserData(String idno, String name, String info) {//Validity check of the value(Type, range), escape processif (!validateInsertData(idno, name, info)) {//If failed to pass the validation, log outputLog.e(this.getClass().toString(), getString(R.string.VALIDATION_ERROR_MESSAGE));return;}//Prepare data to insertContentValues insertValues = new ContentValues();insertValues.put("idno", idno);insertValues.put("name", name);insertValues.put("info", info);//Execute Insertry {mSampleDb.insert("SampleTable", null, insertValues);} catch (SQLException e) {Log.e(this.getClass().toString(), getString(R.string.DB_INSERT_ERROR_MESSAGE));return;}
}
在这个例子中,SQL 命令不是直接写入,而是使用SQLiteDatabase
提供的插入方法。 SQL 命令没有直接使用,所以在这种方法中也没有 SQL 注入的可能。
安卓应用安全指南 4.5.2 使用 SQLite 规则书相关推荐
- 安卓应用安全指南 4.6.2 处理文件 规则书
安卓应用安全指南 4.6.2 处理文件 规则书 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY- ...
- 安卓应用安全指南 4.5.1 使用 SQLite 示例代码
安卓应用安全指南 4.5.1 使用 SQLite 示例代码 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议: ...
- 安卓应用安全指南 4.4.3 创建/使用服务高级话题
安卓应用安全指南 4.4.3 创建/使用服务高级话题 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC ...
- 安卓应用安全指南 4.6.3 处理文件 高级话题
安卓应用安全指南 4.6.3 处理文件 高级话题 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY ...
- 安卓应用安全指南 4.6.1 处理文件 示例代码
安卓应用安全指南 4.6.1 处理文件 示例代码 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY ...
- 安卓应用安全指南 4.4.2 创建/使用服务 规则书
安卓应用安全指南 4.4.2 创建/使用服务 规则书 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC ...
- android 存储盘 dcim,DCIM是个啥?安卓图片存储位置指南
DCIM是个啥?安卓图片存储位置指南 一般安卓手机的相机功能都会有固定的存放路径,这个位置默认为:/sdcard/DCIM/100Andro或者/sdcard/DCIM/Camera,这里的sdcar ...
- 安卓应用安全指南 4.8 输出到 LogCat
4.8 输出到 LogCat 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY-NC-SA 4.0 ...
- 安卓应用安全指南 4.1.2 创建/使用活动 规则书
4.1.2 创建/使用活动 规则书 原书:Android Application Secure Design/Secure Coding Guidebook 译者:飞龙 协议:CC BY-NC-SA ...
最新文章
- 程序人生:外链建设流程与细节都有哪些
- 《HTTP权威指南》– 8.网关、机器人
- Python网络爬虫与信息提取(二)(BeautifulSoup库)
- 《系统集成项目管理工程师》必背100个知识点-52成功的项目团队特点
- Git本地仓库管理远程库(GitHub)——clone(下载)、push(提交)、pull(拉取)操作
- 实践:创建异步 HTTP 处理器
- Leetcode--870. 优势洗牌
- MATLAB的PLOT函数线型设置及横坐标为字符串的代码实例
- 20180828 上课截图
- Windows Server 2008 故障转移群集简介
- Java 字符串格式化 String.format()
- Windows10 安装 RabbitMQ
- zookeeper服务端
- C++中利用输入输入流进行一行输入
- Tera Term使用说明
- 双击div变成可编辑区的简单实现
- 优先队列三大利器——二项堆、斐波那契堆、Pairing 堆
- 机器视觉——远心镜头(1)
- javaweb基于SSM框架的书籍小说在线阅读下载网站
- 信号处理趣学D4——利用谐波叠加对周期方波进行逼近