08.06.2021       Выпуск 390 (07.06.2021 - 13.06.2021)       Статьи

Проверка уязвимостей в коде Python с помощью Bandit

В этом руководстве мы рассмотрим, как простые строки кода могут оказаться разрушительными, и как с помощью Bandit можно их выявить.

Читать>>




Экспериментальная функция:

Ниже вы видите текст статьи по ссылке. По нему можно быстро понять ссылка достойна прочтения или нет

Просим обратить внимание, что текст по ссылке и здесь может не совпадать.

В этом руководстве мы рассмотрим, как простые строки кода могут оказаться разрушительными, и как с помощью Bandit можно их выявить.

Введение

Как разработчиков, нас с самого начала пути призывают писать чистый код. Не менее важным, но менее обсуждаемым является написание и использование безопасного кода.

В проектах Python мы обычно устанавливаем модули и пакеты сторонних разработчиков, чтобы избежать разработки уже существующих решений. Однако из-за этой распространенной практики хакеры используют зависимости, чтобы посеять хаос в нашем программном обеспечении, и поэтому нам нужно уметь обнаруживать, когда происходит что-то не так. Для этого мы используем такие инструменты, как Bandit, утилита анализа безопасности с открытым исходным кодом для проектов на Python.

Уязвимости в Python

Уязвимость безопасности в нашем коде — это недостаток, которым могут воспользоваться злоумышленники для эксплуатации наших систем и/или данных. Когда вы программируете на Python, вы можете обнаружить некоторые уязвимости в использовании функциональных вызовов или импорта модулей, которые могут быть безопасными при локальном вызове, но могут открыть двери для злоумышленников для вмешательства в систему при развертывании без правильной конфигурации.

Вы, вероятно, сталкивались с несколькими из них в своей повседневной деятельности по написанию кода. С некоторыми из наиболее распространенных атак и эксплойтов в значительной степени справляются современные фреймворки и системы, которые предвосхищают такие атаки.

Вот некоторые из них:

Уязвимость OS Command Injection

Основана на модуле subprocess, который используется для выполнения утилит командной строки и вызова процессов, связанных с операционной системой. Следующий фрагмент использует модуль подпроцесса для выполнения поиска DNS и возвращает результат:

import subprocess

input_domain = input("Введите домен: ")
result = subprocess.check_output(
    f"nslookup {input_domain}", shell=True, encoding="UTF-8"
)
print(result)

Что здесь может пойти не так?

В идеальном сценарии конечный пользователь предоставляет имя домена, и сценарий возвращает результаты команды nslookup. Но если вместе с доменом они предоставят команду на базе ОС, например ls, то будет получен следующий результат — команда тоже будет выполнена:

python3 command_inject.py

Введите домен: egorovegor.ru ; ls
Server:         192.168.13.1
Address:        192.168.13.1#53

Non-authoritative answer:
Name:   egorovegor.ru
Address: 92.53.116.135

command_inject.py

Позволив кому-то передать часть команды, мы дали ему доступ к терминалу на уровне ОС.

Представьте себе, насколько разрушительными могут быть последствия, если злоумышленник передаст такую команду, как cat /etc/passwd, которая раскроет пароли существующих пользователей. Как бы просто это ни звучало, модуль subproccess может быть очень рискованным в использовании.

Уязвимость SQL Injection

Атаки SQL Injection в наши дни редки благодаря широко используемым функциям ORM. Но если вы все еще придерживаетесь использования необработанного SQL, вам необходимо знать, как строятся ваши SQL-запросы и насколько безопасно проверяются и передаются параметры запроса.

Рассмотрим следующий фрагмент кода:

from django.db import connection


def find_user(login):
    '''Поиск пользователя в базе данных'''
    with connection.cursor() as cursor_db:
        cursor_db.execute(f"""select login from USERS where name = '{login}'""")
        result = cursor_db.fetchone()
    return result

Вызов функции прост — вы передаете в качестве аргумента строку, скажем, «Ivan», и эта строка вставляется в SQL-запрос, в результате чего получается:

Однако, как и в предыдущем случае, если кто-то добавит символ ;, то сможет создать цепочку из нескольких команд. Например, вставка ‘; DROP TABLE USERS; — приведет к следующему:

select login from USERS where name = ''; DROP TABLE USERS; --'

Первый оператор будет запущен прямо перед тем, как база данных сбросит всю таблицу USERS. Вот это да!

