Xlera8

Chrome zero-day: «Цей експлойт доступний», тому перевірте свою версію зараз

Вийшло останнє оновлення Chrome від Google, і цього разу компанія не збивав слів про одне з двох виправлень безпеки, які він містить:

Google знає, що експлойт для CVE-2023-3079 існує в дикій природі.

Як ми часто бачили від Google раніше, не існує словесності з двома ступенями поділу, щоб сказати, що компанія «знає про повідомлення» про експлойт.

Цього разу це «ми знаємо про це самі», що ще більш відверто перекладається як «ми знаємо, що шахраї зловживають цим, поки ми говоримо», враховуючи, що звіт про помилку надійшов безпосередньо від власної групи дослідження загроз Google.

Як зазвичай, це означає, що Google розслідувала активну атаку (чи то на саму Google, чи на якусь зовнішню організацію, ми не знаємо), під час якої Chrome був пограбований раніше невідомою дірою в безпеці.

Помилка описується просто так: Плутанина типів у V8. (Зрозуміло, що Google на даному етапі не говорить більше, ніж це.)

Як ми вже пояснювали раніше, a плутанина типу Помилка виникає, коли ви надаєте програмі частину даних, які вона повинна аналізувати, перевіряти, обробляти та діяти в один спосіб...

…але пізніше вам вдається обманом змусити програму інтерпретувати дані іншим, неавторизованим, неперевіреним і потенційно небезпечним способом.

Пояснення небезпек плутанини типу

Уявіть, що ви пишете програму мовою C. (Неважливо, знаєте ви мову C чи ні, ви все одно можете просто слідувати).

У C ви зазвичай оголошуєте змінні окремо, таким чином не тільки резервуючи пам’ять, де вони можуть зберігатися, але й сигналізує програмі, як ці змінні мають використовуватися.

Наприклад:

 long long int JulianDayNumber; signed char* CustomerName;

Перше оголошення змінної резервує 64 біти для зберігання простого старого цілого значення, що представляє номер астрономічного дня. (Якщо вам цікаво, сьогодні вдень JDN 23157 – юліанські дні починаються опівдні, а не опівночі, оскільки астрономи часто працюють вночі, а опівніч – це середина їхнього робочого дня.)

Другий резервує 64 біти для збереження адреси пам’яті, де можна знайти текстовий рядок імені клієнта.

Як ви можете собі уявити, вам краще не плутати ці два значення, оскільки число, яке має сенс і безпечно використовувати як номер дня, наприклад 23157, майже напевно буде небезпечним для використання як адресу пам’яті.

Як ви можете бачити з цього дампа пам’яті запущеної програми Windows, найнижча адреса пам’яті, виділена для використання, починається з 0x00370000, що дорівнює 3,604,480 XNUMX XNUMX у десятковій системі, набагато більше, ніж будь-яке розумне число дня.

Фактичні адреси пам’яті, які використовує Windows, змінюються випадковим чином з часом, щоб шахраям було важче вгадати макет вашої пам’яті, тому, якщо ви запустите ту саму програму, ви отримаєте значення, але вони все одно будуть подібними:

І (хоча це не в нижній частині зображення вище) адреси пам’яті розділу даних користувача, коли ця програма запускалася з 0x01130000 до 0x01134FFF, що представляє малоймовірний діапазон дат з 22 липня 44631 по 16 серпня 44687.

Дійсно, якщо ви спробуєте змішати ці дві змінні, компілятор повинен спробувати попередити вас, наприклад, так:

 JulianDayNumber = ім'я клієнта; CustomerName = JulianDayNumber; попередження: присвоєння створює ціле число з вказівника без приведення попередження: присвоєння створює вказівник з цілого числа без приведення

Тепер, якщо ви коли-небудь програмували на C, ви знаєте, що для зручності ви можете оголошувати змінні з кількома різними інтерпретаціями за допомогою union ключове слово, як це:

 union { long long int JulianDayNumer; signed char* CustomerName; } дані;

Тепер ви можете посилатися на ту саму змінну в пам’яті двома різними способами.

