• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Стиллер, не воруй!

XSSBot

Форумный бот
Пользователь
Регистрация
31.12.2005
Сообщения
1 473
Реакции
898
Автор @Захотел-остаться-анонимным
Статья написана для
Конкурса статей #10


szulik.jpg


Ребятушки, предлагаю обсудить один вопрос в житии всяческих Бенов Стиллеров, который всегда казался мне очень странным. А именно: то и дело всплывает какой-то недовольный господин, который купил себе уютненький (как ему казалось) стиллер Х, но теперь обвиняет партнерку стиллера X в том, что они пиздят его драгоценные логи. Или, например, сломали панель стиллера Х, из-за чего все логи утекли и теперь путешествуют по интернетам. Очередное сравнительно недавнее обсуждение этого вдохновило меня на написание этой статьи.

Оставим за скобками всю морально-этическую составляющую использования стиллеров, философские вопросы доверия друг-другу в наше непростое время, а также то, что процесс спизжевания логов может быть основной бизнес моделью партнерки стиллера Х, и обратимся к технической стороне вопроса. Дело в том, что понимание криптографии, как таковой, и честная реализация некоторых ее подходов может практически полностью убрать из уравнения опасность спизженных логов.


Немного теории


Начнем с небольшого количества теории, рассказанной простым пацанским языком, а затем перейдем к практике. В далеком 1976 году на Национальной Компьютерной Конференции очень смышлёными дядьками Уитфилдом Диффи и Мартином Хеллманом была выдвинута судьбоносная для криптографии идея о шифровании с открытыми ключами. До этого безопасная передача ключей шифрования по открытым каналам связи была весьма проблематична, поскольку ключ мог быть перехвачен, а все данные расшифрованы с его помощью.

Алгоритмы шифрования можно разделить по принципу использования ключей на симметричные и асимметричные. Первые для шифрования и расшифровки данных используют один и тот же ключ. Да-да, именно тот один и тот же ключ, который может быть перехвачен. Асимметричные алгоритмы с другой стороны используют ключевую пару: так называемый "публичный ключ" для шифрования и "приватный ключ" для расшифровки данных. Таким образом, мисс Алиса говорит всем: "так, челики, вот вам мой публичный ключ, пишите мне свои секретные сообщения", но приватный ключ держит у себя и никому не показывает. Мистер Боб шифрует свои секретики на публичном ключе мисс Алисы и посылает ей шифр-данные. Мисс Алиса расшифровывает секретики на своем приватном ключе, и никакая ебучая Ева не может узнать секретики, которые Боб переслал Алисе, пока у нее нет доступа к приватному ключу Алисы. В обратную сторону уже Боб может сделать себе публичный и приватный ключи и чувствовать безопасность входящих от Алисы или кого-то другого секретиков. Если вам когда-либо было интересно, почему в криптографии обычно все объясняют с участием Алисы, Боба и Евы, читайте тут, мы традиций не нарушаем.

Можно условно сказать, что в мире асимметричных алгоритмов шифрования существуют только RSA (Ривест, Шамир, Адлеман) и ECC (эллиптические кривые). Слава Летающему Макаронному Монстру, нам с вами не нужно особо много шарить в математике, чтобы использовать эти алгоритмы, вдаваться в подробности о том, как они работают, мы конечно же не будем.

Вроде бы, концепция весьма годная: шифровать сообщения Алисе может кто угодно, а расшифровать их может только сама Алиса. Но почему же тогда асимметричные шифры давным давно не выпилили симметричные из мира практической криптографии. Дело в том, что асимметричные шифры слишком медленные (помимо некоторых других проблем), чтобы их использовать для большого количества данных. Но! Комбинируя асимметричные и симметричные алгоритмы мы можем получить преимущества обоих типов в одном.

Каким же образом их можно объединить? Да очень просто: генерировать ключи симметричного шифрования на новый сеанс связи, а для обмена этими ключами пользоваться асимметричным алгоритмом. Я понимаю, что многим из вас тут я не открыл Америку (сорян, дропами зиродеев не пахнет), тк такой подход используется просто повсеместно в сети Интернет и много где еще. Но давайте посмотрим, как это можно использовать в среде Бенов Стиллеров.


Смоделируем ситуацию


Допустим у нас есть некий новый клиент, который решил купить себе стиллер, будем его так и называть - "Клиент". Так вот, Клиент приходит к Продавцу и говорит, мол "давай мне мой билд". Продавец выдает ему некую тулзу, с помощью которой Клиент генерирует себе ключевую пару какого-то асимметричного алгоритма, допустим RSA. В качестве такой тулзы можно использовать стороннюю программу, типа OpenSSL, или написать кастомную тулзу, но важно, чтобы она поставлялась без обфускации и морфинга, или вообще с исходными кодами в придачу, чтобы Клиент при необходимости мог провести ее аудит (и убедиться, что его нигде не наёбывают).

Публичный ключ Клиент отправляет Продавцу, а приватный хранит у себя и никому не дает. Продавец вшивает публичный ключ Клиента в новый билд Стиллера, который он передает Клиенту. Непосредственно в коде Стиллера после сборки каждого нового лога происходит следующее. Сначала генерируется псевдослучайный ключ для симметрического алгоритма шифрования, допустим AES. Лог зашифровывается с помощью симметричного алгоритма и сгенерированного ранее ключа. Ключ симметричного алгоритма зашифровывается асимметричным алгоритмом с помощью вшитого публичного ключа Клиента и, допустим, дописывается в конец шифр-данных лога.

И получается следующее. Каждый лог зашифрован на каком-то отдельном рандомном ключе симметричного шифрования, который может получить только обладатель приватного ключа, то есть только Клиент (если он, конечно, не был доблоёбом и не давал свой приватный ключ кому ни попадя). Продавец может собирать у себя в панели такие шифр-контейнеры с логами клиентов, при этом ни сам Продавец, ни тот сторонний кулхацкер, который каким-то образом ломанул панель, не сможет эти крипто-контейнеры расшифровать, так как приватные ключи находятся только у Клиентов. Клиенты же скачивают свои логи и расшифровывают их у себя локально с помощью своих приватных ключей.

