fa
Feedback
АК-ВС 3 | Анализатор кода

АК-ВС 3 | Анализатор кода

رفتن به کانال در Telegram

Канал для разработчиков, ИБ-специалистов и интеграторов. Здесь рассказываем о безопасности кода, требованиях регуляторов и о том, как работает АК-ВС 3. ИБ новости: https://t.me/EchelonEyes 📞 8 (495) 223-23-92 📩 akvs3@npo-echelon.ru

نمایش بیشتر
کشور مشخص نشده استدسته بندی مشخص نشده است
233
مشترکین
اطلاعاتی وجود ندارد24 ساعت
-17 روز
-230 روز
آرشیو پست ها
➡️Имя файла — это тоже часть безопасности
+5
➡️Имя файла — это тоже часть безопасности

➡️Приведение типов и ошибки в логике После приведения типа значение может измениться не так, как ожидает разработчик. В резул
➡️Приведение типов и ошибки в логике После приведения типа значение может измениться не так, как ожидает разработчик. В результате проверка в коде начинает работать неправильно. 🧷 Например:
int x = -1;
unsigned int y = x;

if (y > 0) {
    printf("positive\n");
}
📝 Что здесь произошло? x содержит -1. При приведении к беззнаковому типу (unsigned int) это значение преобразуется так, что то же двоичное представление начинает соответствовать большому положительному числу. В итоге условие y > 0 окажется истинным, хотя исходное значение было отрицательным. 🔺Чем это опасно: 1. проверка начинает давать неверный результат 2. код заходит не в ту ветку Из-за этого можно пропустить ошибку или неправильно обработать данные Чаще всего такие проблемы возникают при работе: 〰️со знаковыми и беззнаковыми типами 〰️с целыми и вещественными числами 〰️с типами разного размера ✔️Как этого избежать: 〰️не приводить тип без необходимости 〰️перед приведением проверять, входит ли значение в целевой диапазон, особенно для отрицательных, больших и граничных значений 〰️включать предупреждения компилятора, связанные с приведением типов 😎Приведение типа может изменить значение сильнее, чем кажется на первый взгляд.

➡️Почему ограничения на клиенте не считаются полноценной защитой? Может показаться, что если нужная проверка уже есть на клие
➡️Почему ограничения на клиенте не считаются полноценной защитой? Может показаться, что если нужная проверка уже есть на клиенте, то этого достаточно. Например: 〰️нельзя ввести больше 20 символов 〰️нельзя загрузить файл больше 5 МБ 〰️нельзя выбрать произвольное значение параметра 〰️кнопка опасного действия скрыта или недоступна 🔺Но клиентская часть приложения находится под контролем пользователя, поэтому полагаться только на проверки на этой стороне нельзя. Такие ограничения можно обойти: 〰️прямой отправкой запроса в обход интерфейса 〰️отключением или изменением клиентской логики проверки 〰️использованием инструментов вроде curl или Burp Suite Поэтому проверки на клиенте полезны для удобства и помогают избежать случайных ошибок, но не должны быть единственным механизмом защиты. Если проверка выполняется только на клиенте, на сервер всё равно могут попасть некорректные, недопустимые или вовсе опасные данные. На практике действует простое правило: 〰️на клиенте проверки делают для удобства 〰️на сервере проверки делают для безопасности ✔️Вывод Ограничения на клиенте - это не полноценная защита, а лишь вспомогательная проверка. Всё, что важно для безопасности, должно проверяться на сервере.

Почему случайное число не меняется?
+5
Почему случайное число не меняется?

➡️IDOR - чужие данные по ID Иногда доступ к объекту зависит от одного идентификатора. Например, есть ссылка /order/1642 по ко
➡️IDOR - чужие данные по ID Иногда доступ к объекту зависит от одного идентификатора. Например, есть ссылка /order/1642 по которой пользователь открывает свой заказ. Потом он меняет 1642 на 1643 и вдруг видит уже чужой. 🔺Проблема в том, что идентификатор оказался слишком предсказуемым, а проверка доступа недостаточной или вовсе отсутствующей. Предсказуемые идентификаторы упрощают перебор и открывают доступ к чужим данным. Чаще всего так получают доступ к: 〰️профилям пользователей 〰️заказам 〰️документам 〰️счетам 〰️заявкам Но здесь есть важный момент. Даже если вместо 1642 использовать более сложный и менее очевидный идентификатор, проблема не исчезает. ✔️Безопасность здесь зависит не от того, насколько сложно угадать идентификатор, а в первую очередь от проверки прав доступа к объекту. Если сервер смотрит только на то, существует ли объект, но не проверяет, кто именно запрашивает доступ, этого уже достаточно для инцидента. Поэтому, если система принимает идентификаторы объектов из запроса, стоит проверить: 〰️можно ли перебирать идентификаторы объектов 〰️есть ли для каждого запроса проверка доступа к нужному объекту 😎Иногда хорошая проверка начинается с простого вопроса: "Что произойдет, если просто поменять ID в запросе?"

