Bezbednosni aspekti
JSON:API modul je dizajniran da preuzme model podataka definisan u Drupalu putem Drupal Entity API-ja, Field API-ja i Typed Data API-ja i izloži ga kroz API koji je u skladu sa JSON:API specifikacijom, kako bi omogućio interakciju sa podacima (entitetima) koje Drupal upravlja.
Pri tome, poštuje sve Drupal sigurnosne mere za te podatke:
- Pristup entitetima se poštuje.
- Pristup poljima se poštuje.
- Pri izmeni podataka, poštuju se ograničenja validacije.
internal
zastavica se poštuje (pogledajte dokumentaciju kako može biti postavljena na definiciju entiteta, polja ili osobine).
Drugim rečima: JSON:API ne zaobilazi nijednu postojeću sigurnosnu meru i ne dodaje sopstveni sloj; koristi Drupalovu osnovu.
Bagovi u tipovima entiteta, tipovima polja i tipovima podataka mogu dovesti do sigurnosnih ranjivosti
Ipak, bagovi postoje u kodu koji implementira tipove entiteta, tipove polja i tipove podataka, kao i njihove access control handlere i validacione restrikcije. Ovo se velikim delom može pripisati Drupal nasleđu: Drupal izvorno nije imao validacione restrikcije već samo form validation callbacks; prelazak na API-first mentalitet može se smatrati završenim u Drupal core-u, ali nije garantovan za contributed ili custom module.
Ovi bagovi mogu dovesti do sigurnosnih ranjivosti; i jesu u prošlosti. Takve ranjivosti nisu ograničene na JSON:API modul; one takođe utiču, na primer, na RESTful Web Services modul kao i na bilo koji PHP kod koji koristi Entity API.
Međutim, pošto zlonameran korisnik može lakše da pristupi HTTP API-ju kao što je JSON:API ili RESTful Web Services nego PHP API-ju, ovde je potrebna dodatna pažnja. Za razliku od drugih HTTP API modula, JSON:API ima veći API surface po difoltu: svi ne-internal
entiteti su dostupni po difoltu (uz poštovanje pristupa entitetima), da bi developersko iskustvo bilo što jednostavnije.
Šest bezbednosnih preporuka
1. Važnost korišćenja stabilnih contributed modula
Sigurnosne ranjivosti uzrokovane tipovima entiteta, polja i podataka se rešavaju što je pre moguće samo za stabilne module objavljene na Drupal.org koji su pokriveni security advisory policy. Custom moduli i nestabilni contributed moduli nisu pokriveni. Ako ih koristite, budite dodatno pažljivi.
2. Provera pristupa entitetima i poljima
Bez obzira da li koristite JSON:API ili bilo koji drugi API modul, preporučuje se da auditujete pristup entitetima i poljima na Drupal sajtovima. Ovo je naročito važno ako su pisanje (write) mogućnosti JSON:API-ja omogućene.
3. Izlažite samo ono što koristite
Kada određeni resource types (tipovi entiteta + bundle-ovi) ne treba da budu izloženi, nakon što ste se uverili da im je pristup odbijen, možete ih dodatno isključiti. Da biste isključili resource type ili polje, postoji PHP API koji možete implementirati u custom modulu, ili možete koristiti JSON:API Extras contrib modul, koji daje UI za onemogućavanje resource type-ova i polja. Ovo nije uvek moguće, ali ako vlasnik sajta kontroliše sve API klijente, ovo je način da smanjite API surface na minimum.
4. Read-only režim
Ako vam je potrebno samo čitanje podataka, možete omogućiti read-only mod za JSON:API na /admin/config/services/jsonapi
. Ovo smanjuje rizik od potencijalnih, još nepoznatih bagova u validacionim pravilima i write logici. Pošto većina modernih decoupled Drupal rešenja treba samo čitanje, read-only mod je podrazumevano uključen. (U core JSON:API-ju i verziji 2.4 i novijim za contributed modul.)
5. Sigurnost kroz nevidljivost: tajna osnovna putanja
Osnovna putanja za JSON:API je po difoltu /jsonapi
. Ovo možete promeniti, npr. na /hidden/b69dhj027ooae/jsonapi
, što je jedan od načina da smanjite efikasnost automatizovanih napada. Kreirajte sites/example.com/services.yml
ako već ne postoji i dodajte:
parameters:
jsonapi.base_path: /hidden/b69dhj027ooae/jsonapi
6. Ograničite koji entity bundle-ovi mogu biti kreirani ili izmenjeni uklanjanjem određenih ruta
Ako je potrebno da možete kreirati ili menjati samo određene entity bundle-ove preko JSON:API-ja, možete implementirati event subscriber da uklonite sve POST i PATCH rute osim onih sa bele liste u custom modulu. Ovo ima efekat tek nakon isključivanja read-only moda i može zahtevati rebuild routera.
Dodajte servis u vaš services.yml fajl:
services:
mymodule.route_subscriber:
class: Drupal\mymodule\Routing\JsonapiLimitingRouteSubscriber
tags:
- { name: event_subscriber }
Kreirajte event subscriber. Ovaj primer takođe onemogućava brisanje (DELETE) sadržaja preko JSON:API-ja:
<?php
namespace Drupal\mymodule\Routing;
use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;
/**
* Klasa JsonapiLimitingRouteSubscriber.
*
* Uklanja sve DELETE rute sa jsonapi resursa radi zaštite sadržaja.
*
* Uklanja POST i PATCH rute sa jsonapi resursa osim za one koje želimo da korisnici mogu da kreiraju i menjaju putem API-ja.
*/
class JsonapiLimitingRouteSubscriber extends RouteSubscriberBase {
/**
* {@inheritdoc}
*/
protected function alterRoutes(RouteCollection $collection) {
$mutable_types = $this->mutableResourceTypes();
foreach ($collection as $name => $route) {
$defaults = $route->getDefaults();
if (!empty($defaults['_is_jsonapi']) && !empty($defaults['resource_type'])) {
$methods = $route->getMethods();
if (in_array('DELETE', $methods)) {
// Nikad ne želimo da brišemo podatke, samo da ih deaktiviramo.
$collection->remove($name);
}
else {
$resource_type = $defaults['resource_type'];
if (empty($mutable_types[$resource_type])) {
if (in_array('POST', $methods) || in_array('PATCH', $methods)) {
$collection->remove($name);
}
}
}
}
}
}
/**
* Vrati mutable resource types, koje korisnik može menjati putem API-ja.
*
* @return array
* Lista mutable jsonapi resource tipova kao ključevi.
*/
public function mutableResourceTypes(): array {
return [
'node--article' => TRUE,
'node--document' => TRUE,
'custom_entity--custom_entity' => TRUE,
];
}
}
Ograničite pristup svim JSON:API rutama dodatnom dozvolom
Kada koristite JSON:API za backend integracije, ograničene API klijente ili druge ne-javne svrhe, možda ćete želeti da pristup JSON:API-ju imaju samo korisnici sa specifičnom dozvolom. Umesto ili pored toga, dodajte sledeći kod u pomenuti route subscriber:
// Ograničite pristup svim jsonapi rutama posebnom dozvolom.
foreach ($collection as $route) {
$defaults = $route->getDefaults();
if (!empty($defaults['_is_jsonapi'])) {
$route->setRequirement('_permission', 'FOO custom access jsonapi');
}
}
Zatim definišite tu dozvolu u FOO.permissions.yml i dodelite je željenim korisničkim ulogama.
Tekst preuzet sa Drupal Dokumentacije.