#android #sqlite
#Android #sqlite
Вопрос:
У меня есть контент-провайдер, который я тестировал с помощью фреймворка Drozer, и оказалось, что проекция в query()
методе уязвима для внедрения. В том числе «* ИЗ SQLITE_MASTER —» перечислены все таблицы. Какой лучший способ защититься от этого? Я добавил фильтрацию определенных символов:
public Cursor query(Uri contentUri, String[] projection, String selection, String[] selectionArgs,
String sortOrder) {
/*
* Filter queries that contain certain characters to guard against SQL injection
*/
for (String query : projection) {
if (query.contains("*") || query.contains(";") || query.contains("'") || query.contains(""")) {
//Possible SQL injection attack, leave the query
return null;
}
}
Я понимаю, что фильтрация черного списка — это не путь, и параметризация проекции была бы лучше. Однако я не вижу способа сделать это в query()
методе. У него нет двух аргументов, например, у выбора есть «selection», а затем «selectionArgs». Как лучше всего защититься от внедрения без внесения в черный список?
Ответ №1:
Если вы хотите разрешить клиентам вашего контент-провайдера использовать произвольно сложный SQL, вы ничего не можете сделать; подобная проекция SomeColumn AS "* FROM sqlite_master -- ;'"""
была бы совершенно корректной и безвредной. Чтобы предотвратить доступ к конфиденциальным данным, эти данные должны находиться в другой базе данных.
Однако вы можете наложить ограничение, согласно которому клиенты могут читать только предопределенный набор столбцов без изменений. Чтобы обеспечить это, убедитесь, что все строки в projection
равны одному из этих имен столбцов.
Комментарии:
1. Значит, вы бы внесли его в белый список, а не в черный список? Может быть: проверьте имя таблицы для имени поставщика контента, и если каждая строка в массиве проекций не равна одному из имен столбцов для этой таблицы, выдайте исключение?
2. Это то, что я написал. Или вы просто говорите, что клиентам разрешено читать все в вашей БД.
Ответ №2:
Вероятно, простой способ предотвратить внедрение SQL в параметр проекции — использовать <a rel="noreferrer noopener nofollow" href="https://developer.android.com/reference/android/database/sqlite/SQLiteQueryBuilder.html#setProjectionMap(java.util.Map)» rel=»nofollow noreferrer»/>метод SQLiteQueryBuilder
setProjectionMap . Как указано в документации,
Если задана карта проекции, она должна содержать все имена столбцов, которые может запросить пользователь, даже если ключ и значение совпадают.
Я попытался исправить уязвимого контент-провайдера, добавив этот метод, и вот что показал мне Дрозер:
dz> run app.provider.query content://myContentProvider/myPath/ --projection "'"
Invalid column '