У такого подхода, безусловно, есть свои недостатки. Например, если Клиент внезапно проебал где-то свой ключ, то все свои логи он тоже уже не сможет расшифровать. Или, например, если особо хитро-выебанный Продавец будет шифровать симметричный ключ не только на ключе Клиента, но и на каком-то своем, и без палева дописывать его к шифр-данным. Или же отбрасывать два разных шифр-контейнера: для Клиента и для Продавца. В целом, эти ситуации при наличии достаточной квалификации можно проверить (например, на предмет того, что в шифр-данных присутствуют только зашифрованные симметричным алгоритмом логи и одна версия зашифрованного асимметричным алгоритмом ключа, или что билд не левачит какими-то дополнительными даннами). И понятно, что тогда Продавец не сможет отображать логи в красивых таблицах в панели, да и расшифровка паролей и кук на сервере панели станет невозможной. Но суммарно этот подход может быть весьма неплохим в плане повышения уровня доверия Клиентов к Продавцу, а также исключить то, что слитые логи будут путешествовать по Интернетам.


Переходим к практике


Я набросал небольшой пример реализации такого подхода на дотнетах и языке программирования C#. Выбор языка обусловлен тем, что на его примере легко показать реализацию подхода, ведь в дотнет фреймворк с бородатых времен встроен и алгоритм RSA (асимметричный) и алгоритм AES (симметричный). Насколько я помню, какие-то из встроенных классов являются полностью managed-реализацией, то есть реализованы непосредственно на C#, а какие-то являются простой прослойкой поверх CryptoAPI. Разбираться, какие именно какие, я конечно же не стал, да и вообще сравнительно мало пишу на C#, так что заранее прошу прощения, если код не оптимальный. Напишите в комментариях, как бы вы его улучшили, если чего.

И как же без подъёба?... Я знаю, что разработчики публичных и приватных стиллеров на С# очень любят друг у друга (ну скажем) "заимствовать" код, поэтому реализация на языке C# для них будет привычнее, штоль. Ей богу, как только я вижу один и тот же пресловутый класс SqLiteHandler, который сначала дизассемблировали из VB.NET кода давным давно, а потом растащили просто по всем стиллерам, мне хочется выколоть себе глаза...

Для начала рассмотрим генерацию ключей. Один из классов в дотнете, который реализует RSA называется RSACryptoServiceProvider. Если ему в конструктор передать размер ключа в битах, то он сгенерирует новую ключевую пару. Хранение RSA ключей в нем сделано довольно странно: в виде XML с BASE64 данными ключей, но окей. Метод для генерации ключей принимает два полных пути на файловой системе, они указывают, куда методу сохранить приватный и публичный ключ соответственно.
C#:
private static void Generate(string path_private, string path_public) {
    using var rsa = new RSACryptoServiceProvider(2048);
    var xml_public = rsa.ToXmlString(false);
    var xml_private = rsa.ToXmlString(true);
   
    File.WriteAllText(path_public, xml_public, Encoding.ASCII);
    File.WriteAllText(path_private, xml_private, Encoding.ASCII);
    Console.WriteLine("Public key was written to {0}", path_public);
    Console.WriteLine("Private key was written to {0}", path_private);
}

Стоит сделать небольшую ремарку о размере RSA ключей. В принципе, я являюсь сторонником мнения, что в данном конкретном случае хватит ключей размером в 2048 бит, но если вы хотите большей "секьюрности", то можно сделать ключи 4096 или 8192 бита. В зависимости от увеличения размера RSA ключа зашифрованный AES ключ и вектор инициализации будет занимать больше места. То есть для ключа размером 2048 бит, размер дополнительных данных для передачи AES ключа составит 256 байт, для 4096 бит - 512 байт (в одном байте 8 бит, ога?).

Теперь представим, что в исходный код Стиллера добавлен следующий метод для шифрования массива байт, который был получен, допустим, из заранее созданного ZIP-архива с новыми логами. Метод принимает публичный ключ Клиента и массив данных, которые нужно Клиенту зашифровать. Сначала мы инициализируем алгоритмы RSA и AES, алгоритму RSA подпихиваем публичный ключ Клиента.

При инициализации алгоритма AES происходит генерация симметричного ключа и вектора инициализации, из которых мы формируем буфер с ключевой информацией и зашифровываем его с помощью RSA и публичного ключа Клиента. Второй параметр метода шифрования RSA (установленный в истину) указывает на то, что мы будем использовать OAEP (Optimal Asymmetric Encryption Padding) для выравнивания, в противном случае будет использоваться PKCS#1 v1.5, насколько я понимаю. Вдаваться в подробности о различиях двух этих алгоритмов, наверное, не стоит, ограничимся тем, что в интернетах пишут, что OAEP лучше.

Дальше мы устанавливаем режим алгоритма в CBC (Cipher Block Chaining, то есть режим сцепления блоков), при этом шифрование каждого следующего блока будет зависеть от предыдущего. Таким образом, если в открытых данных вдруг находятся длинные последовательности однотипных или же предсказуемых данных, по шифр-данным это будет понять сложно. Алгоритм AES является блочным, в данном случае шифрование происходит блоками по 16 байт. Если размер данных не кратен размеру блока, то нужно применять выравнивание. В качестве алгоритма выравнивания мы выбираем PKCS7 без особых глубоко-философских на то причин.