Якщо ви пишете data.JulianDayNumber, ви чарівним чином інтерпретуєте збережені дані як ціле число, але записуєте data.CustomerName повідомляє компілятору, що ви посилаєтеся на адресу пам'яті, навіть якщо ви отримуєте доступ до тих самих збережених даних.

Те, що ви робите, більш-менш, це зізнаєтеся компілятору, що іноді ви будете розглядати дані, які маєте, як дату, а іноді як адресу пам’яті, і що ви берете на себе відповідальність за запам'ятовування, яка інтерпретація застосовна в який момент в коді.

Ви можете вирішити мати другу змінну, відому як a tag (зазвичай ціле число), щоб погодитися з вашим union щоб відстежувати, з якими даними ви зараз працюєте, наприклад:

 struct { int тег; union { long long int JulianDayNumer; signed char* CustomerName; } дані; } значення;

Ви можете вирішити це коли value.tag встановлений в 0, дані ще не ініціалізовано для використання, 1 означає, що ви зберігаєте дату, 2 означає, що це адреса пам'яті, а все інше вказує на помилку.

Ну, тобі краще не дозволяти нікому з цим пов’язуватися value.tag налаштування, інакше ваша програма може працювати некоректно.

Більш тривожним прикладом може бути щось на зразок цього:

 struct { int тег; // 1 = хеш, 2 = об'єднання покажчиків на функції { unsigned char hash[16]; // або зберегти випадковий хеш struct { void* openfunc; // або два ретельно перевірених void* closefunc; // покажчики коду для виконання пізніше } validate; } } значення;

Тепер ми перевантажуємо той самий блок пам’яті, щоб іноді використовувати його для зберігання 16-байтового хешу, а іноді для зберігання двох 8-байтових покажчиків на функції, які наша програма викличе пізніше.

Зрозуміло, коли value.tag == 1, ми будемо раді дозволити нашому програмному забезпеченню зберігати будь-який 16-байтовий рядок у пам’яті, виділеній для об’єднання, оскільки хеші є псевдовипадковими, тому будь-яка колекція байтів однаково ймовірна.

Але коли value.tag == 2, наш код повинен бути надзвичайно обережним, щоб не дозволити користувачеві надати неперевірені, ненадійні, невідомі адреси функцій для виконання пізніше.

А тепер уявіть, що ви можете надіслати значення в цей код, коли для тегу встановлено значення 1, тому його не було перевірено та підтверджено…

…але пізніше, незадовго до того, як програма фактично використала збережене значення, ви змогли обманом змусити код змінити тег на 2.

Тоді код прийме ваші неперевірені адреси функцій як «відомі та вже підтверджені безпечні» (навіть якщо це не так), і довірливо відправить виконання програми в недобросовісне місце в пам’яті, яке ви підступно вибрали заздалегідь.

І це те, що відбувається в помилці плутанини типів, хоч і з використанням надуманого та спрощеного прикладу,

Пам’ять, яку було б безпечно споживати, якби її обробляли одним способом, зловмисно доставляється програмі для обробки в альтернативний, небезпечний спосіб.

Що ж робити?

Переконайтеся, що у вас остання версія Chrome або Chromium.

Вам потрібен Chrome 114.0.5735.106 або пізнішої версії на Mac і Linux, а також 114.0.5735.110 або пізнішої версії Windows.

Microsoft Edge, який базується на Chromium, також страждає від цієї помилки.

Microsoft наразі [2023-06-06T16:25:00Z] зазначив, що

Корпорація Майкрософт знає про нещодавні експлойти, які існують у дикій природі. Ми активно працюємо над випуском патча безпеки.

Edge наразі має версію 114.0.1823.37, тому будь-що пронумеровано пізніше має містити виправлення Microsoft CVE-2023-3079.

Щоб перевірити свою версію та примусово оновити, якщо є таке, яке ви ще не отримали:

  • Google Chrome. Трикрапкове меню (⋮) > Документи > Про Chrome.
  • Microsoft Edge. Налаштування та інше (…) > Довідка та відгуки > Про Microsoft Edge.

Ласкаво просимо.


Зв'яжіться з нами!

Привіт! Чим я можу вам допомогти?