PVS-Studio – статический анализатор, позволяющий обнаружить множество проблем, скрытых в исходном коде. Среди них также присутствуют ошибки, связанные с безопасностью приложений. К примеру, недавно анализатор научился определять наличие в коде конфиденциальных данных, таких как пароли. Данная потенциальная уязвимость находится в списке OWASP Top Ten и является куда более опасной, чем может показаться на первый взгляд. В чём же эта опасность состоит и как статический анализатор может от неё уберечь? Что ж, об этом (и не только) и написана данная заметка!
Мы продолжаем развивать PVS-Studio как SAST решение и планируем научить анализатор находить ещё больше ошибок, связанных с безопасностью, в коде на C, C++, C# и Java. Более подробно об этих планах (и не только) можно прочитать в статье "Дорожная карта PVS-Studio на 2021 год".
О хранении секретных данных в коде
Одним из вариантов развития поддержки SAST является добавление новых диагностических правил, реализующих проверку соответствия кода различным стандартам. Среди последних нововведений в C#-анализаторе стала проверка наличия в исходниках конфиденциальных данных. Хранение таких данных в коде противоречит пункту 2.10.4 OWASP Application Security Verification Standard (ASVS):
Verify passwords, integrations with databases and third-party systems, seeds and internal secrets, and API keys are managed securely and not included in the source code or stored within source code repositories. Such storage SHOULD resist offline attacks. The use of a secure software key store (L1), hardware TPM, or an HSM (L3) is recommended for password storage.
Риски, связанные с небезопасным хранением конфиденциальных данных в коде, входят в список OWASP Top Ten. В Common Weakness Enumeration (CWE) также присутствуют 2 позиции, связанные с данным вопросом: CWE-798 и CWE-259. Несмотря на это может возникать вопрос – в чём же состоит опасность?
Для проектов с открытым исходным кодом ответ очевиден – пароль или какие-либо другие данные, записанные в коде, доступны всем желающим для просмотра и использования. Злоумышленнику даже не придётся совершать каких-либо сложных действий: достаточно просто покопаться в репозитории.
Несколько лучше дела обстоят в том случае, если приложение доступно только в скомпилированном виде. Это даже может создать иллюзию безопасности. Ведь исходный код, казалось бы, недоступен, а значит, недоступны и записанные в нём данные. Увы, это необязательно так.
В реальной практике нередкими являются случаи, когда в системе захардкожены данные, которые могут использоваться для получения различных прав. Как правило, у пользователей даже нет возможности изменить эти данные. Для их получения злоумышленники могут использовать самые разные способы. В некоторых случаях логины, пароли и т. п. вообще можно увидеть в интерфейсе системы. В других – понадобится изучение различных файлов, декомпиляция кода, brute force и прочее. Так или иначе, умельцы умеют находить способы раскрытия захардкоженных секретов.
Достаточно часто актуальна следующая проблема: злоумышленник, получив хранящиеся в исходниках системы логины и/или пароли, сможет использовать их для подключения к другим системам этого типа. К примеру, он может установить систему локально. Проведя исследование и получив логины и пароли для этой локальной версии, злоумышленник сможет подключаться и к другим, использующим те же данные.
Кроме того, потенциальную опасность представляет тот факт, что данные, хранящиеся в исходниках, доступны всем программистам, которые с ними работают. В то же время, пользователь, установивший ту или иную систему для своих нужд, едва ли будет рад узнать, что компания-разработчик в любой момент может получить полный контроль над используемой им системой – а следовательно, получить различные секретные данные самого пользователя и т. д. Найденные в списке Common Vulnerabilities and Exposures (CVE) вхождения говорят о том, что такие ошибки рано или поздно обнаруживаются. И при этом, конечно же, выставляются на всеобщее обозрение.
Как было сказано ранее, уязвимости, связанные с захардкоженными конфиденциальными данными, не редкость: среди CVE можно отыскать множество примеров. Один из них – CVE-2012-5862. Система, о которой сообщается в данной позиции CVE, содержала файл "login.php", в котором присутствовал следующий код:
$password = mysql_escape_string($_POST['password']);
if (crypt($password,salt)=='satIZufhIrUfk'){
$sql_pthr_ = "SELECT user,password FROM account WHERE livello = 0";
....
}
if ($password=='astridservice' and $stilecustumization=='astrid'){ // <=
....
}
if (crypt($password,salt)=='saF8bay.tvfOk'){
$sql_insert="INSERT INTO account(user,password,livello,nome) VALUES
('sinapsi','sinapsi','0','Amministratore Sinapsi')";
....
}
В данном коде есть место, где переменная, содержащая переданный пользователем пароль, напрямую сравнивается со строковым литералом. Очевидно, злоумышленнику не составит труда использовать эту информацию для выполнения различных операций, не доступных обычному пользователю.
C#-анализатор PVS-Studio обнаруживает хранение конфиденциальных данных с помощью диагностического правила V5601. К примеру, взгляните на C#-код, напоминающий вышеприведённый пример:
string password = request.GetPostValue("password");
....
if (password == "astridservice" && stilecustomization == "astrid")
....
Проанализировав данный код, PVS-Studio сформирует следующее предупреждение:
V5601 Suspicious string literal could be a password: 'astridservice'. Storing credentials inside source code can lead to security issues.
Таким образом, статический анализатор позволит вовремя заметить подобную ошибку в коде и внести исправление. Следовательно, уровень безопасности вашего проекта также возрастёт.
Примечание. Стоит отметить, что V5601 принадлежит группе диагностических правил OWASP. Данная группа появится в PVS-Studio с выходом версии 7.12. По умолчанию OWASP-правила будут отключены, однако это можно легко изменить, используя, к примеру, интерфейс плагина для Visual Studio или Rider либо же напрямую редактируя файл настроек.
Указанный пример – лишь один из многих: захардкоженные конфиденциальные данные могут привести к появлению самого разного рода проблем. Во время своего исследования я находил множество других CVE-позиций, связанных с захардкоженными конфиденциальными данными. Ниже приведены ссылки на некоторые из них:
CVE-2004-1920 – роутер с super-логином и super-паролем;
CVE-2004-2556 – точка доступа с super-логином (опять) и не-super-паролем "5777364";
CVE-2004-2557 – результат "исправления" CVE-2004-2556 (по крайней мере, логин больше не super);
CVE-2012-1288 – захардкоженные данные аккаунта администратора;
CVE-2012-2949 – захардкоженный пароль в приложении на Android
и т. д.
Ещё один повод запускать анализ регулярно
Существует расхожее мнение, что статический анализатор достаточно использовать раз в несколько месяцев – перед релизом (или вообще раз в год). Это достаточно странная позиция. Исправить проблемы, накопившиеся за кучу времени, куда труднее, чем поправить перед коммитом код, написанный только что. Тем более, благодаря инкрементальному анализу проверка пройдет гораздо быстрее.
Во многих случаях удобным вариантом будет настройка анализа коммитов и pull request'ов. Это ещё сильнее повысит безопасность разрабатываемого приложения. Ведь код, содержащий ошибки, никак не попадёт в основную ветку репозитория. Это будет настоящим спасением в том случае, если разработчик вдруг забыл провести анализ. Более подробно про то, как настроить проверку pull request'ов, можно почитать в документации (см. раздел "Развёртывание анализатора в облачных CI").
Новая же возможность поиска конфиденциальных данных в коде ещё раз подтверждает необходимость регулярного проведения анализа: как на компьютерах программистов, так и в рамках CI. Ведь даже если программист заложит в исходники какие-нибудь пароли, то анализатор сообщит ему об этом. При необходимости разработчик может посмотреть документацию по диагностике V5601, чтобы понять, в чём именно состоит опасность.
Если же анализ проводится редко, то выходит, что захардкоженные данные будут долгое время храниться в исходниках. Для open-source проекта это совсем плохо – к тому времени, как анализатор позволит обнаружить проблему, данные уже нельзя будет считать конфиденциальными. Тем не менее, не защищены от подобной ситуации и другие проекты. Что если пользователь получит, скажем, бета-версию приложения? Такую как раз могут выдать между релизами. Если регулярные проверки исходников не проводятся, код в такой версии не будет проверен статическим анализатором. Получается, что все данные, "спрятанные" в исходниках, опять оказываются в открытом доступе.
Заключение
PVS-Studio постоянно развивается: добавляются новые диагностические правила, дорабатываются некоторые существующие механизмы, открываются новые направления. Стоит также отметить, что во многом именно постоянный диалог с пользователями позволяет делать анализатор лучше. И диагностическое правило V5601 – лишь один из компонентов, делающих анализатор средством, которое позволит повысить безопасность кода ваших проектов.
А как насчёт того, чтобы попробовать использовать PVS-Studio на своих проектах? Сделать это можно совершенно бесплатно, перейдя по ссылке и заполнив простенькую формочку. Ну, а у меня на этом всё, спасибо за внимание и до новых встреч!
Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Nikita Lipilin. PVS-Studio Clashes with Hardcoded Passwords.