Далее мы просто производит шифрование данных алгоритмом AES. В дотнетах принято все делать через потоки данных, наверное, это в целом правильно (для учета случая, когда нужно обработать большое количество данных и не сожрать всю память), но для целей шифрования сравнительно небольшого лога - это не удобно, но окей. Для шифр-данных я сделал отдельный буфер, в который происходит шифрование, затем этот буфер объединяется с зашифрованным алгоритмом RSA ключом симметричного шифрования. Если вам вдруг станет нужно обрабатывать таким образом большие данные, то старайтесь не плодить дополнительных буферов в памяти.
C#:
public static byte[] Encrypt(string public_key, byte[] data) {
    using var rsa = new RSACryptoServiceProvider();
    using var aes = new AesCryptoServiceProvider();
    rsa.FromXmlString(public_key);

    var key_buffer = new byte[48];
    Array.Copy(aes.Key, 0, key_buffer, 0, 32);
    Array.Copy(aes.IV, 0, key_buffer, 32, 16);
    key_buffer = rsa.Encrypt(key_buffer, true);
   
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;

    var mode = CryptoStreamMode.Write;
    using var data_buffer = new MemoryStream();
    using var encryptor = aes.CreateEncryptor();
    using(var crypto_stream = new CryptoStream(data_buffer, encryptor, mode))
    { crypto_stream.Write(data, 0, data.Length); }

    var encrypted_data = data_buffer.ToArray();
    using var encrypted_buffer = new MemoryStream();
    encrypted_buffer.Write(encrypted_data, 0, encrypted_data.Length);
    encrypted_buffer.Write(key_buffer, 0, key_buffer.Length);
   
    return encrypted_buffer.ToArray();
}

У Клиента есть тулза для расшифровки логов и его собственный приватный ключ, в этой самой тулзе реализован следующий метод, который по своей сути является просто зеркальным отражением метода шифрования. Мы разделяем данные на зашифрованные логи и зашифрованный алгоритмом RSA симметричный ключ (с вектором инициализации). В данном случае нам нужно знать, какой размер будет у блока данных зашифрованного симметричного ключа, этот размер можно получить после инициализации RSA через свойство KeySize (возвращается размер в битах, поэтому мы приводим его к байтам). Далее мы расшифровываем AES ключ и вектор инициализации и с его помощью расшифровываем и возвращаем данные. Опять же данный подход не совсем оптимальный для больших данных, но для логов - почему бы нет. Важно отметить, что параметры алгоритмов шифрования, такие как режим и выравнивание, очевидным образом должны быть одинаковые при шифровании и расшифровке.
C#:
public static byte[] Decrypt(string private_key, byte[] data) {
    using var rsa = new RSACryptoServiceProvider();
    using var aes = new AesCryptoServiceProvider();
    rsa.FromXmlString(private_key);
   
    var rsa_length = rsa.KeySize / 8;
    var key_buffer = new byte[rsa_length];
    var data_buffer = new byte[data.Length - rsa_length];
    Array.Copy(data, 0, data_buffer, 0, data.Length - rsa_length);
    Array.Copy(data, data.Length - rsa_length, key_buffer, 0, rsa_length);
    key_buffer = rsa.Decrypt(key_buffer, true);

    var aes_key = new byte[32];
    var aes_iv = new byte[16];
    Array.Copy(key_buffer, 0, aes_key, 0, 32);
    Array.Copy(key_buffer, 32, aes_iv, 0, 16);
   
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;
    aes.Key = aes_key;
    aes.IV = aes_iv;

    var mode = CryptoStreamMode.Read;
    using var decrypted = new MemoryStream();
    using var data_stream = new MemoryStream(data_buffer);
    using var decryptor = aes.CreateDecryptor();
    var crypto_stream = new CryptoStream(data_stream, decryptor, mode);
       
    crypto_stream.CopyTo(decrypted);
    return decrypted.ToArray();
}

Я приложу полный демо-код этого подхода к статье, он должен работать на всех версиях дотнетов от 4.0 до 4.8. Скорее всего он будет работать и на более ранних версиях (если вам такое может быть нужно), но для этого нужно будет заменить вызовы некоторых методов своим кодом (например, метода CopyTo для потоков данных).


Заключение


Итак, мы с вами посмотрели (условно) реализацию старого (как мир) протокола господинов Диффи и Хеллмана применительно к современным стиллерам. Как говорили древние криптографы: "если сударь не хочет, чтобы логи его клиентов спиздили, сударю надобно использовать криптографию с открытыми ключами" (с). Да, у такого подхода есть свои недостатки, которые я предлагаю обсудить в комментариях, но вообще говоря, мне до сих пор не понятно, почему в каждом из стиллеров не применяется что-то такое? Или есть в природе стиллеры, которые так работают (я прост не шарю)? Может быть, все уже привыкли к типичной модели MaaS стиллеров, при которой риск спизженных логов является необходимым злом? В общем, я не знаю, да и не моё это дело по большому счету, но почему бы не обсудить? Пишите в комментариях, что думаете...

Специально для любимого xss.pro.
Автор материала - самый талантливый (в плане написания конкурсных статей) бот в мире XSSBot! (эти ихние американские ЧатыГПТ и китайские ЛЛМки сосац!)
 

Вложения

  • Program.cs.zip
    1.3 КБ · Просмотры: 32
Последнее редактирование модератором:
но вообще говоря, мне до сих пор не понятно, почему в каждом из стиллеров не применяется что-то такое?
Как же не понятно, когда очень даже понятно:

И понятно, что тогда Продавец не сможет отображать логи в красивых таблицах в панели, да и расшифровка паролей и кук на сервере панели станет невозможной.

Оно, конечно, решаемо переносом панели на оборудование Клиента. Однако, это увеличивает порог входа для, собственно, Клиента и усложняет задачу разработки и сохранения своих Know-How для Продавца. Ну и логи сложнее пиздить, да 😺

В общем, сколь бы красивой ни была схема с ассиметричной криптографией, она не может гарантировать неприкосновенности данных Клиента в рассматриваемой ситуации. А если гарантий нет, то нет и смысла заморачиваться. Поэтому, самым надежным гарантом неприкосновенности данных Клиента является: "Слющай, мамой клянусъ!" со стороны Продавца 😹
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Да, я думал про это уже давно, но руки не дошли до технической реализации.
Спасибо за статью, но врядли кто-то с автором стиллера это реализует, по ряду причин.
p.s. вместо rsa лучше юзать эллиптику
 
