tavis nörttimaailmassa

EksisONE - artikkeleita ja ohjeita nörttimaailmasta

REST API ja wp-json: turvallisuusriski?

WordPressissä on tekninen ratkaisu, jota kutsutaan nimellä REST API. Se on rajapinta, joka tarjoaa suoralla osoitteella helposti koneluettavassa JSON-muodossa kaikenlaista tietoa- Se on tärkeä ominaisuus, ja aika harva oikeasti tietää mikä se on ja mitä tekee. Monet lisäosat sitä mainostavat käyttävänsä tai ainakin tukevansa. REST API:n olemassaoloon herätään yleensä kahta kautta. Joko on googletettu ja törmätty varoituksiin sen riskeistä tai on seurattu logeista liikennettä ja huomattu bottien suunnaton mielenkiinto wp-json hakemistoon.

REST API jakaa kaiken mahdollisen julkisen tiedon jokaisesta artikkelista, sivusta, kategoriasta, tageista ja muista WordPressin data- ja sisältötyypeistä. Ja myös julkaisseet käyttäjätkin kuuluvat datatyyppiin. Kun mikä tahansa ohjelma, lisäosa tai botti haluaa keskitetysti yhdellä pyynnöllä sivuston kaikki tiedot, niin REST API mahdollistaa sen. Eikä se liity pelkästään tiedon saantiin, vaan REST API mahdollistaa myös sisällön muokkaamisen ja luomisenkin.

REST API avaa sisällön

Nyt aletaan olla ongelmien ytimessä. Saatat sulkea boteilta pääsyn sisältöön. Muuta ei tarvita kuin user agentin muuttaminen vastaavaksi kuin tavallisella käyttäjällä, piipahdus yhdessä osoitteessa ja botti on saanut kertalaakista koko sisällön.

Jos WordPressiin on asennettu sisältöä muokkaava plugin, jossa on aukko, niin sama botti saa kertalaakista muutettua tai poistettua koko sisällön.

REST API ei tyydy pelkästään sisältöön, vaan kaikki julkiset tiedot saadaan käyttäjistä, jotka ovat julkaisseet jotain. Käyttäjistä ei paljasteta sähköpostiosoitetta eikä salasanaa, mutta kaikki muu näkyy. Woocommercen asiakkaat eivät näy, koska ostostaan huolimatta (joka on teknisesti julkaisu ja kommentti), heitä ei näytetä julkaisseina käyttäjinä. Tosin, taannoin WordPressissä oli hetken bugi, joka laittoi jokaisen rekisteröityneen käyttäjän maailmalle näkyväksi.

Automatticin mukaan REST API ei ole minkäänlainen turvallisuusriski. Ei se varsinaisesti olekaan, koska se näyttää vain tiedot, jotka olisivat muutenkin julkisia. Sisältöön pääsee käsiksi tulemalla sivustolle ja jos klikkaat kirjoittajan nimeä, niin saa samat tiedot kuin mitä REST API tarjoaa. Kyse ei ole niinkään suorasta turvallisuusriskistä, vaan laajemmassa merkityksessä yksityisyys ja näkyvyysongelmasta. Sekä siitä, että REST API:n toimintaa ei pysty asetuksista estämään tai rajoittamaan.

Jos sinulla on sisältöä, jota et halua maailmalle suoraan, niin REST API tekee toiveesi tyhjäksi. Samaten jos sivuston luonne on sellainen, että kirjoittajien ei tarvitsisi olla suoraan näkyvissä ja olet estänyt PHP:llä näkyvyyden artikkeissa, niin REST API paljastaa kaiken kuitenkin.

Aikaisemmin botin piti ryömiä koko sisältö läpi saadakseen varastettua sisällön. Enää ei tarvitse. Koko sisältö saadaan yhdellä ainoalla http-pyynnöllä. Samalla kun Automattic halusi helpottaa JSON-pohjaisten sisältöön liittyvien palvelujen toimintaa, niin he sallivat sisältövarkaille koko sivuston rakenteen ja sisällön kopioimisen. Asian olisi saanut totetutettua vielä helpommin vain tarjoamalla suora kopio tietokannasta.

Se, että julkaisseista käyttäjistä julkaistaan käytännössä kaikki mahdollinen, ei kuulemma ole riski. Mutta jos mietitään asiaa sitä kautta, että WordPressin oletuksena on, että käyttäjän nimi on myös näyttönimi (display name), joka on salassa pidettävä käyttäjätunnus, niin riski on selvä. Hyökkääjän on aina tiedettävä kasi asiaa, käyttäjätunnus ja salasana. Nyt WordPress paljastaa käyttäjätunnuksen.

