Veracode静态扫描报告指出了我的内容提供商实施中的SQL注入漏洞。
之前,我发布了question与我对这个漏洞的所有怀疑有关。
经过几次讨论后,我得出的结论是,报告中可能存在误报。因为根据我研究和阅读的内容,我遵循Android docs和other referenced sources中提到的安全准则来避免SQL注入。
到处都有建议对传递给SQL查询的数据执行至少一些输入验证。我想要涵盖这种可能性,这就是缺陷的原因。 每个人都要求我在传递查询之前清理数据。 如何确切地清理传递给selectionArgs数组的变量传递给Content Provider的delete(),update()方法?
DatabaseUtils.sqlEscapeString()是否足够? 请提出建议!
这是我需要清理变量的实现:
public Loader<Cursor> onCreateLoader(int id, Bundle b) {
switch (id) {
case THOUGHT_LOADER:
return new CursorLoader(getActivity(), NewsFeedTable.CONTENT_URI, NewsFeedTable.PROJECTION, NewsFeedTable._id + "=?", new String[]{tid}, null);
case COMMENT_LOADER:
return new CursorLoader(getActivity(), CommentTable.CONTENT_URI, CommentTable.PROJECTION, CommentTable.COLUMN_TID + "=?", new String[]{tid}, null);
default:
return null;
}
}
报告指出该缺陷:此行中SQL命令('SQL注入')(CWEID 89)中使用的特殊元素的中和不正确
deleted = db.delete(BulletinTable.TABLE_NAME,selection,selectionArgs); 在以下代码中:
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
if (uri.equals(Contract.BASE_CONTENT_URI)) {
deleteDatabase();
return 1;
}
SQLiteDatabase db = openHelper.getWritableDatabase();
int deleted = 0;
switch (matcher.match(uri)) {
case BULLETIN:
deleted = db.delete(BulletinTable.TABLE_NAME, selection, selectionArgs);
break;
case CLASSROOMS:
deleted = db.delete(ClassroomsTable.TABLE_NAME, selection, selectionArgs);
break;
default:
throw new IllegalArgumentException("Unsupported URI: " + uri);
}
if (deleted > 0) {
getContext().getContentResolver().notifyChange(uri, null);
}
return deleted;
}
答案 0 :(得分:1)
selectionArgs
数组中的值永远不需要清理,因为它们不能被解释为SQL命令(这是具有单独参数值的重点)。
sqlEscapeString()
的目的是格式化一个字符串,以便将其放入SQL命令(即转义单引号;所有其他字符在SQL字符串中没有任何意义)。但是当你知道有一个字符串时,你应该selectionArgs
,所以这个函数没用。
您只需要清理最终在SQL命令本身中的字符串。在这种情况下,这将是selection
。如果此值来自用户或其他某个应用程序,那么您无法控制DELETE语句实际执行的内容(它可以调用SQL函数,或执行访问数据库其他部分的子查询)。
出于实际目的,无法清理旨在包含SQL命令的字符串,因为那时您需要一个完整的SQL解析器。如果您的内容提供商可用于外部代码,则应允许仅通过URI删除特定项目,并禁止自定义selection
。