Да, я думал про это уже давно, но руки не дошли до технической реализации.
Спасибо за статью, но врядли кто-то с автором стиллера это реализует, по ряду причин.
p.s. вместо rsa лучше юзать эллиптику
Поддержу, идея хорошая если у тебя свой свой сервис или софт с завязкой на него. Но я так понимаю тут лишь вопрос доверия между клиентом и сервисом. RSA еще та блев*тина, не все знают, но там еще пучок подверсий если OpenSSL используйте, т.е. если у вас есть программный модуль не на основе OpenSSL то есть очень большая вероятность, что данные не откроются, буквально 4 месяца назад с этим сталкивался, пришлось выдирать нужный код из openssl - а там помойка просто жесть. Все таки не рекомендую RSA использовать. Лучше какой уж как советовали ECDSA
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Посмотреть вложение 102955

Ребятушки, предлагаю обсудить один вопрос в житии всяческих Бенов Стиллеров, который всегда казался мне очень странным. А именно: то и дело всплывает какой-то недовольный господин, который купил себе уютненький (как ему казалось) стиллер Х, но теперь обвиняет партнерку стиллера X в том, что они пиздят его драгоценные логи. Или, например, сломали панель стиллера Х, из-за чего все логи утекли и теперь путешествуют по интернетам. Очередное сравнительно недавнее обсуждение этого вдохновило меня на написание этой статьи.

Оставим за скобками всю морально-этическую составляющую использования стиллеров, философские вопросы доверия друг-другу в наше непростое время, а также то, что процесс спизжевания логов может быть основной бизнес моделью партнерки стиллера Х, и обратимся к технической стороне вопроса. Дело в том, что понимание криптографии, как таковой, и честная реализация некоторых ее подходов может практически полностью убрать из уравнения опасность спизженных логов.


Немного теории


Начнем с небольшого количества теории, рассказанной простым пацанским языком, а затем перейдем к практике. В далеком 1976 году на Национальной Компьютерной Конференции очень смышлёными дядьками Уитфилдом Диффи и Мартином Хеллманом была выдвинута судьбоносная для криптографии идея о шифровании с открытыми ключами. До этого безопасная передача ключей шифрования по открытым каналам связи была весьма проблематична, поскольку ключ мог быть перехвачен, а все данные расшифрованы с его помощью.

Алгоритмы шифрования можно разделить по принципу использования ключей на симметричные и асимметричные. Первые для шифрования и расшифровки данных используют один и тот же ключ. Да-да, именно тот один и тот же ключ, который может быть перехвачен. Асимметричные алгоритмы с другой стороны используют ключевую пару: так называемый "публичный ключ" для шифрования и "приватный ключ" для расшифровки данных. Таким образом, мисс Алиса говорит всем: "так, челики, вот вам мой публичный ключ, пишите мне свои секретные сообщения", но приватный ключ держит у себя и никому не показывает. Мистер Боб шифрует свои секретики на публичном ключе мисс Алисы и посылает ей шифр-данные. Мисс Алиса расшифровывает секретики на своем приватном ключе, и никакая ебучая Ева не может узнать секретики, которые Боб переслал Алисе, пока у нее нет доступа к приватному ключу Алисы. В обратную сторону уже Боб может сделать себе публичный и приватный ключи и чувствовать безопасность входящих от Алисы или кого-то другого секретиков. Если вам когда-либо было интересно, почему в криптографии обычно все объясняют с участием Алисы, Боба и Евы, читайте тут, мы традиций не нарушаем.

Можно условно сказать, что в мире асимметричных алгоритмов шифрования существуют только RSA (Ривест, Шамир, Адлеман) и ECC (эллиптические кривые). Слава Летающему Макаронному Монстру, нам с вами не нужно особо много шарить в математике, чтобы использовать эти алгоритмы, вдаваться в подробности о том, как они работают, мы конечно же не будем.

Вроде бы, концепция весьма годная: шифровать сообщения Алисе может кто угодно, а расшифровать их может только сама Алиса. Но почему же тогда асимметричные шифры давным давно не выпилили симметричные из мира практической криптографии. Дело в том, что асимметричные шифры слишком медленные (помимо некоторых других проблем), чтобы их использовать для большого количества данных. Но! Комбинируя асимметричные и симметричные алгоритмы мы можем получить преимущества обоих типов в одном.

Каким же образом их можно объединить? Да очень просто: генерировать ключи симметричного шифрования на новый сеанс связи, а для обмена этими ключами пользоваться асимметричным алгоритмом. Я понимаю, что многим из вас тут я не открыл Америку (сорян, дропами зиродеев не пахнет), тк такой подход используется просто повсеместно в сети Интернет и много где еще. Но давайте посмотрим, как это можно использовать в среде Бенов Стиллеров.


Смоделируем ситуацию


Допустим у нас есть некий новый клиент, который решил купить себе стиллер, будем его так и называть - "Клиент". Так вот, Клиент приходит к Продавцу и говорит, мол "давай мне мой билд". Продавец выдает ему некую тулзу, с помощью которой Клиент генерирует себе ключевую пару какого-то асимметричного алгоритма, допустим RSA. В качестве такой тулзы можно использовать стороннюю программу, типа OpenSSL, или написать кастомную тулзу, но важно, чтобы она поставлялась без обфускации и морфинга, или вообще с исходными кодами в придачу, чтобы Клиент при необходимости мог провести ее аудит (и убедиться, что его нигде не наёбывают).

Публичный ключ Клиент отправляет Продавцу, а приватный хранит у себя и никому не дает. Продавец вшивает публичный ключ Клиента в новый билд Стиллера, который он передает Клиенту. Непосредственно в коде Стиллера после сборки каждого нового лога происходит следующее. Сначала генерируется псевдослучайный ключ для симметрического алгоритма шифрования, допустим AES. Лог зашифровывается с помощью симметричного алгоритма и сгенерированного ранее ключа. Ключ симметричного алгоритма зашифровывается асимметричным алгоритмом с помощью вшитого публичного ключа Клиента и, допустим, дописывается в конец шифр-данных лога.

