Увійти Реєстрація
Вакансії
Вакансії Laravel Компанії Статистика
Підготовка
Як підготуватися < href="https://laravelukraine.com/interviews" wire:navigate.hover class="flex items-center gap-3 rounded-md px-3 py-2 text-base font-medium text-gray-600 hover:bg-gray-50 hover:text-gray-900 dark:text-gray-400 dark:hover:bg-gray-900 dark:hover:text-white" >Співбесіди Тестування Документація
Блог
Всі статті Серії
Екосистема
Пакети Ресурси Проєкти Інструменти Події Відео
Інше
Про нас Реклама
Новини 12 листопада 2026

Вразливість у Livewire PowerGrid: пошук через searchableRaw() показує чужі рядки

У Livewire PowerGrid знайшли вразливість GHSA-wj8p-8c55-266p: колонка з searchableRaw() або searchableJson() додає свою умову пошуку так, що вона обходить усі обмеження, які таблиця задає в datasource(). Автентифікований користувач, якому доступне поле пошуку, бачить рядки, яких бачити не повинен, наприклад записи інших користувачів. Критичність середня (CVSS 4.3, CWE-863 - неправильна авторизація), повідомив про проблему pboese.

Хто уражений і як оновитися

Уражені всі версії до 7.0.0 включно. Автор звіту перевірив 6.11.1 і 7.0.0, а старіші версії з searchableRaw() найімовірніше теж уражені. Під загрозою таблиця, у якої одночасно:

  • обмеження рядків прописане в datasource() (поточний користувач, статус, вкладка, категорія);
  • хоча б одна колонка оголошена через searchableRaw() або searchableJson().

Виправлення вийшло 31 жовтня в PowerGrid 7.0.1. Сам фікс живе в пакеті power-components/turbine, на якому побудовано PowerGrid 7: версія 0.14.1 застосовує сирі orWhere-умови всередині групи пошуку, а PowerGrid 7.0.1 тепер вимагає turbine ^0.14.1. Перевірте, що стоїть у проєкті, й оновіться разом із залежностями:

  composer show power-components/livewire-powergrid power-components/turbine
  composer update power-components/livewire-powergrid --with-dependencies

Із гілкою 6.x гірше: остання її версія 6.11.1 уражена, а патча для неї немає. Перехід на 7.x - це окрема робота (PHP 8.3+, Laravel 12+, Livewire 4, Tailwind CSS 4), тож до нього варто прибрати searchableRaw() і searchableJson() з таблиць, які обмежують рядки в datasource().

Як ламається запит

Звичайні колонки з searchable() PowerGrid загортає в одну групу where(function ...). А searchableRaw() зберігає свою умову з методом orWhereRaw, і окремий крок конвеєра застосовує її вже після групи пошуку, прямо до кореневого запиту. В advisory наведено SQL, який виходить у підсумку:

  where `orders`.`user_id` = ? and (`orders`.`number` LIKE ? or ...) or customers.name LIKE ?

AND у SQL зв'язує сильніше за OR, тож база читає це так:

  (`orders`.`user_id` = ? and (...)) or customers.name LIKE ?

Друга половина не знає нічого про user_id. Варто ввести в пошук "acme", і таблиця покаже замовлення всіх користувачів, чий клієнт зветься Acme. Експорт будує набір даних тими самими кроками, тож вивантажить ті самі чужі рядки у файл.

Зверніть увагу, що для relationSearch() у 7.x цю пастку вже обійшли: умова пошуку по зв'язку стоїть усередині групи, і коментар у коді описує саме цей ризик. searchableRaw() просто не отримав того самого лікування - до 7.0.1.

Чому глобальні скопи вистояли

Якщо обмеження на "свої" рядки зроблено глобальним скопом (Global Scope) моделі, вразливість його не зачіпає. Eloquent застосовує глобальні скопи наприкінці, перед виконанням запиту, і коли серед уже наявних умов є OR, сам бере їх у дужки, а умову скопу додає через AND окремо:

  where ((`orders`.`number` LIKE ? or ...) or customers.name LIKE ?) and `orders`.`user_id` = ?

Умови, написані прямо в datasource(), такого захисту не мають: для Eloquent це звичайні where того самого рівня, що й рядок orWhereRaw, доданий пізніше. А саме в datasource() найчастіше й обмежують таблицю поточним користувачем.

Та сама пастка у власному коді