Sähköpostiosoitekin on suojattu – paitsi että lisääntyvä tapa WordPressin ylläpidossa on käyttää sähköpostiosoitetta myös näyttönimenä ja käyttäjätunnuksena. Sallitaan niin spämmikeruu kuin hyökkäyksen helpottaminen.

Tokikaan tilanne ei ole aivan noin surkea, jos rekisteröitynyt käyttäjä ei julkaise yhtään mitään, ei edes kommentteja, ja kirjoittajat huolehtivat vahvoista salasanoista. Sisällön suhteen ollaankin riippuvaisempia koodareista.

Kokeile itse mitä saat sivustostasi irti:

https://www.example.tld/wp-json/wp/v2/users
https://www.example.tld/wp-json/wp/v2/posts

REST API ja rajoitukset

Vaikka REST API ei ole mukana WordPressin perusasetuksissa, niin sen estäminen on melkoisen helppoa. Yksinkertaisin tapa on estää kokonaan serverillä tai .htaccess -tiedostossa /wp-json/wp/v2/ polku. Tuossa on tosin potentiaalinen ongelma ja riski, että heitetään lapsi pesuveden mukana. Paitsi että WordPressin ydin nojautuu REST API:n käyttöön (kokeile mm. jättää luonnos auki vuorokaudeksi ja katso mitä tapahtuu, kun WordPress haluaa kirjautua taustalla uudestaan), niin osa lisäosista tarvitsee nyt jo REST API:a. Huomenna saattaa tulla lisäosa, joka kytkee luvallisesti sivustofarmin tai verkkokauppojen sisältöä toisiinsa hyödyntäen REST API:a ja oletkin estänyt sen.

On löydettävä kultainen keskitie, jossa estetään sisältövarkaus, mutta sallitaan luvallinen käyttö. Sellainen keskitie on olemassa. Sallitaan REST API ainoastaan kirjautuneille käyttäjille, tai tiukimmillaan vain administrator-tunnukselle.

functions.php

Lapsiteeman (ethän käytä teemaa tähän, ethän) functions.php on tässäkin yksi tapa ratkaista asia. Oikeammin, käytä mielummin Snippets-lisäosaa aina, kun on tarvetta säätää functions.php -tiedostoa.

Tämä estää kaikilta, jotka eivät ole kirjautuneina:


add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
if ( ! is_user_logged_in() ) {
return new WP_Error( 'rest_not_logged_in', 'You are not currently logged in.', array( 'status' => 401 ) );
}
return $result;
});

 

Pykälää tiukempi edellyttää, että pyyntö tulee administrator-oikeuksilla:


add_filter( 'rest_authentication_errors', function( $result ) {
if ( ! empty( $result ) ) {
return $result;
}
if ( ! is_user_logged_in() ) {
return new WP_Error( 'rest_not_logged_in', 'You are not currently logged in.', array( 'status' => 401 ) );
}
if ( ! current_user_can( 'administrator' ) ) {
return new WP_Error( 'rest_not_admin', 'You are not an administrator.', array( 'status' => 401 ) );
}
return $result;
});

Disable REST API

Yleinen nykkisääntö on, että jos jokin asia on helposti toteutettavissa ilman lisäosaa, niin silloin lisäosaa ei käytetä. Mutta kuten aina, niin koodisnippetejä ei ylläpidä kukaan ja jos ympäristö muuttuu oleellisesti, niin joutuu itse etsimään korjaussarjaa. Lisäosia taasen yleensä ainakin jollain tavoin ylläpidetään.

Ikiaikainen wordpress-dilemma: painitaan helppokäyttöisyyden ja asennuksen sekä tietokannan paisumisen välillä.

En ole kokeillut, mutta tätä on käytetty paljon ja Google löytää huomattavan vähän negatiivisia kommentteja:

https://wordpress.org/plugins/disable-json-api/

 

Varnish

Itse käytän Varnishia. Ainakin siihen asti, että tulee jokin perusteltu syy tehdä asiat toisin,

Syntaksi on hyvin simppeli. Käytän omaa vcl.tiedostoa per virtual host ja jokaisesta wordpress-asennuksesta löytyy tämä. Jos käyttäjä ei ole kirjautunut, eli cookieta ei ole asennettu, niin annetaan error 403.

vcl_recv {
...
# REST API
if ( !req.http.Cookie ~ "wordpress_logged_in" && req.url ~ "/wp-json/wp/v2/users" ) {
   return(synth(403, "Unauthorized request"));
}
...
}

Lopuksi

REST API:n rajoittaminen ei ole prioriteettilistan ykkönen, mutta sen saa korjattua niin helposti, että olla tekemättä on jo melkoista laiskuutta. Tosin, jos et rajoita ylipäätään mitenkään bottiliikennettä, niin ei REST API ole myöskään oleellinen asia fiksata.