Текуща ситуация: PHP2Shell. Две критични уязвимости в PHP (CVSS 9,2) позволяват злонамерен код без вход. Корекции от 21.10.2026 г.Какво да направите сега →

Защита на REST API в PHP

Интерфейсите често са защитени по-зле от уебсайта пред тях. Най-важните правила за REST API в PHP, от правата върху обектите до ограничаването на честотата.

Актуалност 5 мин. четенеСигурна разработка

Накратко: За сигурността на API в PHP най-важни са пет точки: само HTTPS, удостоверяване на всяка непублична крайна точка, проверка на правата за всеки отделен обект, строги граници за метода, типа на съдържанието и размера на заявката, както и кратки съобщения за грешки без вътрешни подробности. Към това се добавят ограничаване на честотата и журнал на събитията, свързани със сигурността. Срещу уязвимости в самия интерпретатор на PHP като PHP2Shell това не помага; за това е нужна актуализацията на PHP.

Интерфейсът зад уебсайта

Много фирми проверяваха в седмицата след 21.10.2026 г. уебсайтовете си. Интерфейсите зад тях по-рядко бяха в списъка. А точно там протичат чувствителни процеси: приложението на клиентския портал извлича фактури, системата за управление на стоките записва наличности в магазина, партньор съобщава поръчки чрез уебхук. Често тези API бяха изградени бързо, за една-единствена цел, и после никога не бяха преглеждани.

Един API няма интерфейс, който да прави грешките видими. Липсваща проверка на правата в ежедневието не бива забелязана от никого, докато всички клиенти питат само за това, което трябва. Атакуващият обаче изпробва точно онова, което не е предвидено.

Първата стъпка затова е опис. Какви крайни точки изобщо има? Често се намират стари версии като /api/v1/, които след преминаването към /v2/ никога не са били изключени, тестови крайни точки от разработката или публично достъпно описание на интерфейса, което изброява вътрешни функции. Всяка крайна точка, която вече не е нужна, трябва да се изключи. Всяка, която остава, се нуждае от отговорно лице.

Сигурност на API в PHP: основните правила

OWASP REST Security Cheat Sheet обобщава доказани правила. За PHP проекти те могат да се преведат в кратък списък:

  1. Само HTTPS. Токени и данни за достъп никога не бива да се предават нешифровани.
  2. Всяка крайна точка проверява сама. Удостоверяването може да се извършва централно, а решението за достъп се взема в крайната точка.
  3. Право за всеки обект. Не само „влязъл е“, а „има право точно на този запис“.
  4. Определете разрешените методи. Което не е изрично разрешено, се отхвърля с 405.
  5. Проверете типа на съдържанието и размера. Грешен тип дава 415, твърде големи заявки 413.
  6. Валидирайте входните данни. Тип, дължина, формат и диапазон на стойностите, от страна на сървъра.
  7. Без тайни в URL. Токените и ключовете принадлежат в заглавни части, а не в query string.
  8. Кратки грешки. Без stack trace, пътища или SQL съобщения към клиента.
  9. Ограничаване на честотата. На твърде много заявки се отговаря с 429.
  10. Скрийте крайните точки за администриране. Не са публично достъпни или само със силен вход.

Право върху обект: най-честата грешка

Един пример прави проблема осезаем. Една крайна точка връща фактури под /api/rechnungen/{id}. Проверява се дали има валиден токен. Не се проверява дали фактурата принадлежи на клиента на токена. Който увеличи с едно собствения си номер на фактура, вижда тази на съседа.

Решението е просто и въпреки това трябва да се приложи на всяко място: самата заявка се ограничава до правомерната област.

<?php
// Разрешаване само на метод GET
if ($_SERVER['REQUEST_METHOD'] !== 'GET') {
    http_response_code(405);
    header('Allow: GET');
    exit;
}

$kundeId = $auth->kundeId();          // от проверения токен
$id = filter_var($routeId, FILTER_VALIDATE_INT);
if ($id === false) {
    http_response_code(400);
    exit;
}

// Правото е в заявката: само собствени фактури
$stmt = $pdo->prepare('SELECT nummer, betrag, datum FROM rechnungen WHERE id = ? AND kunde_id = ?');
$stmt->execute([$id, $kundeId]);
$rechnung = $stmt->fetch(PDO::FETCH_ASSOC);

if (!$rechnung) {
    http_response_code(404);           // не издавайте дали ID съществува
    exit;
}

header('Content-Type: application/json');
echo json_encode($rechnung, JSON_THROW_ON_ERROR);