Обратите внимание, что последняя кавычка была закомментирована с помощью двойного тире. Параметры SQL-запросов могут стать кошмаром, если их не проанализировать должным образом. Вот где инструменты безопасности могут помочь в обнаружении таких непреднамеренных, но вредных строк кода.

Библиотека Bandit

Bandit — это инструмент с открытым исходным кодом, написанный на языке Python, который поможет вам проанализировать ваш Python-код и найти в нем общие проблемы безопасности. Он сможет просканировать ваш Python-код, найти уязвимости и эксплойты, такие как те, что были упомянуты в предыдущем разделе.

Установка

Bandit можно установить локально или в виртуальной среде с помощью pip:

Использование

Bandit можно использовать в следующих кейсах:

  • DevSecOps: включение Bandit как части практики непрерывной интеграции (CI).
  • Разработка: Bandit можно использовать локально как часть локальной настройки разработки, где разработчики могут контролировать эксплуатацию функций до фиксации кода.

Bandit может быть легко интегрирован в CI-тесты, и перед отправкой кода в производство можно проводить общие проверки на уязвимости.

Например, инженеры DevSecOps могут вызывать Bandit всякий раз, когда поднимается запрос на перенос или происходит фиксация кода, для повышения безопасности. На основе рекомендаций организации можно разрешить или ограничить импорт модулей и вызовы функций.

Bandit предоставляет пользователям контроль над тем, какие модули использовать, а какие занести в черный список. Этот контроль определяется в конфигурационном файле, который может быть создан с помощью инструмента bandit-config-generator. Результаты выполняемых тестов кода могут быть экспортированы в виде CSV, JSON и т.д.

Конфигурационный файл может быть сгенерирован вот так:

Созданный файл config.yml содержит несколько частей, соответствующих тестам, которые могут быть разрешены или отменены, вызовам функций, которые могут быть разрешены или отменены, а также максимальной длине криптографических ключей. Пользователь может использовать bandit, указав этот конфигурационный файл или выполнить все тесты, просто передав директорию проекта:

bandit -r code/ -f csv -o out.csv

[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: None
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    running on Python 3.8.5
434 [0.. 50.. 100.. 150.. 200.. 250.. 300.. 350.. 400.. ]
[csv]   INFO    CSV output written to file: out.csv

В этом вызове Bandit вы будете указывать каталог проекта с помощью флага -r и записывать вывод в виде CSV с помощью флага -o. Bandit тестирует все скрипты Python внутри этого каталога проекта и возвращает вывод в виде CSV. Вывод очень подробный, и вот как он выглядит:

Как уже упоминалось в предыдущем разделе, импорт модуля subprocess и аргумент shell=True представляют высокую угрозу безопасности. Если использование этого модуля и аргумента неизбежно, их можно внести в белый список конфигурационного файла и заставить его пропустить тесты, включив коды B602 (subprocess_popen_with_shell_equals_true) и B404 (import_subprocess) в «skips». Вы можете найти эти коды в сгенерированном конфигурационном файле. Тесты, включенные в файл в секции skips, следующие:

Если вы повторно запустите тесты Bandit, используя сгенерированный файл конфигурации, это приведет к созданию пустого CSV-файла, обозначающего, что все тесты были пройдены:

bandit -c config.yml -r code/ -f csv -o out2.csv
[main]  INFO    profile include tests: None
[main]  INFO    profile exclude tests: B404,B602
[main]  INFO    cli include tests: None
[main]  INFO    cli exclude tests: None
[main]  INFO    using config: code/config.yml
[main]  INFO    running on Python 3.8.5
434 [0.. 50.. 100.. 150.. 200.. 250.. 300.. 350.. 400.. ]
[csv]   INFO    CSV output written to file: out2.csv

Для совместной работы внутри организации этот файл конфигурации bandit должен быть встроен во вновь создаваемые проекты, чтобы разработчики могли иметь к нему доступ даже локально.

Заключение

Код должен быть чистым и безопасным. В этом кратком руководстве мы рассмотрели Bandit, библиотеку Python, используемую для выявления типичных проблем безопасности в модулях, которые вы, вероятно, уже используете.






Разместим вашу рекламу

Пиши: mail@pythondigest.ru

Нашли опечатку?

Выделите фрагмент и отправьте нажатием Ctrl+Enter.

Система Orphus