Предотвращение внедрения через проекцию в запросе контент-провайдера (параметризация?)

#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 '