➡️Утечка через сравнение строк Как думаете, сколько времени занимает такая проверка? if token == "secret_key": allow_access()
➡️Утечка через сравнение строк Как думаете, сколько времени занимает такая проверка?
if token == "secret_key":
    allow_access()
Почти за мгновение. Но иногда эти миллисекунды могут выдать секрет. 🔍В чем дело Во многих реализациях строки сравниваются посимвольно. Алгоритм обычно выглядит так: 1) Сравнить первый символ 2) Если совпал - второй 3) Если совпал второй - третий И так далее Если символ не совпал, тогда сравнение заканчивается. 📝Где появляется проблема Предположим секретный токен A9F4K2 Если атакующий отправит BXXXX Сравнение закончится на первом символе. Если отправить AXXXX, то проверка пройдет чуть дальше. В результате время выполнения будет немного отличаться. Если отправить много запросов и измерять время ответа, можно постепенно угадывать символы по одному. ✔️Как решают проблему Используют сравнение за константное время. Алгоритм сравнивает все символы, даже если первый уже не совпал. Для этого во многих языках есть специальные функции, например: GO
subtle.ConstantTimeCompare(a, b)
JavaScript
crypto.timingSafeEqual(a, b)
😎Как часто вы видели проверки секретов через обычное ==?

📌Некоторые вещи про безопасность были сказаны задолго до SSDLC
+4
📌Некоторые вещи про безопасность были сказаны задолго до SSDLC

➡️Магические числа в коде Магическое число - это любое числовое значение, которое прямо вставлено в код без пояснения, в чём
➡️Магические числа в коде Магическое число - это любое числовое значение, которое прямо вставлено в код без пояснения, в чём его смысл и почему выбрано именно оно. Проще говоря число есть, а что оно означает не ясно. Представьте такой код⬇️
if ((flags & 64) != 0 && status == 3) {
    mode = 12;
}
Что означает 64? Что такое 3? Почему 12? Разработчику, который видит такой код впервые, остаётся только догадываться, что именно означают эти значения. А вероятность неверной интерпретации достаточно высока. 📝Почему это плохо? 1. Код становится труднее читать Приходится догадываться, что имел автор в виду 2. Поддержка усложняется Если такое число используется в нескольких местах, при изменении логики придётся искать и менять его везде. 3. Возрастает вероятность ошибок Одно и то же число может использоваться с разным назначением, из-за чего легко изменить не тот участок кода и нарушить логику. 🧷 Кстати, в ГОСТ Р 56939-2024 использование магических чисел прямо приводится как пример запрещённой практики при формировании правил безопасного кодирования. 👍 Как лучше делать? Использовать понятные именованные значения, чтобы из самого кода было ясно, что именно проверяется или присваивается⬇️
const int FLAG_ENCRYPTED = 0x40;
const int STATUS_AUTHORIZED = 3;
const int MODE_SECURE = 12;

if ((flags & FLAG_ENCRYPTED) != 0 && status == STATUS_AUTHORIZED) {
    mode = MODE_SECURE;
}
Теперь код читается так: "Если установлен флаг шифрования и статус авторизован, то установить безопасный режим" ✔️Число должно объяснять себя через имя, а не через догадки разработчика.

👆Червь Морриса
+4
👆Червь Морриса

0.1 + 0.2 ≠ 0.3. Как тогда правильно сравнивать числа ⁉️ В прошлом посте мы разобрали, что числа с плавающей точкой хранятся
0.1 + 0.2 ≠ 0.3. Как тогда правильно сравнивать числа ⁉️ В прошлом посте мы разобрали, что числа с плавающей точкой хранятся по стандарту IEEE 754, и многие десятичные дроби представляются в памяти приближённо. 🔍 Как правильно сравнивать? Поскольку вычисления с числами с плавающей точкой содержат небольшую погрешность, можно использовать проверку, что разница между числами очень мала: abs(a - b) < 1e-9 👍 Встроенное решение Во многих языках программирования есть встроенные средства для корректного сравнения чисел с плавающей точкой. В качестве примера рассмотрим Python:
import math math.isclose(a, b)
Эта функция предназначена для сравнения чисел с плавающей точкой и проверяет условие:
abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)
Чтобы формула не выглядела пугающе, разберём её по шагам:
1. Сначала вычисляется большее по модулю число из двух. Это нужно, чтобы относительная погрешность считалась от большего значения. 2. Это число умножается на коэффициент rel_tol. Так вычисляется допустимая относительная погрешность. 3. Затем выбирается большее из двух значений: 〰️Относительная погрешность 〰️Абсолютная погрешность 4. И только после этого abs(a-b) сравнивается с полученным порогом.
По умолчанию используются следующие значения:
rel_tol = 1e-9 abs_tol = 0.0
Иногда достаточно понять одну маленькую особенность и многое становится на свои места.