С развитием технологий вопросы безопасности программного обеспечения выходят на первый план. Как защитить код от уязвимостей? Какие инструменты помогут разработчикам писать более безопасные программы? На эти и другие вопросы в эксклюзивном интервью ответил Александр Устинов, аналитик по кибербезопасности, автор канала "Кибербомж".
— Александр, какие самые частые причины появления уязвимостей в программах?
— Первое — это неосведомленность об этих самых уязвимостях. Это может показаться нелогичным: как разработчик может не знать об уязвимостях? Но не все программы и сайты, которыми мы пользуемся, написаны разработчиками уровня "сеньор" с многолетним опытом. Многие из них пишут начинающие программисты, которых еще не научили такому понятию как безопасный код. Хотя, по правде говоря, этот фактор присущ не только начинающим разработчикам программного обеспечения (ПО).
Второе — использование сторонних библиотек. Ведь они написаны такими же людьми, которые, как и мы, могут не выспаться, заболеть или просто ошибиться. Поэтому перед внедрением в свой проект сторонней библиотеки, стоит предварительно протестировать её на безопасность. Бывают даже случаи кражи аккаунтов разработчиков и подмена исходного кода сторонних библиотек.
Третья причина — использование устаревшего ПО (фреймворки, библиотеки, CMS), известного своими уязвимостями.
На четвертом месте я бы назвал несколько безответственный подход разработчиков к необходимости тестирования собственного кода на безопасность. Данный фактор, конечно, не относится ко всем поголовно. Но я заметил, что в больших компаниях с ростом числа тестировщиков разработчики стали меньше тестировать свой код. "Зачем? Ведь его протестирует тестировщик", — думают они. Вот только тестировщики тестируют функциональность, юзабилити, юзер-экспириенс… Тестирование безопасности не входит в их область знаний и компетенций.
Порой это связано не с безответственностью, а с ошибками планирования. Дело в том, что современный цикл разработки разбивается на спринты. Это отрезок времени длительностью две недели, в рамках которого разрабатываются запланированные функции приложения. Разработчик пытается успеть сделать новую функцию в срок, тестировщику нужно эту функцию протестировать. Зачастую это происходит аккурат к концу спринта, и времени на тестирование безопасности остаётся крайне мало. Поэтому часть нового функционала идёт в продакшн в обход отдела безопасности. Если постфактум обнаруживается уязвимость, то её исправление будет сделано не раньше следующего спринта. Конечно, бывают исключения: если уязвимость критическая, то её исправляют как можно скорее.
И еще один важный момент — это бездумное использование нейронных сетей при написании кода. Разработчик должен знать, что делает каждая строка кода в его merge requestʼе, а не просто проверить, что код запустился. Всегда нужно помнить, что ИИ обучался в интернете на коде, написанном людьми. Среди этого кода были как хорошие, так и плохие практики.
SQL-инъекция — это кибератака, при которой злоумышленник внедряет вредоносный SQL-код в запросы к базе данных, чтобы получить несанкционированный доступ к информации или управлению системой.
Как защитить свой код от SQL-инъекции:
— относиться ко всем данным, приходящим от клиента как к "недоверенным" и применять к ним валидацию типов (то есть, проверять, что данные соответствуют ожидаемому формату) и санитизацию (удаление из переданных данных специальных символов или подстрок);
— не использовать "сырые" SQL-запросы (то есть, собранные вручную), и никогда напрямую не конкатенировать (по сути, не "склеивать") необработанный пользовательский ввод в SQL-запрос;
— использовать ORM библиотеки для работы с базами данных, обязательно изучить документацию, ведь в ней часто есть раздел про безопасность;
— отслеживать обновления используемой ORM библиотеки и, соответственно, вовремя ее обновлять.
— Почему обновления библиотек так важны для безопасности?
— В сторонних библиотеках регулярно находят уязвимости, и разработчики их патчат (исправляют). Не обновлённая библиотека — частый вектор атаки. Когда мы скачиваем и внедряем библиотеку в своё приложение, она становится его частью со всеми вытекающими.
Будет обидно, если вы предусмотрели всё, но оставили не обновлённую библиотеку с критической уязвимостью.
Стоит воздержаться от использования заброшенных или архивированных библиотек, которые не будут запатчены никогда.
Цифра
60% кибератак проводится через уязвимости, для которых был доступен, но не применен "патч".
Источник: servicenow.com.
Советы по обеспечению безопасности пользовательских данных при написании кода
Ключевой принцип: все внешние данные проверяются перед использованием, а их обработка выполняется с учётом возможных угроз.
— Все данные, полученные от пользователей или внешних систем, следует считать потенциально опасными и проверять их на соответствие ожидаемому формату, а также удалять в случае необходимости спецсимволы, которые могут нарушить работу системы.
— Каждое поле в программе должно иметь четко заданный тип данных, и, если полученное значение не соответствует типу (например, вместо числа пришел текст), система должна прекратить обработку и сообщить об ошибке.
— Не конвертируйте XML-данные из ненадежных источников. Если такая необходимость есть, используйте настройки, которые не позволят программе загружать потенциально опасные сторонние данные.
— Как хранить пароли пользователей, чтобы их не украли?
— Во-первых, нельзя хранить пароли в открытом виде. Их нужно хешировать с использованием "соли" (добавление к паролю "случайного" набора символов) и "перца" (секретного ключа, который хранится отдельно от базы). Хеширование — это превращение пароля в набор случайных символов, который хакер, даже украв базу данных, не сможет расшифровать. Для хеширования нужно использовать стойкие алгоритмы, например, bcrypt или argon2.
Кроме того, хранить пароли лучше в отдельной таблице, к которой у приложения нет прямого доступа.
— Я читала, что самые опасные ошибки допускаются при написании кода на С или С++. Это действительно так? Как защититься от взлома, если программа написана на этом языке?
— Действительно, принято так считать ввиду того, что на этих языках часто пишут низкоуровневое ПО. Низкоуровневое не потому, что низкий уровень программистов, а как раз наоборот. Имеется в виду низкий уровень абстракций: часто работа ведётся напрямую с процессами и памятью устройства, поскольку на С и С++ пишут драйвера, ПО для заводов, прошивки.
Для дополнительной защиты приложений на C/C++ разработаны специальные механизмы компиляции и runtime-защиты. Например, stack canaries, ASLR, DEP. Если их включить, то даже при наличии уязвимости, её эксплуатация усложнится, либо станет невозможной.
Также если вы работаете на С/С++, стоит отдельно изучать практики по безопасности. Их можно найти, в частности, на таком ресурсе, как Microsoft Learn.
— Существуют ли способы автоматической проверки кода на безопасность?
— Да, есть ряд специализированного ПО для проверки кода на безопасность — так называемые SAST (Static Application Security Testing) решения. Также есть IAST и RASP решения, которые предлагают возможность совмещения динамического и статического анализа. Из платных решений существуют checkmarx, PT AI, mend, oversecured scanner.
— Что делать, если в программе нашли опасную ошибку уже после выпуска?
— Если речь о веб-приложении, то нужно локализовать код, который привёл к уязвимости, назначить ответственного за исправление кода, а затем провести расследование, просмотреть логи приложения на предмет того, пытался ли кто-то уже проэксплуатировать уязвимость.
Если в компании есть WAF (специальное средство защиты веб-приложений от атак), можно написать правило, которое будет блокировать атаку в будущем или сейчас, если хакеры уже прознали о бреши безопасности.
Если говорить про мобильное или десктоп приложение, то тут все немного сложнее, так как обновлённое приложение нужно доставить до конечного клиента. То есть в данном случае нужно не только исправить ошибку, но и подготовить обновление, которое пользователь должен скачать.
— Где ИТ-специалисты, разработчики могут получить информацию об основах кибербезопасности при написании кода? Посоветуйте, если можете, какие-то конкретные ресурсы.
— Во-первых, на профильных конференциях. Например, в РФ есть PHDays, Offzone, Zeronights, Volga CTF. Они больше других нацелены на специалистов по кибербезопасности. Также есть Huizenbug: целевая аудитория этой конференции — разработчики и тестировщики, на ней часто выступают мои коллеги с материалом, который будет полезен разработчикам. Записи с этих конференций обычно всегда доступны на их каналах.
Я ранее упоминал инструмент semgrep. Он производит сигнатурный анализ уязвимостей для разных языков программирования. В себе он содержит базу правил, которые можно изучить. Для каждого правила описано, что это за уязвимость, пример уязвимого кода и пример исправленного кода.
Можно обучаться по похожему принципу, идя от противного.
Есть примеры приложений, с заранее заложенными в них уязвимостями. Можно смотреть код этих приложений и изучать, как делать не нужно (например, https://github.com/JoyChou93/java-sec-code?tab=readme-ov-file, https://github.com/digininja/DVWA, https://github.com/juice-shop/juice-shop, https://cheatsheetseries.owasp.org/cheatsheets/PHP_Configuration_Cheat_Sheet.html, https://owasp.org/www-project-top-ten/).
Кроме того, обычно в документации к фреймворкам для разработки есть раздел про безопасность. Я рекомендую его изучать (например, для PHP symphony — https://symfony.com/doc/current/security.html).
— После вуза (или во время практики) студенты имеют какие-то базовые знания по безопасной работе с кодом? Или эти знания они получают уже во время практики или самостоятельного изучения?
— Очень зависит от вуза и преподавательского состава. Когда я учился, такой дисциплины у нас не было, и никто не преподавал. Чаще всего это получается через практику и самообразование.
Кратко
Что делать для обеспечения безопасности кода:
— повышать уровень насмотренности разработчиков в разрезе безопасности;
— покрывать код тестами, нацеленными на безопасность (например, автоматическая проверка ролевой модели по матрице доступа);
— использовать современные IDE (приложение, в котором пишут код), которые могут самостоятельно подсветить разработчикам некоторые недочеты, способные привести к уязвимостям;
— добавить в процесс CI/CD утилиты, которые проверяют код на безопасность (из бесплатных, например, semgrep, codeql, joern);
— отслеживать уязвимости в сторонних библиотеках;
— внедрять практики security gates (подразумевается, что если в ходе релиза новой версии, суммарный коэффициент безопасности переваливает за определённую отметку, этот релиз останавливается);
— применять ИИ инструменты для проверки и анализа кода: например, можно спросить ИИ, безопасен ли код, который вы написали, подвержен ли он уязвимостям из OWASP TOP 10.
(Важно: ИИ должен быть запущен у вас локально, не отправляйте ваш код в chatgpt или perplexity).
Материал подготовлен при поддержке гранта Минобрнауки России в рамках Десятилетия науки и технологий.
Цифра
70% приложений содержат хотя бы одну уязвимость после пяти лет разработки
Источник: www.veracode.com.