PowerGrid тут лише приклад. orWhere без групування - одна з найпоширеніших помилок в Eloquent, і вона так само тихо ламає фільтр доступу в контролерах, API та звітах. Кілька звичок, які її прибирають:

  • Будь-який orWhere - тільки всередині групи. Пошук по кількох полях загортайте в замикання або беріть whereAny(), який групує умови сам:
  Order::query()
      ->where('user_id', $request->user()->id)
      ->where(function ($query) use ($term) {
          $query->where('number', 'like', "%{$term}%")
              ->orWhere('note', 'like', "%{$term}%");
      });

  // або
  Order::query()
      ->where('user_id', $request->user()->id)
      ->whereAny(['number', 'note'], 'like', "%{$term}%");
  • Дивіться на SQL. toSql() або toRawSql() у тесті чи в tinker одразу покаже, де стоять дужки. Саме так перевіряє виправлення новий тест у Turbine: він очікує в запиті "in_stock" = ? and (dishes.name like ?).

  • Тестуйте поведінку, а не лише SQL. Найнадійніший тест на такі речі - два користувачі зі схожими даними і перевірка, що пошук одного не віддає записів іншого:

  it('does not leak other users orders through search', function () {
      $alice = User::factory()->create();
      $bob = User::factory()->create();

      Order::factory()->for($bob)->create(['number' => 'ACME-2']);

      $this->actingAs($alice)
          ->get('/orders?search=ACME')
          ->assertOk()
          ->assertDontSee('ACME-2');
  });

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

Що зробити зараз

Якщо в проєкті є PowerGrid, пройдіться пошуком по searchableRaw( і searchableJson(. Немає збігів - вразливість вас не стосується, але оновитися до 7.0.1 все одно варто. Є збіги в таблицях, що обмежують рядки в datasource(), - оновлюйтеся на 7.x негайно або, на 6.x, приберіть ці колонки з пошуку до переходу. Для гілки 6.x це не перша проблема за рік: у липні в ній уже закривали SQL-ін'єкцію через sortDirection (CVE-2026-65971, виправлено в 6.10.4).

А у власному коді - той самий пошук, тільки по orWhere: кожен, що стоїть не всередині where(function ...), вартий другого погляду.

13

Читати в документації

Коментарі

Увійдіть, щоб залишити коментар

Будьте першим, хто залишить коментар!

Читайте також

Новини 14 листопада 2026

Laravel Octane 2.23: стрімінг відповідей-генераторів запрацював на FrankenPHP і Swoole

Octane 2.23.0 виправив баг, через який response()->stream() з генератором на FrankenPHP і Swoole віддавав 200 з порожнім тілом і ламав SSE та стрімінг Laravel AI SDK. Також у релізі підтримка RoadRunner 3.x, мінімальна версія FrankenPHP 1.13.2 і слухачі як singletons.

9
Новини 14 листопада 2026

RFC пропонує хуки життєвого циклу запиту для воркер-режиму PHP

Кевін Дюнгла виніс на обговорення RFC «Request lifecycle hooks for SAPIs with a worker mode»: два нові хуки модулів request_begin і request_end та функції php_request_begin() і php_request_end(). Вони мають замінити крихкі скидання стану, через які FrankenPHP цього року виправляв витік session ID і помилки пам'яті. Ціль - PHP 8.7, голосування ще не призначене.

11

Вакансії за темою

Black River Express
13 днів тому

Senior PHP Developer

Senior PHP розробник для логістичної платформи: бекенд-сервіси на PHP 8.3+ та Laravel 11 і веб-панель на Filament 3 та Livewire 3. Завдання: REST API, авторизація, інтеграції через API і вебхуки, оптимізація PostgreSQL, черги та кешування. Вимоги: комерційний досвід Laravel, знання PostgreSQL, Redis, WebSockets, CI/CD та діагностики продакшн-проблем. Віддалено, також розглядають сильних Middle+.

ВебФорза Нова
Сьогодні

Програміст PHP (Laravel, WordPress, гіг-контракт)

Розробка на фреймворку Laravel та створення тем і плагінів для WordPress. Завдання включає роботу з jQuery, JS, CSS, HTML і PHP, використання git та оптимізацію швидкості завантаження сторінок. Оформлення за гіг-контрактом з погодинною оплатою.

Starlight Media Нова
2 дні тому

Senior Full-Stack Developer (PHP / Go / Vue.js)

Senior Full-Stack розробник матиме розвивати й підтримувати існуючі веб-платформи, писати модулі, сервіси та API, а також розробляти клієнтську частину на Vue.js і Vanilla JS. Основний стек: PHP 8.x з Yii2 та/або Laravel, Go для сервісів, MySQL/MariaDB, REST API і Webhooks. Вимоги: досвід від 3 років, знання ООП і шаблонів проєктування, ES6+, Vue.js, SPA, Git, Docker і Composer; англійська B1-B2.

Пакети за темою

Kalimera

welldigit/kalimera

Interactive installer that scaffolds Laravel applications the Well Digit way.

v1.0.0 17

Filament

filament/filament

Найпопулярніша адмін-панель для Laravel: ресурси, таблиці, форми та дашборди описуються PHP-класами поверх Livewire, Alpine і Tailwind. Замінює рутину CRUD-інтерфейсів декларативною конфігурацією.

31,852 v5.7.6 11