Огляд безпеки Nym
Аудит безпеки компонентів Nym core
Вступ
В липні 2021 року Nym пройшов аудит безпеки у Jean-Philippe Aumasson, відомого експерта з безпеки. Аудит мав на меті виявлення потенційних вразливостей у кодовій базі Nym, зосереджуючи увагу на криптографії, безпеці коду та безпеці протоколів. Огляд мав на меті забезпечити цілісність і надійність системи, охоплюючи ключові аспекти її архітектури та реалізації. Ви можете побачити повний звіт про аудит тут.
Підсумок аудиту
Аудит відбувався влітку 2021 року. Сфера аудиту охоплювала кілька репозиторіїв проєкту Nym, зокрема:
- Головний репозиторій Nym: nymtech/nym, який реалізує сервіси мікснодів, шлюзів та валідаторів.
- Формат пакета Sphinx Mixnet: nymtech/sphinx, використовується вузлами змішування.
- Протокол підпису Coconut Threshold Blind: nymtech/coconut, використовується для видачі облікових даних.
Аудит полягав у перегляді останньої версії коду в гілці розробки, яка регулярно оновлювалася через швидкий розвиток проєкту. Команда Nym надала JP Aumasson повний доступ до кодової бази, детальних специфікацій проекту, дослідницьких статей та супутньої документації.
Ключові сфери аудиту
Аудит зосередився на трьох основних областях: безпеці коду, криптографії та проєктуванні протоколів. Аудитори ретельно перевірили кодову базу Ним, щоб виявити вразливості, шукаючи поширені проблеми, такі як небезпечні патерни кодування та неправильно оброблені помилки. Особлива увага була приділена безпеці пам'яті та уникненню таких проблем, як переповнення цілих чисел.
Криптографічний огляд охоплював широкий спектр основних примітивів, використаних компанією Nym, таких як AES-128-CTR, BLAKE2b, ChaCha, Ed25519 та інші. Метою було забезпечити належну реалізацію цих алгоритмів та перевірити їх стійкість до атак на сторонні канали, неналежного використання параметрів та недоліків у генерації випадковості.
Крім перевірки окремих компонентів, аудит також досліджував протоколи, що визначають основну функціональність Nym. Це включало в себе дослідження формату пакета Sphinx та протоколу сліпого підпису Coconut з пороговим значенням для виявлення будь-яких слабких місць, які можуть загрожувати конфіденційності або безпеці. Огляд зосереджувався на потенційних витоках інформації, що загрожують анонімності користувача, а також на вразливостях, таких як обхід перевірки MAC, атаки на малі підгрупи та недоліки в криптографічних операціях, таких як арифметика BLS12-381 і докази з нульовим розголошенням.
Огляд висновків
Під час аудиту було виявлено дев’ять вразливостей безпеки. Жодна з вразливостей не була оцінена як критична, дві — як високі, одна — як середня, а шість — як низькі. Крім того, було зроблено 17 спостережень, які пропонують рекомендації для подальшого зміцнення мережі Nym. Нижче наведено огляд виправлень, реалізованих для усунення всіх виявлених вразливостей безпеки.
S-SPHX-01: Відсутні валідації ключів (Низький)
Проблема, виявлена в nymtech/sphinx
стосовно недостатньої валідації приватних і публічних ключів, була вирішена шляхом міграції на бібліотеку x25519
, яка за своєю суттю забезпечує дійсність ключів через свій дизайн. Імплементація x25519
гарантує, що приватні ключі коректно обмежуються, що означає, що вони автоматично обмежуються дійсним підмножиною скалярів, усуваючи ризик використання недійсних приватних ключів. Крім того, хоча x25519
не явно валідовує публічні ключі, його реалізація на базі сходинки Монтгомері вбудовано запобігає використанню певних недійсних точок кривої. Це пом'якшує ризик зіткнення з точками на безкінечності або іншими неправильно сформованими відкритими ключами. Крім того, процес обміну ключами забезпечує виявлення та відхилення спільного секрету, що складається лише з нулів, якщо це необхідно. Використовуючи x25519
, ми значно поліпшили верифікацію ключів, зменшивши ризик використання недійсних або неправильно відформатованих ключів у системі. Це ефективно вирішує проблеми, підняті в аудиті щодо валідації ключів.
S-COCO-01: Неровномірний розподіл хешу до скаляра (Низький)
Процес хешування для отримання скаляра у полі BLS12-381 раніше передбачав відображення виходу хеш-функції безпосередньо на елемент скалярного поля. Однак цей підхід запровадив упередження через операцію модульного зменшення (mod p), що може призвести до неуніфікованого розподілу, коли вихідний хеш не співпадає ідеально з простим модулем поля. Щоб вирішити цю проблему, ми замінили існуючу функцію хешування в скалярі на функцію hash_to_field з бібліотеки bls12_381. Ця функція відповідає стандартизованій специфікації перетворення хешу в поле, забезпечуючи рівномірне та неспотворене перетворення виходу хешу в елементи поля. Крім того, протокол zk-Nym, який замінив протокол Coconut, також покладається на цю функцію для своїх хешуючих операцій, забезпечуючи узгодженість і правильність у криптографічних обчисленнях.
S-COCO-02: дозволи на файли ключів keygen-cli (Низький)
Аудитори відзначили, що файли ключів keygen-cli
мають звичайні права доступу, але їм потрібно надати більш обмежені права доступу для кращої безпеки. Ця проблема не вимагала жодних змін, оскільки keygen-cli
використовувався лише на ранніх етапах нашої реалізації Coconut. Він більше не є частиною основного репозиторію Nym і не використовується активно. Оскільки інструмент став застарілим, подальші дії щодо його прав доступу не були потрібні.
S-CRYP-01: Потенційне повторне використання IV потокового шифру (Високий)
Проблема стосується функції, яка шифрує дані за допомогою вектора ініціалізації (IV). Якщо IV не надано, функція за замовчуванням використовує нульовий IV, що може призвести до повторного використання IV. Цю проблему було вирішено, додавши протокол AES-GCM-SIV під час реєстрації. Щоб запобігти атакам пониження версії, ми видалили можливість використовувати застарілий ключ AES-128-CTR для зв'язку між клієнтом і шлюзом. Якщо як клієнт, так і шлюз оновлені, вони завжди генеруватимуть випадковий, ненульовий IV.
S-PROT-01: Потенційне подвійне використання облікового запису (Високий)
Аудитори помітили, що переглянута версія Coconut не містила механізму виявлення подвійного витрачання, що могло призвести до того, що кілька шлюзів неправильно валидаціювали виріб як невикористаний одночасно. Однак контракт на пропускну спроможність Coconut пізніше було оновлено для відстеження використання облікових даних шляхом збереження стану в блокчейні, що вирішує цю проблему. Крім того, Кокос з тих пір був замінений на протокол zk-nyms, який включає вбудовану функціональність виявлення подвоєння витрат.
S-NYM-01: Залежності з відомими вразливостями (Середня)
Аудитори виявили, що кілька компонентів проєкту Nym покладалися на старі версії залежностей з відомими вразливостями безпеки. Наприклад, репозиторій Sphinx використовував ненадійну версію generic-array
, основний репозиторій Nym спирався на застарілий tokio
, а клієнт Nym мав кілька пакетів з відомими проблемами безпеки, деякі з яких, здавалося, могли бути використані у контексті Nym. Відповідно до рекомендацій аудиторів, ми регулярно оновлювали залежності. Ми тепер активно керуємо нашими залежностями за допомогою Dependabot
, який постійно моніторить і автоматично виявляє застарілі або вразливі пакети в наших репозиторіях. Подивіться на виправлення Dependabot, які постійно застосовуються у нашому репозиторії.
S-NYM-02: Помилка розшифровки не оброблена (Низький)
Проблема, яка була виявлена в коді, виникає у функції recover_identifier
в nym/common/nymsphinx/acknowledgments/identifier.rs
, де збої шифрування, такі як некоректні параметри, не обробляються належним чином. Це може призвести до паніки або інших небезпечних станів. Схожа проблема існує у функції recover_plaintext
в nym/common/nymsphinx/src/receiver.rs
. Невиконання управління помилками декодування може призвести до того, що система потрапить в нестабільний або небезпечний стан. Після ретельного перегляду функціональностей, ми дійшли висновку, що перший приклад, наведенй у recover_identifier
, не є проблемою. Неможливо надати некоректні параметри, оскільки все параметризовано за допомогою AckEncryptionAlgorithm
(link), отже, будь-які некоректні значення будуть виявлені під час компіляції.
Другий випадок, який вони згадали, recover_plaintext
, більше не існує. Однак код, який його замінив, recover_plaintext_from_regular_packet
, мав теоретично можливий випадок збою, якщо ми будемо змінювати деякі параметри на незвичайні значення. Ми вирішили цю проблему, додавши належну обробку помилок, щоб забезпечити стабільність системи, навіть у граничних випадках.
S-NYM-03: Паніка в генерації фрагментів ID (Низький)
Код, що використовується для випадкового генерування нових фрагментів ID, вибирає випадкове значення i32
і бере його абсолютне значення. Однак, такий підхід може призвести до паніки у випадках, коли випадково обране значення є i32::MIN
, оскільки його абсолютне значення не може бути представлене в межах i32
. Це призводить до помилки «спроба заперечити з переповненням» через обмеження кодування 2-доповнення.
Ми погоджуємося з тим, що оцінка серйозності встановлена занадто низько для цієї проблеми, оскільки ймовірність зіткнення з цим випадком приблизно 1 з 4 мільярдів. Однак ми вирішили цю проблему, впровадивши рекомендоване виправлення аудитора, щоб запобігти потенційним панікам і несподіваним збоям, особливо коли мільйони користувачів генерують тисячі ідентифікаторів фрагментів.
S-NYM-04: Мнемоніка не обнулена (Низький)
Виявлена проблема підкреслила, що мнемоніка BIP39, використана для з'єднання з сервісом nymd, не знищувалася після використання, що призводило до збереження декількох копій мнемоніки в пам'яті. Це збільшило ризик вразливості, оскільки мнемоніки легше ідентифікуються в пам'яті порівняно з сирими криптографічними ключами. Для вирішення цього питання ми впровадили кілька мітогенацій. У компонентах Rust ми інтегрували crate zeroize, щоб забезпечити безпечне очищення пам'яті, що містить мнемоніку, щойно вона виходить із області видимості. Оскільки JavaScript є мовою з автоматичним управлінням пам'яттю і не забезпечує прямий контроль над звільненням пам'яті, ми обрали інший підхід для зменшення впливу в середовищі виконання JavaScript. Зокрема, ми модифікували систему так, що виконання JavaScript завершується, як тільки мнемонічний код було передано до шару Rust. Це забезпечує очищення всіх екземплярів мнемонічного у JavaScript пам'яті під час завершення роботи. Мнемоніка передається в Rust якомога швидше, зменшуючи її витривалість у JavaScript. Оскільки в Rust zeroize
забезпечує, що всі примірники мнемоніки надійно стираються, як тільки вони більше не потрібні. Завдяки цим змінам ми значно мінімізували присутність мнемоніки в пам'яті, зменшуючи ризик витоку та забезпечуючи надійне управління і видалення чутливих даних.
Останні слова
Ми хочемо подякувати JP Aumasson за його досвід і відданість протягом цього аудитного процесу. Ми також висловлюємо вдячність за співпрацю та професіоналізм, проявлені під час планування та виконання аудиту. Наша безперервна відданість безпеці залишається пріоритетом, і ми з нетерпінням чекаємо на продовження партнерства з експертами з безпеки для підтримки найвищих стандартів для нашої екосистеми.