1. Использование устаревших и небезопасных примитивов. Невозможность смены в новых версиях ПО, без потери прямой совместимости, устаревшего примитива на другой или смены формата файла.
1.1. Использование средств для обеспечения совместимости между версиями, которые позволяют понижать версию протокола с безопасной на небезопасную. То есть отсутствие принудительного использования более новой версии или возможность отключить такое принудительное использование.
1.2. Отсутствие обязательного применения криптографии или возможность снизить её защищённость или отказаться от неё, в том числе, в результате ошибок, ручных или автоматических переключений на нешифрованный канал при невозможности создать шифрованный и т.п.
В том числе, возможность подключения по http, если недоступен https (неиспользование HSTS).
1.3. Непредусмотренная возможность смены примитива (при потере его стойкости) или его запоздалая замена при том, что схема шифрования не обладает запасом на много лет вперёд. Либо использование одного длинного параметра, но другого короткого (в шифре "Магма" ключ 256 битов, но блок всего 64 бита). Запас шифров, по возможности, должен рассчитываться по схеме 80 битов в 1980-ом году + 1бит на 1 год или 2 бита на 1 год.
Примитивы должны выводиться из использования как минимум за 10 лет до предполагаемого конца использования (для того, чтобы старые версии программ ещё могли шифровать данные и выводится постепенно). Например, для шифрования с обеспечением секретности до 2050-ого года и требованием к давности текста 20 лет (срок, за который шифротекст всё ещё не расшифруют), мы должны использовать 2050-1980=70, 70+80=150 битов ключевой информации минимум и выводить шифры из использования максимум в 2020-ом году (2050-20 лет срока давности=2030 и ещё 10 лет запаса на вывод). Таким образом, 150 битов непригодны к использованию ещё в 2020-ом году.
Учитывая возможность наличия коллизионных атак, стойкость лучше удваивать.
Для шифра в 384 бита длинной делим стойкость на 2. 192 бита. 192 - 80 + 1980 = 2092. Это год, когда шифр станет не стойким (разумеется, очень приблизительно). Берём 10 лет запаса, то в 2080-ом мы должны выводить такие шифры из эксплуатации.
2. Использование только одного примитива, использование одного хеша на один примитив вместо двух (если длина не имеет значения). То есть доверие только одному криптографическому примитиву (особенно, если он не самый стойкий и есть аналоги).
3. Отсутствие закрытия двумя схемами шифрования (гаммированием с обратной связью и гаммированием, например). Неиспользование открытого текста как дополнительной синхропосылки (дополнительного рандомизатора шифротекста).
3.1. Верное решение - закрыть открытый текст как минимум двумя схемами шифрования, причём обе схемы должны быть с разными ключами. Вообще, любой проход должен быть со своим ключом, который более нигде не используется.
4. Отсутствие учёта интерактивности в криптографии и возможности повторной отсылки изменённых сообщений или возможности проведения атаки с заданным открытым или шифротекстом.
5. Нарушение правил проектирования:
5.1. В каждом массиве данных, при обработке этого массива мы должны знать:
1) Достигли ли мы конца массива, логического блока на этом байте
2) Как интерпретировать следующий байт: он должен быть интерпретирован однозначно (то есть не быть, например, либо дополнением, либо значением, в зависимости от его собственного значения).
3) Если злоумышленник изменил массив хотя бы в одном бите, мы должны это заметить без выхода за пределы массива и, желательно, не показывая, что мы заметили это слишком рано (чтобы исключить тайминг-атаки).
4) Интерпретация одного и того же массива разными прикладными алгоритмами должна быть одна и та же. Мягкое отношение к ошибкам (их игнорирование) не допускается.
5) Любое различие в семантике ввода должно быть формально отражено на входе алгоритма или изменением алгоритма без возможности успешного применения другого алгоритма перебором и т.п.
Например, размер вводимых данных должен быть однозначно идентифицирован, ключ, модификаторы и т.п. должны быть однозначно идентифицированы и разделены (грубо говоря, если ключ на байт меньше, а синхропосылка на байт больше - это должно выводить разные результаты, даже если они конкатенируются и вводятся через один и тот же ввод).
В качестве последствий нарушения правила 5.1, см. Padding Oracle
5.2. Перед шифрованием, в каждом массиве данных должна быть:
1) по возможности, нарушена структура (злоумышленнику должно быть неизвестно, где находится шифрованный байт ни относительно начала массива, ни относительно других байтов, даже если он знает, что именно было зашифрованно; если злоумышленник изменяет открытый текст, то ему не должны быть известны различия в перемешанном тексте, даже неизвестно, какой именно бит поменяется и сколько именно битов поменяются [кроме, быть может, того, что криптостойко поменяются с вероятностью 1/2 все биты, следующие за этим по шифротексту])
2) вставлен шум (в том числе, если есть хеши, желательно хешировать ими и шум, см. 4.1)
3) Массив открытого текста должен быть выровнен по длине. Если это канал связи, то шум должен добавляться так, чтобы скрывать точный траффик по сети (чтобы нельзя было понять, сколько именно данных передаются прямо сейчас, а где - пауза между данными).
4) Не должно быть некриптостойких зависимостей между данными внутри одного массива (скажем, crc32 или просто известные длины блоков внутри файлов) или они должны быть криптостойко закрыты так, чтобы не только данные были закрыты, но и закрыты (удалены) зависимости. То есть если есть зависимость между битами открытого текста, то между битами шифротекста любая зависимость не должна устанавливаться или должна быть криптостойкой (должна быть криптостойко разорвана).
То есть должно быть устранено наличие логических или иных математических взаимозависимостей в коде (если они не развязаны криптографией надлежащей стойкости, аналогичной используемой). Для устранения можно применять разделение на разные блоки шифрования (если схема достаточно хорошо развязывает разные блоки, например, гаммирование с обратной связью через губку) и зашумление введением шума и перестановками.
При шифровании последовательно по слоям, нужно использовать сначала более сильные алгоритмы, а затем уже более слабые (если они вообще используются). В том числе, зашифрованный хеш должен быть не менее стоек, чем шифрующий его алгоритм.
4.1) Незашифрованный хеш открытого текста, вычисленный без ключа, может быть использован злоумышленником для угадывания открытого текста путём перебора. Незашифрованный хеш должен быть от шифротекста (с иным ключом), а хеш от открытого текста должен быть зашифрован. Кроме этого, хеш лучше брать с каким-либо ключом, чтобы даже расшифрованный хеш злоумышленник не мог проверить (если хеш берётся не в один проход с гаммой, то хеш должен быть на отдельном ключе, см. пункт 3.1).
5.3. Для того, чтобы злоумышленнику было труднее проверить, верно ли он подобрал пароль/ключ, его нужно заставить выполнить как можно больше операций. Например, он должен расшифровать весь текст перед тем, как проверить хеш текста. Не должно быть зашифрованных контрольных сумм паролей и прочее для упрощения такой проверки.
5.4. Нужно предполагать как можно большие возможности злоумышленника, если это упрощает анализ и не приводит к серьёзным дополнительным издержкам.
В частности, можно предполагать, что злоумышленник может выполнить какие-то частные атаки на алгоритмы шифрования. Например, по двум хешам с одним ключом понять, что эти хеши на одном ключе и таким образом установить, что два файла зашифрованны одним и тем же человеком.
Почти всегда злоумышленник может:
1) Осуществить налёт на объект и временно завладеть устройством или похитить его
2) Применить терморектальный криптоанализ
3) Скрытно проникнуть в слабозащищённые объекты, скрытно украсть, а затем вернуть устройство и т.п.
4) Осуществить атаки по ПЭМИН и другие не программные атаки, даже если они кажутся сложными или дорогими (что не всегда так)
5) Воздействовать на канал связи: удалять сообщения, изменять их, посылать повторно те же или изменённые и даже вынудить обманом послать сообщение оператора системы. Поэтому, атака с заданным открытым текстом вполне возможна хоть в каком-либо варианте.
6) Если он имеет из другого источника эталонные файлы, он может сравнить длину шифротекста с длиной шифротекста эталонного файла даже не зная правильного ключа
7) Злоумышленник может быть похожим на действия иностранных разведок, ОПГ, террористов либо наоборот, действия гос. органов. Если можно себе представить и реализовать защиту в соотв. ситуациях, то её стоит делать. Т.к. в промышленном шпионаже и обычной жизни ситуации более разносторонние и атаки могут происходить по совершенно неожиданным сценариям и векторам. Поэтому учёт нетипичных сценариев может помочь закрыть и эти неожиданные каналы.
Также может быть:
1) Случайный отказ оборудования
2) Небрежность со стороны оператора криптграфической системы (от усталости, спешки и т.п.)
3) Забытые оператором пароли и пин-коды
5.5. По возможности, необходимо пытаться обеспечить защиту от компрометации одних шифротекстов, если скомпрометированны другие шифротексты или ключи.
6. Невыровненность по времени или потреблению ресурсов (тайминг-атаки). В том числе, невыровненность по времени при выдаче сообщений об ошибках (padding oracle).
7. Отсутствие комментариев к проектным решениям и решениям в коде: почему сделано именно так.
Отсутствие указаний на небезопасность вызываемых функций.
Смешивание в одном API функций, идущих на разных уровнях абстракции, что может запутать программиста.
Смешивание в одном API безопасных и небезопасных функции без указания, что и как использовать, и без указания в наименованиях на небезопасность.
8. Отсутствие должной энтропии для инициализации алгоритмов, в том числе, на момент включения устройства (то есть использование энтропии в системе, где её мало и нет специального генератора энтропии). Это означает, что генерация случайного ключа или непредсказуемой синхропосылки невозможна: разные устройства будут генерировать, с высокой вероятностью (например, 1%) одни и те же ключи.
9. Использование криптографически сгенерированных идентификаторов (тоукенов) или иных объектов без запаса по длине. Запас по длине должен быть всегда, когда это возможно.
В том числе, в случае, если алгоритм генерации будет взломан, дополнительная длина объектов может затруднить их взлом. Аналогично, при плохой энтропии, приходящейся на один байт: большее количество байтов даст большую энтропию.
10. Разработчик часто вообще не защищает то, что можно защитить, потому что система имеет низкую ценность.
Реально, всегда необходимо иметь защиту на случай ошибки приоритизации или ошибки оценки рисков. То есть защищать (по возможности) надо даже то, что нам кажется не нужно защищать. Если что-то можно защитить, затруднить атаку, и цена этого мала, нужно это сделать (если это не создаёт риски усложнения и появления ошибок).
Также, желательно, не только использовать основные меры защиты, помогающие предотвратить утечку, но и дополнительные, которые затрудняют действия атакующих. Если эти приёмы защиты не слишком сложны и не привнесут в программу дополнительных потенциальных дефектов и т.п.
11. Переоценка возможностей пользователя и плохо обоснованные ограничения.
Например, ограничение на длину пароля в 32 или 64 символа не позволяет человеку запомнить длинный пароль с низкой энтропией на каждый символ.
В то время как длинный пароль абсолютно ничем не вредит.
12. Неиспользование возможностей рандомизации.
Желательно использовать содержимое открытого текста для дополнительной рандомизации.
Например, шифрование блока хешем открытого текста перед открытым текстом в режиме CBC даст дополнительную рандомизацию для этого режима.
Для режима CBC часто могут не использовать синхропосылку, хотя она там есть, что позволяет сравнить два шифротекста на равенство их начал; поэтому, синхропосылка должна использоваться в обязательном порядке.
13. Неучёт косвенных или перспективных данных по нестойкости, сговору и т.п.
В том числе, некоторые действия субъектов могут быть интерпретированы как сотрудничество или прикрытие закладок. Но могут быть объяснены и какими-то другими обстоятельствами и логикой.
Однако, возможность объяснения данных, указывающих на сговор с одной стороны, другим способом никак не отрицает то, что сговор действительно может быть.
Вообще, до некоторой степени, если не доказано иное, то опасность существует.
14. Допущение оптимизаций с нарушением логики. Например, Intel Meltdown.
Сначала мы должны проверить права на доступ, и только затем начинать этот доступ. Если прав нет, состояние системы никак не должно измениться.
15. Оказание давления на программистов, не связанного с безопасностью: сроки, быстрота исполнения программы и т.п.
Программисты должны стремиться к безопасной, совершенной с технической и логической точки зрения системе.
Она должна быть простой, понятной и интуитивно нравится программистам.
Если есть хоть какие-то сомнения в логике работы (даже интуитивные сомнения, нелогичные, чувственные), сомнения должны перевесить любые другие доводы.
Например, атака Meltdown была бы невозможна, если бы микропроцессор не был бы оптимизирован так, что выполнял те команды, которые он не должен был выполнять (хотя потом и делал вид, что их не выполнял).
Например, использование одной синхропосылки для разных ключей при шифровании одного и того же сообщения может повлечь за собой меньшую стойкость зашифрованной информации (например, при совпадении частей ключей они будут похожи).
16. Отсылка зашифрованных данных туда, куда их не нужно отсылать с целью повышения производительности, масштабируемости и т.п.
Если человеку не нужно знать данных и работать с ними, то он не должен иметь к ним доступ даже в зашифрованном виде, т.к. иначе мы даём ему возможность атаковать криптографию.
17. Нарушение изначальной семантики проектирования. Смешивание технологической семантики с криптографической, с семантикой процессов, которые происходят во внешнем мире. Слишком узкие предположения относительно конкретного использования, основанные на тех применениях, что уже есть.
Всегда лучше использовать более общие модели, если это возможно.
Более частные модели хороши своей простотой, однако баланс между простотой и безопасностью может быть разный. Если есть возможность обеспечить одновременно простоту и безопасность более общей модели, лучше использовать именно её.
Смешивание операций безопасности с чем-то ещё. Сначала надо завершить безопасность, а потом уже переходить к другим процедурам.
17.1. Атака BIAS на Bluetooth.
Устройства разделяются на ведомые и ведущие. Аутентификация, почему-то, происходит только ведомого устройства. Однако, ведомое устройство, в любой момент времени, может сказать, что оно теперь - ведущее, и избежать таким образом аутентификации.
https://threatpost.com/bluetooth-bugs-impersonation-devices/155886/
То есть если устройства заранее одноранговые, то ошибка состоит в том, что их аутентификация тоже должна быть одноранговой - оба устройства должны быть аутентифицированны. В этом нарушение семнатики: устройства одноранговые, а проверка такая, как будто одно устройство имеет приоритет над вторым.
18. Использование системных или стандартных компонентов, от которых зависит безопасность.
Системные и стандартные компоненты не должны использоваться.
Системные и стандартные компоненты могут измениться, что может повлечь за собой непредсказуемое поведение программы.
Неизвестно, как именно эти компоненты работают, что может послужить поводом для использования недокументированных (или неизвестных пользователю) возможностей и ошибок
В такие компоненты можно внести баги
Разные системы могут реализовывать компоненты по разному.
Кроме этого, однородность работы под разными системами также упрощает анализ программы, в том числе, криптоанализ.
19. Для избежания ошибок, необходимо проверить,
19.1. что числа, которые не должны быть связаны друг с другом, не связаны друг с другом. Например, что два ключа RSA (открытый и закрытый) сгенерированы от разных случайных входов. Ключи не должны идти последовательно друг за другом.
19.2. Что время выполнения программы не зависит от ключевой информации.
19.3. Что все числа, которые должны быть связаны друг с другом, связаны друг с другом. При этом, используются все биты каждого числа (то есть при изменении только одного бита результат меняется, какой бы бит входа мы не изменили)
19.4. Случайные данные действительно случайны. Синхропосылки гарантированно обрабатываются один раз и на их значение никто не может повлиять (отсутствует навязывание значения синхропосылки со стороны злоумышленника).
19.5. числа, которые должны быть развязаны между собой n битами шифрования, развязаны именно ими или большим количеством и их нельзя угадать. Пароли/pin-коды достаточно стойкие и их нельзя подобрать. Что мешает злоумышленнику вторгнуться и сгенерировать синхропосылку или изменить что-либо?
19.6. Если есть возможность, то схемы генерации ключей должны быть такими, чтобы выводить информации меньше, чем их внутреннее криптографическое состояние. То есть, чтобы для восстановления ключа не хватало данных, даже если будет взломан алгоритм шифрования.
19.7. Для исключения возможности использования радужных таблиц при переборе паролей, стоит дополнять пароли модификаторами (солью). Соль увеличивает длину подбираемого пароля с точки зрения радужной таблицы.
20. При использовании менее стойких алгоритмов для реализации повышенной стойкости, неверно брать 100% битов выхода менее стойкого алгоритма. Эти биты зависимы друг от друга на n битов стойкости, когда нужно, например, 2*n.
Поэтому, необходимо брать n/k битов с каждого выхода нестойкого алгоритма, не более (где k - отношение стойкости более стойкого алгоритма к менее стойкому алгоритму).
21. При разработке систем шифрования нет учёта угрозы того, что злоумышленник подтвердит подлинность документа. То есть хеши секретных документов не защищаются. Похищенные секретные документы снабжены цифровой подписью и, следовательно, их подлинность подтверждена.
21.1. Например, противник захватил заложника и требует передачи ему секретного документа, хеш которого известен противнику.
22.0. Отсутствие в модели угроз "интимных" атак (подсматривание паролей супругом, находящимся рядом) и атак методом кнута и паяльника.
22.1. Отсутствие в модели угроз халатности/необученности одного из пользователей криптографического продукта (нестойкий пароль для шифрования, забытые операции). В том числе, использование других продуктов шифрованя.
Здесь модель также должна учитывать вопросы обеспечения совместимости: откат на использование предыдущих версий также должен рассматриваться как угроза.
23. Вывод подробных сообщений об ошибках (например, в атаке Padding Oracle). Они могут содержать слишком много информации. Ошибки должны быть сокрыты в логах, а вывод пользователю может содержать номер лог-записи.
Доп. литература:
https://owasp.org/Top10/A02_2021-Cryptographic_Failures/
ASVS 4.0 (github)Шпаргалки ASVS