[Информационная безопасность, Python] Ищем уязвимости в Python-коде с помощью open source инструмента Bandit (перевод)
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Наверное, все разработчики слышали, что нужно писать чистый код. Но не менее важно писать и использовать безопасный код.
Python-разработчики обычно устанавливают модули и сторонние пакеты, чтобы не изобретать велосипеды, а использовать готовые и проверенные решения. Но проблема в том, что они не всегда тщательно проверены на уязвимости.
Часто хакеры используют эти уязвимости, в известно каких целях. Поэтому мы должны иметь возможность хотя бы фиксировать факты вторжения в наш код. А ещё лучше — заранее устранять уязвимости. Для этого нужно сначала самим найти их в коде, используя специальные инструменты.
В этом туториале мы рассмотрим, как даже в очень простом коде могут появиться уязвимости и как использовать утилиту Bandit для их поиска.
Наиболее распространённые уязвимости в Python-коде
Вы, вероятно, слышали про взломы крупных веб-сайтов и кражу данных их пользователей. Возможно, с какими-то атаками вы сталкивались лично. Через уязвимости в нашем коде злоумышленники могут получить доступ к командам операционной системы или к данным. Некоторые функции или Python-пакеты могут казаться безопасными, когда вы используете их локально. Однако при развёртывании продукта на сервере они открывают двери для хакеров.
С наиболее распространёнными атаками более-менее справляются современные фреймворки и другие умные инструменты разработки ПО, имеющие встроенную защиту. Но понятно, что не со всеми и далеко не всегда.
Командная инъекция (внедрение команд)
Командная инъекция — вид атаки, целью которой является выполнение произвольных команд в ОС сервера. Атака срабатывает, например, при запуске процесса с помощью функций модуля subprocess, когда в качестве аргументов используются значения, хранящиеся в переменных программы.
В этом примере мы используем модуль subprocess, чтобы выполнить nslookup и получить информацию о домене:
# nslookup.py
import subprocess
domain = input(«Enter the Domain: «)
output = subprocess.check_output(f«nslookup {domain}», shell=True, encoding='UTF-8')
print(output)
Что здесь может пойти не так?
Конечный пользователь должен ввести домен, а скрипт должен вернуть результат выполнения команды nslookup. Но, если вместе с именем домена через точку с запятой ввести ещё и команду ls, будут запущены обе команды:
$ python3 nslookup.py
Enter the Domain: stackabuse.com ; ls
Server: 218.248.112.65
Address: 218.248.112.65#53
Non-authoritative answer:
Name: stackabuse.com
Address: 172.67.136.166
Name: stackabuse.com
Address: 104.21.62.141
Name: stackabuse.com
Address: 2606:4700:3034::ac43:88a6
Name: stackabuse.com
Address: 2606:4700:3036::6815:3e8d
config.yml
nslookup.py
Используя эту уязвимость, можно выполнять команды на уровне ОС (у нас ведь shell = true).
Представьте себе, что случится, если злоумышленник, например, отправит на выполнение команду cat/etc/passwd, которая раскроет пароли существующих пользователей. Так что использование модуля subprocess может быть очень рискованным.
SQL-инъекция
SQL-инъекция — это атака, в ходе которой из пользовательского ввода конструируется SQL-выражение, содержащее вредоносные запросы.
Благодаря активному использованию ORM количество таких атак существенно снизилось. Но если в вашей кодовой базе по-прежнему есть фрагменты, написанные на чистом SQL, необходимо знать, как строятся эти SQL-запросы. Насколько безопасны аргументы, которые вы валидируете и подставляете в запрос?
Рассмотрим пример:
from django.db import connection
def find_user(username):
with connection.cursor() as cur:
cur.execute(f«»select username from USERS where name = '%s'«» % username)
output = cur.fetchone()
return output
Тут всё просто: в качестве аргумента передадим, например, строку «Foobar». Строка вставляется в SQL-запрос, в результате чего получается:
select username from USERS where name = 'Foobar'
Так же, как и в случае с командной инъекцией, — если кто-то передаст символ «;», он сможет выполнять несколько команд. Например, добавим к нашему запросу вместо имени пользователя строку «'; DROP TABLE USERS; --» и получим:
select username from USERS where name = ' '; DROP TABLE USERS; --'
Этот запрос удалит всю таблицу USERS. Упс!
Обратите внимание, на двойной дефис в конце запроса. Это комментарий, который нейтрализует следующий за ним символ «'». В результате команда select отработает с аргументом «' '» вместо имени пользователя, а потом выполнится команда DROP, которая больше не является частью строки.
select username from USERS where name = ' ';
DROP TABLE USERS;
Аргументы SQL-запроса могут создать кучу проблем, если за ними не следить. Вот где инструменты для анализа безопасности могут хорошо помочь. Они позволяют найти в коде уязвимости, которые непреднамеренно внесли разработчики.
Команда assert
Не применяйте команду assert, чтобы защитить те части кодовой базы, к которым пользователи не должны получить доступ. Простой пример:
def foo(request, user):
assert user.is_admin, «user does not have access»
# далее идёт код с ограниченным доступом
По умолчанию __debug__ установлено в True. Однако на продакшне могут сделать ряд оптимизаций, в том числе установить для __debug__ значение False. В этом случае команды assert не сработают и злоумышленник добраться до кода с ограниченным доступом.
Используйте команду assertтолько для отправки сообщений о нюансах реализации другим разработчикам.
Bandit
Bandit — это инструмент с открытым исходным кодом, написанный на Python. Он помогает анализировать Python-код и находить в нём наиболее распространённые уязвимости. О некоторых из них я рассказал в предыдущем разделе. Используя менеджер пакетов pip, Bandit можно легко установить локально или на удалённую виртуалку например.
Устанавливается эта штука с помощью простой команды:
$ pip install bandit
Bandit нашёл применение в двух основных сферах:
- DevSecOps: как один из процессов Continuous Integration (CI).
- Разработка: как часть локального инструментария разработчика, используется для проверки кода на уязвимость до коммита.
Как использовать Bandit
Bandit может быть легко интегрирован как часть тестов CI, а проверки на уязвимость можно выполнять перед отправкой кода в продакшн. Например, инженеры DevSecOps могут запускать Bandit’а всякий раз, когда происходит pull-запрос или коммит кода.
Результаты проверки кода на уязвимость можно экспортировать в CSV, JSON и так далее.
Во многих компаниях существуют ограничения и запреты на использование некоторых модулей, потому что с ними связаны определённые, хорошо известные в узких кругах, уязвимости. Bandit может показать, какие модули можно использовать, а какие внесены в чёрный список: конфигурации тестов для соответствующих уязвимостей хранятся в специальном файле. Его можно создать с помощью Генератора конфигураций (bandit-config-generator):
$ bandit-config-generator -o config.yml
Сгенерированный файл config.yml содержит блоки конфигурации для всех тестов и чёрного списка. Эти данные можно удалить или отредактировать. Для указания списка идентификаторов тестов, которые должны быть включены или исключены из процедуры проверки, нужно использовать флаги -t и -s:
- -t TESTS, --tests TESTS, где TESTS — список идентификаторов тестов (в квадратных скобках, через запятую), которые нужно включить.
- -s SKIPS, --skip SKIPS, где SKIPS — список идентификаторов тестов (в квадратных скобках, через запятую), которые нужно исключить.
Проще всего использовать конфигурационный файл с настройками по умолчанию.
$ 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
В команде выше после флага -r указан каталог проекта, после флага -f — формат вывода, а после флага -o указан файл, в который нужно записать результаты проверки. Bandit проверяет весь python-код внутри каталога проекта и возвращает результат в формате CSV.
После проверки мы получим достаточно много информации:
Продолжение таблицы
Как упоминалось в предыдущем разделе, импорт модуля subprocess и использование аргумента shell = True в вызове функции subprocess.check_output несут серьёзную угрозу безопасности. Если использование этого модуля и аргумента неизбежно, их можно внести в белый список в файле конфигурации и заставить Bandit’а пропускать тесты, включив в список SKIPS идентификаторы B602 (subprocess_popen_with_shell_equals_true) и B404 (import_subprocess):
$ bandit-config-generator -s [B602, B404] -o config.yml
Если повторно запустить Bandit, используя новый файл конфигурации, на выходе получим пустой CSV-файл. Это означает, что все тесты были пройдены:
> bandit -c code/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. Если вы используете в своих проектах модули, в которых сомневаетесь, их можно проверить на уязвимость прямо сейчас. Да и наш собственный код мы порой не успеваем довести до ума, жертвуя не только красивыми решениями, но и о безопасностью. Каковы ваши приоритеты?
VPS серверы от Маклауд быстрые и безопасные.
Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации!
оригинал
===========
Источник:
habr.com
===========
===========
Автор оригинала: Sathiya Sarathi Gunasekaran
===========Похожие новости:
- [Информационная безопасность] Барахолка для Пентестера
- [Информационная безопасность, Законодательство в IT, IT-компании] В сети обнаружен зарубежный сервер Elasticsearch с обновляемой базой СМС-сообщений, предположительно, с номера 900
- [Ненормальное программирование, Python, Обработка изображений, Машинное обучение, Разработка под Windows] Управляем звуком ПК от активности пользователя с помощью Python
- [] JetBrains Academy: платформенные обновления, любимые проекты пользователей и годовая подписка
- [Python, Алгоритмы, Big Data, Машинное обучение, Искусственный интеллект] DataScience Digest — 17.06.21
- [Разработка игр, Старое железо, Игры и игровые приставки] То, чего не может быть: самые необычные версии обычных игровых консолей
- [Информационная безопасность, Облачные сервисы] Идеальный пароль по науке: трудно взломать, невозможно забыть
- [Информационная безопасность, Криптография, Законодательство в IT, Криптовалюты] Украинские власти разоблачили крупную группировку криптовымогателей
- [API] 17 интересных (и забавных) API для вашего проекта
- [Информационная безопасность, Python, Программирование, Машинное обучение] Вышла библиотека PyWhat для автоматического парсинга трафика
Теги для поиска: #_informatsionnaja_bezopasnost (Информационная безопасность), #_python, #_python, #_poisk_ujazvimostej (поиск уязвимостей), #_bandit, #_blog_kompanii_maklaud (
Блог компании Маклауд
), #_informatsionnaja_bezopasnost (
Информационная безопасность
), #_python
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 02:24
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Наверное, все разработчики слышали, что нужно писать чистый код. Но не менее важно писать и использовать безопасный код. Python-разработчики обычно устанавливают модули и сторонние пакеты, чтобы не изобретать велосипеды, а использовать готовые и проверенные решения. Но проблема в том, что они не всегда тщательно проверены на уязвимости. Часто хакеры используют эти уязвимости, в известно каких целях. Поэтому мы должны иметь возможность хотя бы фиксировать факты вторжения в наш код. А ещё лучше — заранее устранять уязвимости. Для этого нужно сначала самим найти их в коде, используя специальные инструменты. В этом туториале мы рассмотрим, как даже в очень простом коде могут появиться уязвимости и как использовать утилиту Bandit для их поиска. Наиболее распространённые уязвимости в Python-коде Вы, вероятно, слышали про взломы крупных веб-сайтов и кражу данных их пользователей. Возможно, с какими-то атаками вы сталкивались лично. Через уязвимости в нашем коде злоумышленники могут получить доступ к командам операционной системы или к данным. Некоторые функции или Python-пакеты могут казаться безопасными, когда вы используете их локально. Однако при развёртывании продукта на сервере они открывают двери для хакеров. С наиболее распространёнными атаками более-менее справляются современные фреймворки и другие умные инструменты разработки ПО, имеющие встроенную защиту. Но понятно, что не со всеми и далеко не всегда. Командная инъекция (внедрение команд) Командная инъекция — вид атаки, целью которой является выполнение произвольных команд в ОС сервера. Атака срабатывает, например, при запуске процесса с помощью функций модуля subprocess, когда в качестве аргументов используются значения, хранящиеся в переменных программы. В этом примере мы используем модуль subprocess, чтобы выполнить nslookup и получить информацию о домене: # nslookup.py
import subprocess domain = input(«Enter the Domain: «) output = subprocess.check_output(f«nslookup {domain}», shell=True, encoding='UTF-8') print(output) Что здесь может пойти не так? Конечный пользователь должен ввести домен, а скрипт должен вернуть результат выполнения команды nslookup. Но, если вместе с именем домена через точку с запятой ввести ещё и команду ls, будут запущены обе команды: $ python3 nslookup.py
Enter the Domain: stackabuse.com ; ls Server: 218.248.112.65 Address: 218.248.112.65#53 Non-authoritative answer: Name: stackabuse.com Address: 172.67.136.166 Name: stackabuse.com Address: 104.21.62.141 Name: stackabuse.com Address: 2606:4700:3034::ac43:88a6 Name: stackabuse.com Address: 2606:4700:3036::6815:3e8d config.yml nslookup.py Используя эту уязвимость, можно выполнять команды на уровне ОС (у нас ведь shell = true). Представьте себе, что случится, если злоумышленник, например, отправит на выполнение команду cat/etc/passwd, которая раскроет пароли существующих пользователей. Так что использование модуля subprocess может быть очень рискованным. SQL-инъекция SQL-инъекция — это атака, в ходе которой из пользовательского ввода конструируется SQL-выражение, содержащее вредоносные запросы. Благодаря активному использованию ORM количество таких атак существенно снизилось. Но если в вашей кодовой базе по-прежнему есть фрагменты, написанные на чистом SQL, необходимо знать, как строятся эти SQL-запросы. Насколько безопасны аргументы, которые вы валидируете и подставляете в запрос? Рассмотрим пример: from django.db import connection
def find_user(username): with connection.cursor() as cur: cur.execute(f«»select username from USERS where name = '%s'«» % username) output = cur.fetchone() return output Тут всё просто: в качестве аргумента передадим, например, строку «Foobar». Строка вставляется в SQL-запрос, в результате чего получается: select username from USERS where name = 'Foobar'
Так же, как и в случае с командной инъекцией, — если кто-то передаст символ «;», он сможет выполнять несколько команд. Например, добавим к нашему запросу вместо имени пользователя строку «'; DROP TABLE USERS; --» и получим: select username from USERS where name = ' '; DROP TABLE USERS; --' Этот запрос удалит всю таблицу USERS. Упс! Обратите внимание, на двойной дефис в конце запроса. Это комментарий, который нейтрализует следующий за ним символ «'». В результате команда select отработает с аргументом «' '» вместо имени пользователя, а потом выполнится команда DROP, которая больше не является частью строки. select username from USERS where name = ' ';
DROP TABLE USERS; Аргументы SQL-запроса могут создать кучу проблем, если за ними не следить. Вот где инструменты для анализа безопасности могут хорошо помочь. Они позволяют найти в коде уязвимости, которые непреднамеренно внесли разработчики. Команда assert Не применяйте команду assert, чтобы защитить те части кодовой базы, к которым пользователи не должны получить доступ. Простой пример: def foo(request, user):
assert user.is_admin, «user does not have access» # далее идёт код с ограниченным доступом По умолчанию __debug__ установлено в True. Однако на продакшне могут сделать ряд оптимизаций, в том числе установить для __debug__ значение False. В этом случае команды assert не сработают и злоумышленник добраться до кода с ограниченным доступом. Используйте команду assertтолько для отправки сообщений о нюансах реализации другим разработчикам. Bandit Bandit — это инструмент с открытым исходным кодом, написанный на Python. Он помогает анализировать Python-код и находить в нём наиболее распространённые уязвимости. О некоторых из них я рассказал в предыдущем разделе. Используя менеджер пакетов pip, Bandit можно легко установить локально или на удалённую виртуалку например. Устанавливается эта штука с помощью простой команды: $ pip install bandit
Bandit нашёл применение в двух основных сферах:
Как использовать Bandit Bandit может быть легко интегрирован как часть тестов CI, а проверки на уязвимость можно выполнять перед отправкой кода в продакшн. Например, инженеры DevSecOps могут запускать Bandit’а всякий раз, когда происходит pull-запрос или коммит кода. Результаты проверки кода на уязвимость можно экспортировать в CSV, JSON и так далее. Во многих компаниях существуют ограничения и запреты на использование некоторых модулей, потому что с ними связаны определённые, хорошо известные в узких кругах, уязвимости. Bandit может показать, какие модули можно использовать, а какие внесены в чёрный список: конфигурации тестов для соответствующих уязвимостей хранятся в специальном файле. Его можно создать с помощью Генератора конфигураций (bandit-config-generator): $ bandit-config-generator -o config.yml
Сгенерированный файл config.yml содержит блоки конфигурации для всех тестов и чёрного списка. Эти данные можно удалить или отредактировать. Для указания списка идентификаторов тестов, которые должны быть включены или исключены из процедуры проверки, нужно использовать флаги -t и -s:
Проще всего использовать конфигурационный файл с настройками по умолчанию. $ 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 В команде выше после флага -r указан каталог проекта, после флага -f — формат вывода, а после флага -o указан файл, в который нужно записать результаты проверки. Bandit проверяет весь python-код внутри каталога проекта и возвращает результат в формате CSV. После проверки мы получим достаточно много информации: Продолжение таблицы Как упоминалось в предыдущем разделе, импорт модуля subprocess и использование аргумента shell = True в вызове функции subprocess.check_output несут серьёзную угрозу безопасности. Если использование этого модуля и аргумента неизбежно, их можно внести в белый список в файле конфигурации и заставить Bandit’а пропускать тесты, включив в список SKIPS идентификаторы B602 (subprocess_popen_with_shell_equals_true) и B404 (import_subprocess): $ bandit-config-generator -s [B602, B404] -o config.yml
Если повторно запустить Bandit, используя новый файл конфигурации, на выходе получим пустой CSV-файл. Это означает, что все тесты были пройдены: > bandit -c code/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. Если вы используете в своих проектах модули, в которых сомневаетесь, их можно проверить на уязвимость прямо сейчас. Да и наш собственный код мы порой не успеваем довести до ума, жертвуя не только красивыми решениями, но и о безопасностью. Каковы ваши приоритеты? VPS серверы от Маклауд быстрые и безопасные. Зарегистрируйтесь по ссылке выше или кликнув на баннер и получите 10% скидку на первый месяц аренды сервера любой конфигурации! оригинал =========== Источник: habr.com =========== =========== Автор оригинала: Sathiya Sarathi Gunasekaran ===========Похожие новости:
Блог компании Маклауд ), #_informatsionnaja_bezopasnost ( Информационная безопасность ), #_python |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 02:24
Часовой пояс: UTC + 5