И получается следующее. Каждый лог зашифрован на каком-то отдельном рандомном ключе симметричного шифрования, который может получить только обладатель приватного ключа, то есть только Клиент (если он, конечно, не был доблоёбом и не давал свой приватный ключ кому ни попадя). Продавец может собирать у себя в панели такие шифр-контейнеры с логами клиентов, при этом ни сам Продавец, ни тот сторонний кулхацкер, который каким-то образом ломанул панель, не сможет эти крипто-контейнеры расшифровать, так как приватные ключи находятся только у Клиентов. Клиенты же скачивают свои логи и расшифровывают их у себя локально с помощью своих приватных ключей.

У такого подхода, безусловно, есть свои недостатки. Например, если Клиент внезапно проебал где-то свой ключ, то все свои логи он тоже уже не сможет расшифровать. Или, например, если особо хитро-выебанный Продавец будет шифровать симметричный ключ не только на ключе Клиента, но и на каком-то своем, и без палева дописывать его к шифр-данным. Или же отбрасывать два разных шифр-контейнера: для Клиента и для Продавца. В целом, эти ситуации при наличии достаточной квалификации можно проверить (например, на предмет того, что в шифр-данных присутствуют только зашифрованные симметричным алгоритмом логи и одна версия зашифрованного асимметричным алгоритмом ключа, или что билд не левачит какими-то дополнительными даннами). И понятно, что тогда Продавец не сможет отображать логи в красивых таблицах в панели, да и расшифровка паролей и кук на сервере панели станет невозможной. Но суммарно этот подход может быть весьма неплохим в плане повышения уровня доверия Клиентов к Продавцу, а также исключить то, что слитые логи будут путешествовать по Интернетам.


Переходим к практике


Я набросал небольшой пример реализации такого подхода на дотнетах и языке программирования C#. Выбор языка обусловлен тем, что на его примере легко показать реализацию подхода, ведь в дотнет фреймворк с бородатых времен встроен и алгоритм RSA (асимметричный) и алгоритм AES (симметричный). Насколько я помню, какие-то из встроенных классов являются полностью managed-реализацией, то есть реализованы непосредственно на C#, а какие-то являются простой прослойкой поверх CryptoAPI. Разбираться, какие именно какие, я конечно же не стал, да и вообще сравнительно мало пишу на C#, так что заранее прошу прощения, если код не оптимальный. Напишите в комментариях, как бы вы его улучшили, если чего.

И как же без подъёба?... Я знаю, что разработчики публичных и приватных стиллеров на С# очень любят друг у друга (ну скажем) "заимствовать" код, поэтому реализация на языке C# для них будет привычнее, штоль. Ей богу, как только я вижу один и тот же пресловутый класс SqLiteHandler, который сначала дизассемблировали из VB.NET кода давным давно, а потом растащили просто по всем стиллерам, мне хочется выколоть себе глаза...

Для начала рассмотрим генерацию ключей. Один из классов в дотнете, который реализует RSA называется RSACryptoServiceProvider. Если ему в конструктор передать размер ключа в битах, то он сгенерирует новую ключевую пару. Хранение RSA ключей в нем сделано довольно странно: в виде XML с BASE64 данными ключей, но окей. Метод для генерации ключей принимает два полных пути на файловой системе, они указывают, куда методу сохранить приватный и публичный ключ соответственно.
C#:
private static void Generate(string path_private, string path_public) {
    using var rsa = new RSACryptoServiceProvider(2048);
    var xml_public = rsa.ToXmlString(false);
    var xml_private = rsa.ToXmlString(true);
  
    File.WriteAllText(path_public, xml_public, Encoding.ASCII);
    File.WriteAllText(path_private, xml_private, Encoding.ASCII);
    Console.WriteLine("Public key was written to {0}", path_public);
    Console.WriteLine("Private key was written to {0}", path_private);
}

Стоит сделать небольшую ремарку о размере RSA ключей. В принципе, я являюсь сторонником мнения, что в данном конкретном случае хватит ключей размером в 2048 бит, но если вы хотите большей "секьюрности", то можно сделать ключи 4096 или 8192 бита. В зависимости от увеличения размера RSA ключа зашифрованный AES ключ и вектор инициализации будет занимать больше места. То есть для ключа размером 2048 бит, размер дополнительных данных для передачи AES ключа составит 256 байт, для 4096 бит - 512 байт (в одном байте 8 бит, ога?).

Теперь представим, что в исходный код Стиллера добавлен следующий метод для шифрования массива байт, который был получен, допустим, из заранее созданного ZIP-архива с новыми логами. Метод принимает публичный ключ Клиента и массив данных, которые нужно Клиенту зашифровать. Сначала мы инициализируем алгоритмы RSA и AES, алгоритму RSA подпихиваем публичный ключ Клиента.

При инициализации алгоритма AES происходит генерация симметричного ключа и вектора инициализации, из которых мы формируем буфер с ключевой информацией и зашифровываем его с помощью RSA и публичного ключа Клиента. Второй параметр метода шифрования RSA (установленный в истину) указывает на то, что мы будем использовать OAEP (Optimal Asymmetric Encryption Padding) для выравнивания, в противном случае будет использоваться PKCS#1 v1.5, насколько я понимаю. Вдаваться в подробности о различиях двух этих алгоритмов, наверное, не стоит, ограничимся тем, что в интернетах пишут, что OAEP лучше.

Дальше мы устанавливаем режим алгоритма в CBC (Cipher Block Chaining, то есть режим сцепления блоков), при этом шифрование каждого следующего блока будет зависеть от предыдущего. Таким образом, если в открытых данных вдруг находятся длинные последовательности однотипных или же предсказуемых данных, по шифр-данным это будет понять сложно. Алгоритм AES является блочным, в данном случае шифрование происходит блоками по 16 байт. Если размер данных не кратен размеру блока, то нужно применять выравнивание. В качестве алгоритма выравнивания мы выбираем PKCS7 без особых глубоко-философских на то причин.