Заявката със заместители защитава същевременно от SQL инжекция, вижте Предотвратяване на SQL инжекция в PHP. Как PHP предоставя данните от заявката като метод, заглавни части и тяло, обяснява Superglobals: $_GET, $_POST, $_FILES и др..

Правилна проверка на токени

Много API работят с JSON Web Tokens. OWASP Cheat Sheet посочва за това ясни правила: токените трябва да са подписани, неподписаните токени се отхвърлят, а алгоритъмът за проверка се определя на сървъра, а не се взема от токена. Издателят, аудиторията и срокът на валидност също спадат към проверката. Ползвайте за това поддържана библиотека вместо собствени реализации.

Собствените токени, например за уебхукове или връзки за еднократна употреба, трябва да идват от криптографски сигурен генератор на случайни числа и да се сравняват за константно време. Как става това в PHP, показва Сигурни случайни числа и токени в PHP.

Съвет

Дайте на всеки клиент и всеки партньор отделен ключ с точно онези права, от които се нуждае. Тогава изтекъл ключ може да се блокира поотделно, без да се прекъсват всички други свързвания.

Поставяне на граници: размер, тип и темпо

Един API трябва да приема само онова, което очаква. Това започва с типа на съдържанието: крайна точка, която обработва JSON, отхвърля всичко друго. Максималният размер на заявката ограничавате на няколко нива, в уеб сървъра и в PHP чрез post_max_size. Тази граница спада и към преходните мерки, които php.net е посочил за PHP2Shell. Как се избира смислено, описва Смислено ограничаване на post_max_size и upload_max_filesize.

Ограничаването на честотата защитава от подбиране на идентификатори и от претоварване. То може да се реализира в уеб сървъра, във предхождащо прокси или в приложението. Важно е границите да важат за всеки ключ или потребител, а не само за всеки IP адрес.

За API, които се извикват директно от браузъра, се добавя CORS, тоест правилата кои чужди уебсайтове могат да правят заявки. Задавайте тези заглавни части само ако такива извиквания наистина са предвидени, и назовавайте разрешените произходи поотделно, вместо да допускате всеки произход. Заместител, който разрешава всички уебсайтове, при крайни точки с вход е почти винаги грешка.

Накрая журналът: неуспешните входове, отхвърлените токени и отказаните достъпи принадлежат в журнала, самите токени не. Без тези записи една атака срещу API остава невидима.

Как помага PHP SOS конкретно?

  • Отчитаме всички интерфейси на Вашите PHP системи, включително забравените и вътрешните, и проверяваме кои са публично достъпни.
  • Четем логиката на правата и тестваме целенасочено дали чужди записи могат да бъдат извлечени.
  • Определяме граници за размер, тип и темпо в уеб сървъра и PHP и ги съгласуваме с Вашите клиенти.
  • За цялостна проверка отвън комбинираме това с одит на сигурността и тест за проникване.

Заключение: Един API е толкова сигурен, колкото е най-небрежната му крайна точка. Който проверява правата за всеки обект, поставя ясни граници и поддържа грешките кратки, затваря най-честите уязвимости много преди някой да ги търси целенасочено.

Често задавани въпроси

Достатъчен ли е API ключ като защита?

За чувствителни данни не. API ключът обикновено идентифицира приложение, а не потребител, и лесно се предава нататък. OWASP REST Security Cheat Sheet съветва API ключовете да не се ползват като единствена защита за чувствителни ресурси.

Какво е право върху обект и защо толкова често липсва?

Има се предвид проверката дали влезлият потребител има право да вижда или променя точно този запис. Често липсва, защото разработчиците проверяват само дали изобщо някой е влязъл. Тогава е достатъчно да се промени идентификатор в URL, за да се извлекат чужди данни.

Защитава ли добре защитен API от PHP2Shell?

Не. PHP2Shell е в интерпретатора на PHP и действа при засегнатите режими на работа, преди Вашият код изобщо да се изпълни. Срещу това помага само актуализация на PHP с рестарт. Ограниченията за размера на заявките са все пак смислени и спадат към преходните мерки на php.net.

Какви статус кодове трябва да връща един API при грешки, свързани със сигурността?

Обичайни са 401 без валиден вход, 403 при липса на право, 405 при непозволен метод, 413 при твърде голяма заявка, 415 при грешен тип на съдържанието и 429 при твърде много заявки. Самият отговор остава кратък и без вътрешни подробности.

Източници

Незабавен контакт

Всеки час има значение. Пишете ни сега.

Опишете накратко системата, версията на PHP и какво сте забелязали. Ние се свързваме с Вас, уточняваме ситуацията и работим отдалечено, докато инцидентът бъде приключен и документиран.

Незабавна помощ