Далее мы просто производит шифрование данных алгоритмом AES. В дотнетах принято все делать через потоки данных, наверное, это в целом правильно (для учета случая, когда нужно обработать большое количество данных и не сожрать всю память), но для целей шифрования сравнительно небольшого лога - это не удобно, но окей. Для шифр-данных я сделал отдельный буфер, в который происходит шифрование, затем этот буфер объединяется с зашифрованным алгоритмом RSA ключом симметричного шифрования. Если вам вдруг станет нужно обрабатывать таким образом большие данные, то старайтесь не плодить дополнительных буферов в памяти.
C#:
public static byte[] Encrypt(string public_key, byte[] data) {
    using var rsa = new RSACryptoServiceProvider();
    using var aes = new AesCryptoServiceProvider();
    rsa.FromXmlString(public_key);

    var key_buffer = new byte[48];
    Array.Copy(aes.Key, 0, key_buffer, 0, 32);
    Array.Copy(aes.IV, 0, key_buffer, 32, 16);
    key_buffer = rsa.Encrypt(key_buffer, true);
  
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;

    var mode = CryptoStreamMode.Write;
    using var data_buffer = new MemoryStream();
    using var encryptor = aes.CreateEncryptor();
    using(var crypto_stream = new CryptoStream(data_buffer, encryptor, mode))
    { crypto_stream.Write(data, 0, data.Length); }

    var encrypted_data = data_buffer.ToArray();
    using var encrypted_buffer = new MemoryStream();
    encrypted_buffer.Write(encrypted_data, 0, encrypted_data.Length);
    encrypted_buffer.Write(key_buffer, 0, key_buffer.Length);
  
    return encrypted_buffer.ToArray();
}

У Клиента есть тулза для расшифровки логов и его собственный приватный ключ, в этой самой тулзе реализован следующий метод, который по своей сути является просто зеркальным отражением метода шифрования. Мы разделяем данные на зашифрованные логи и зашифрованный алгоритмом RSA симметричный ключ (с вектором инициализации). В данном случае нам нужно знать, какой размер будет у блока данных зашифрованного симметричного ключа, этот размер можно получить после инициализации RSA через свойство KeySize (возвращается размер в битах, поэтому мы приводим его к байтам). Далее мы расшифровываем AES ключ и вектор инициализации и с его помощью расшифровываем и возвращаем данные. Опять же данный подход не совсем оптимальный для больших данных, но для логов - почему бы нет. Важно отметить, что параметры алгоритмов шифрования, такие как режим и выравнивание, очевидным образом должны быть одинаковые при шифровании и расшифровке.
C#:
public static byte[] Decrypt(string private_key, byte[] data) {
    using var rsa = new RSACryptoServiceProvider();
    using var aes = new AesCryptoServiceProvider();
    rsa.FromXmlString(private_key);
  
    var rsa_length = rsa.KeySize / 8;
    var key_buffer = new byte[rsa_length];
    var data_buffer = new byte[data.Length - rsa_length];
    Array.Copy(data, 0, data_buffer, 0, data.Length - rsa_length);
    Array.Copy(data, data.Length - rsa_length, key_buffer, 0, rsa_length);
    key_buffer = rsa.Decrypt(key_buffer, true);

    var aes_key = new byte[32];
    var aes_iv = new byte[16];
    Array.Copy(key_buffer, 0, aes_key, 0, 32);
    Array.Copy(key_buffer, 32, aes_iv, 0, 16);
  
    aes.Mode = CipherMode.CBC;
    aes.Padding = PaddingMode.PKCS7;
    aes.Key = aes_key;
    aes.IV = aes_iv;

    var mode = CryptoStreamMode.Read;
    using var decrypted = new MemoryStream();
    using var data_stream = new MemoryStream(data_buffer);
    using var decryptor = aes.CreateDecryptor();
    var crypto_stream = new CryptoStream(data_stream, decryptor, mode);
      
    crypto_stream.CopyTo(decrypted);
    return decrypted.ToArray();
}

Я приложу полный демо-код этого подхода к статье, он должен работать на всех версиях дотнетов от 4.0 до 4.8. Скорее всего он будет работать и на более ранних версиях (если вам такое может быть нужно), но для этого нужно будет заменить вызовы некоторых методов своим кодом (например, метода CopyTo для потоков данных).


Заключение


Итак, мы с вами посмотрели (условно) реализацию старого (как мир) протокола господинов Диффи и Хеллмана применительно к современным стиллерам. Как говорили древние криптографы: "если сударь не хочет, чтобы логи его клиентов спиздили, сударю надобно использовать криптографию с открытыми ключами" (с). Да, у такого подхода есть свои недостатки, которые я предлагаю обсудить в комментариях, но вообще говоря, мне до сих пор не понятно, почему в каждом из стиллеров не применяется что-то такое? Или есть в природе стиллеры, которые так работают (я прост не шарю)? Может быть, все уже привыкли к типичной модели MaaS стиллеров, при которой риск спизженных логов является необходимым злом? В общем, я не знаю, да и не моё это дело по большому счету, но почему бы не обсудить? Пишите в комментариях, что думаете...

Специально для любимого xss.pro.
Автор материала - самый талантливый (в плане написания конкурсных статей) бот в мире XSSBot! (эти ихние американские ЧатыГПТ и китайские ЛЛМки сосац!)
Статья достойная уважения и внимания, такой подход рекомендуется в целом в большинстве проектов организовать помимо кул маркета билдов стиллера
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Да, я думал про это уже давно, но руки не дошли до технической реализации.
Спасибо за статью, но врядли кто-то с автором стиллера это реализует, по ряду причин.
p.s. вместо rsa лучше юзать эллиптику
Можешь рассказать вкратце про эллиптику, очень интересно послушать твой довод.
p.s. лень перекапывать весь интернет ради трёх предложений, когда могу спросить у тебя вкратце.
 
Можешь рассказать вкратце про эллиптику, очень интересно послушать твой довод.
p.s. лень перекапывать весь интернет ради трёх предложений, когда могу спросить у тебя вкратце.
Ты просишь занятого человека в двух словах рассказать мат часть криптографического алгоритма? Извини конечно, но ты больной?
 
Пожалуйста, обратите внимание, что пользователь заблокирован
вкратце про эллиптику
Не знаю, что конкретно Quake3 имел ввиду, но я знаю, что размер ключа по отношению к криптостойкости у эллиптических кривых лучше, да и генерация ключей должна проходить быстрее. Но имхо, если учесть, что реализацию RSA можно подсосать из системы (как в статье, или через CryptoApi/bcrypt в Венде, какая-то версия OpenSSL наверняка будет на Линуксах и Маках), чтобы не таскать с собой - это хороший плюс. Криптография с открытым ключом - это довольно много кода: нужна реализация больших чисел, помимо самого алгоритма. Я знаю, что современные стиллаки могут мегабайтные библиотеки с собой таскать или выкачивать (типа SQLite3 и какую-то реализацию AES со счетчиком Галуа вместо bcrypt.dll), но у меня, как у представителя "старой школы", несколько мегабайтные экзешники вызывают стыд.
 
Не знаю, что конкретно Quake3 имел ввиду, но я знаю, что размер ключа по отношению к криптостойкости у эллиптических кривых лучше, да и генерация ключей должна проходить быстрее. Но имхо, если учесть, что реализацию RSA можно подсосать из системы (как в статье, или через CryptoApi/bcrypt в Венде, какая-то версия OpenSSL наверняка будет на Линуксах и Маках), чтобы не таскать с собой - это хороший плюс. Криптография с открытым ключом - это довольно много кода: нужна реализация больших чисел, помимо самого алгоритма. Я знаю, что современные стиллаки могут мегабайтные библиотеки с собой таскать или выкачивать (типа SQLite3 и какую-то реализацию AES со счетчиком Галуа вместо bcrypt.dll), но у меня, как у представителя "старой школы", несколько мегабайтные экзешники вызывают стыд.
Ты абсолютно прав!!! НО как я и писал в ключах RSA много ньюансов, не в самих ключах конечно, а в том в каком виде их предоставляют и вот как раз в этой помойке стандартов часто встречаются недоработки - ИМЕННО поэтому тащат OpenSSL со всем гуано что там есть в своих стилаках многие (90% конечно тащат потому что мозгов нет). НО как сказано выше есть уже стандарты которые вешают мало и работают везде одинакого. Про RSA давно надо забыть, то к какому виду мировое сообщество привело этот алгоритм и распространяет я называю помойкой. Вот просто лениво расписывать пример когда RSA стандарт косячит в разных системах и библиотеках, на вскидку гляньте стандарты упаковки ключа pkcs их там во первых не мало, а во вторых мировое сообщество стандартов добавляет к нему поправки которые не все знают и добавляют.
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
но вообще говоря, мне до сих пор не понятно, почему в каждом из стиллеров не применяется что-то такое?
Идея просто отличная пока поверхностно думаешь о ней и не начинаешь реализовывать.
Это гарантии для клиентов (а значит больше клиентов и дополнительный заработок), все та же простота MaaS (не нужно специальных знаний от клиентов для установки) и еще куча преимуществ которые позволяли бы нам зарабатывать больше.
Мы вели разработки в этом направлении, и я говорю об этом как практик, а не теоретик. Гладко было на бумаге, да забыли про овраги, а их здесь очень и очень много и скажу так - все я так и не прошел, в этом нет никакого экономического смысла.
Например, любому клиенту хочется видеть сразу количество файлов куки, количество паролей, количество кошельков и прочее, не говоря уже о фильтрах и других наворотов, а при использовании шифрования это сделать невозможно, и этот овраг я прошел, отправляя на сервер пакет с количеством кук и паролей посчитанных на машине (по сути отправлялись просто числа, в этом ничего такого), подчеркну что для других фич вроде фильтров я выход так и не нашел. Вторая проблема оказалась гораздо серьезнее, так как затрагивает практически ВСЕ, а состоит она в том, что приходится отправлять весь лог целиком (его не получается дробить, отправлять по частям), а это уже большие потери по стуку, да, там можно было притянуть, что называется, кота за яйца и все переписать, но я на этом остановился, потому что повторюсь, в этом нет никакого экономического смысла.
Клиентам проще купить self-hosted продукт, чем отказаться от кучи фич что сейчас предоставляют стилеры, во всяком случае, потребность в описанном в статье очень низкая, а идея такая приходила я думаю каждому разработчику стилера.
 
Идея просто отличная пока поверхностно думаешь о ней и не начинаешь реализовывать.
Это гарантии для клиентов (а значит больше клиентов и дополнительный заработок), все та же простота MaaS (не нужно специальных знаний от клиентов для установки) и еще куча преимуществ которые позволяли бы нам зарабатывать больше.
Мы вели разработки в этом направлении, и я говорю об этом как практик, а не теоретик. Гладко было на бумаге, да забыли про овраги, а их здесь очень и очень много и скажу так - все я так и не прошел, в этом нет никакого экономического смысла.
Например, любому клиенту хочется видеть сразу количество файлов куки, количество паролей, количество кошельков и прочее, не говоря уже о фильтрах и других наворотов, а при использовании шифрования это сделать невозможно, и этот овраг я прошел, отправляя на сервер пакет с количеством кук и паролей посчитанных на машине (по сути отправлялись просто числа, в этом ничего такого), подчеркну что для других фич вроде фильтров я выход так и не нашел. Вторая проблема оказалась гораздо серьезнее, так как затрагивает практически ВСЕ, а состоит она в том, что приходится отправлять весь лог целиком (его не получается дробить, отправлять по частям), а это уже большие потери по стуку, да, там можно было притянуть, что называется, кота за яйца и все переписать, но я на этом остановился, потому что повторюсь, в этом нет никакого экономического смысла.
Клиентам проще купить self-hosted продукт, чем отказаться от кучи фич что сейчас предоставляют стилеры, во всяком случае, потребность в описанном в статье очень низкая, а идея такая приходила я думаю каждому разработчику стилера.
)
эта книга не нуждается в рекламе, ведь она и так хорошо продается
 
Пожалуйста, обратите внимание, что пользователь заблокирован
не в самих ключах конечно, а в том в каком виде их предоставляют
Ну да, дотнетовские XML-строки с ключами тож довольно странно выглядят, и скорее всего придется поебаться, чтобы их конвертировать в какой-то удобоваримый для другой библиотеки формат, но если ты на обоих сторонах пользуешься одинаковыми библиотеками, то у тебя таких проблем не должно быть. Иногда то, что мелкомягкие имеют пунктики по обратной совместимости, играет нам на руку.

Идея просто отличная пока поверхностно думаешь о ней и не начинаешь реализовывать.
Я не то чтобы спорю с этим утверждением, но практически всегда удобство пользования и безопасность - это противоположные понятия, тут уже выбираешь либо одно, либо другое. Если рассматривать юзабилити того, что написано в статье, мне кажется, что самой удобной была бы модель, когда панель в классическом понимании будет не панелью, а просто сервером, который агрегирует крипто-контейнеры логов со стиллеров и хранит их у себя, типа как облачное хранилище, больше ничего не делает и веб-интерфейса не имеет, только апи, чтобы сузить поверхность для атаки на нее. Продавец дает клиенту графическое декстопное приложение, которое общается с панелью по апи, скачивает крипто-контейнеры логов с сервера и автоматом их разбирает с помощью приватного ключа, затем уже отображает в красивых таблицах то, что скачано и разобрано локально. Авторизацию на сервере тоже можно сделать автоматической по приватному ключу, если надо, могу примерно расписать как. Но такой случай, когда клиент обязан держать свой приватный ключ на компьютере или вм с доступом в интернет не полностью безопасен. Безопаснее было бы это все делать на оффлайн машине, но опять же, это не удобно клиенту, так что...
 
Хз, это точно конкурсная статья? Мануал по использованию алгоритмов шифрования на сишарпе, как по мне.

Если вы рассматриваете это как защита от воровства логов - единственная защита это свой софт.
 
Хз, это точно конкурсная статья? Мануал по использованию алгоритмов шифрования на сишарпе, как по мне.

Если вы рассматриваете это как защита от воровства логов - единственная защита это свой софт.
Конечно не тянет, много букф/воды, тут идея хорошая. Ептать, я думал ты давно здох ))) Привет, чтоли
 
Кому важна безопасность и не хочет доверять массовому продукту, тот может всегда взять продукт, который размещается на своём личном сервере! Благо есть такие продукты! Кому то важно удобство, быстрота и обслуживание - для них есть мы, а для тех кто готов контролировать процессы все самостоятельно, есть продукты , которые размещаются на своём сервере!

Конечно можно шифровать не весь лог, а к примеру только кошельки, так как самое главное содержимое, тогда и сортировка останется и прочее...

В общем тут дело выбора, кто готов к самостоятельности, те даже сами пишут Stealer , а кто не хочет постигать всё это, может всегда разместится у массового продукта :)
 
Кому важна безопасность и не хочет доверять массовому продукту, тот может всегда взять продукт, который размещается на своём личном сервере! Благо есть такие продукты! Кому то важно удобство, быстрота и обслуживание - для них есть мы, а для тех кто готов контролировать процессы все самостоятельно, есть продукты , которые размещаются на своём сервере!

Конечно можно шифровать не весь лог, а к примеру только кошельки, так как самое главное содержимое, тогда и сортировка останется и прочее...

В общем тут дело выбора, кто готов к самостоятельности, те даже сами пишут Stealer , а кто не хочет постигать всё это, может всегда разместится у массового продукта :)
Хотел дизлайк воткнуть тебе и в бан бы отправить за накрутку комментов, но чет настроение хорошее, ты статью то хорошо прочитай о чем она для начала, а потом комменты пиши. Там идея в другом.
 
Хотел дизлайк воткнуть тебе и в бан бы отправить за накрутку комментов, но чет настроение хорошее, ты статью то хорошо прочитай о чем она для начала, а потом комменты пиши. Там идея в другом.
Какая накрутка коментов? у вас всё впорядке ? Ну расскажите в чём идея, если вы такой умный, а то получается бана за накрутку залуживаете именно вы.

Вроде как тут говорится о том, что бы сделать шифрование логов и владельцы масс продуктов, которые держут логи на своих сервера не имели к ним доступа, а только те, кто имеет к ним ключ, то есть владельцы самих логов.

На что я и говорю, что можно спокойно выбирать уже сейчас альтернативы, которые размещаются на личных серверах, а если важно удобство, что является не маловажным фактором, есть массовые продукты.

Тут дело и выбор остаётся за каждый, никто никого не ущемляет... Да и как выше Lumma сказал, что при шифровании таким методом, многие возможности теряются при сортировках и прочем, но в целом можно шифровать только кошельки, но тогда рынку придётся перестраиваться и писать новые чекеры, а многие работают сразу уже по схеме, когда приходит готовый лог в ТГ.
 
но вообще говоря, мне до сих пор не понятно, почему в каждом из стиллеров не применяется что-то такое?
если ты не видел, это не значит что не применяется =) во флеймере было, и еще как минимум у одного чела с этого форума в приватном стиллаке.
почему это не делается в maas - тут все думаю очевидно ...
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Можешь рассказать вкратце про эллиптику, очень интересно послушать твой довод.
Мне лень пересказывать мануалы + все уже сказали до меня, вкратце есть 2 аргумента:
1. Размер ключа меньше, 256 бит ЕСС == 2048 RSA
2. В некоторых реализациях (типа 25519) для ключа тебе надо всего лишь 32 случайных байт , а не все эти PRIVAT_BLOB и подобное.

И да, конечно RSA есть в системе, а ЕСС нет (не помню насчет CNG), но это не аргумент.
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх