WordPressin nonce-tarkistukset ja käyttöoikeudet omassa lisäosassa

Oma WordPress-lisäosa voi tallentaa asetuksia, muokata sisältöjä tai käynnistää taustatehtäviä. Jokainen tällainen toiminto tarvitsee palvelimella tehtävät tarkistukset. Pelkkä hallintapaneeliin sijoitettu painike ei…
Oma WordPress-lisäosa voi tallentaa asetuksia, muokata sisältöjä tai käynnistää taustatehtäviä. Jokainen tällainen toiminto tarvitsee palvelimella tehtävät tarkistukset. Pelkkä hallintapaneeliin sijoitettu painike ei suojaa sen taustalla olevaa käsittelijää.
Nonce-tarkistus ja käyttöoikeuden tarkistus ratkaisevat eri ongelmia. Nonce auttaa torjumaan tilanteita, joissa käyttäjän selain yritetään saada lähettämään tahaton toimintapyyntö. Käyttöoikeus puolestaan määrittää, saako kyseinen käyttäjä suorittaa toiminnon.
Näiden lisäksi lisäosan pitää tarkistaa vastaanotettavat tiedot ja käsitellä tulostettava sisältö turvallisesti. Toimiva kokonaisuus muodostuu useasta tarkistuksesta, joista jokaisella on oma tehtävänsä.
Mitä nonce tarkoittaa WordPressissä?
Nonce on toimintoon liittyvä tarkiste, joka voidaan lisätä esimerkiksi lomakkeen piilokenttään. Palvelin tarkistaa sen ennen pyynnön hyväksymistä.
WordPressin nonce ei nimestään huolimatta ole aidosti kertakäyttöinen. Sama tarkiste voi kelvata useita kertoja voimassaoloaikansa aikana. Oletusasetuksilla todellinen voimassaolo vaihtelee noin 12–24 tunnin välillä.
Nonce auttaa suojautumaan CSRF-hyökkäyksiltä eli sivustojen väliseltä pyyntöväärennökseltä. Se ei kuitenkaan todista, että käyttäjällä olisi oikeus muuttaa asetuksia, eikä estä saman hyväksytyn pyynnön toistamista. WordPressin nonce-järjestelmä
Ajattele esimerkiksi asetusten tallentamista: palvelimen täytyy tarkistaa sekä pyynnön tarkiste että käyttäjän oikeus muuttaa kyseisiä asetuksia.
Käyttöoikeus tarkistetaan erikseen
WordPressissä oikeuksia tarkistetaan tavallisesti current_user_can()-funktiolla. Sille annetaan tarvittava capability eli käyttöoikeus:
if ( ! current_user_can( 'manage_options' ) ) {
wp_die(
'Sinulla ei ole oikeutta muuttaa asetuksia.',
'',
array( 'response' => 403 )
);
}
manage_options sopii moniin sivustotason asetustoimintoihin. Sisältöjen käsittelyssä kannattaa käyttää kyseiseen tehtävään sopivaa oikeutta.
Yksittäisen artikkelin muokkausoikeus voidaan tarkistaa näin:
current_user_can( 'edit_post', $artikkeli_id );
Kohteen tunniste on olennainen: käyttäjä voi saada muokata omia artikkeleitaan mutta ei muiden sisältöjä.
Tarkista käyttöoikeuksia roolinimen sijaan. Roolien oikeuksia voidaan muuttaa, joten pelkkä käyttäjän luokittelu ylläpitäjäksi tai kirjoittajaksi ei kuvaa kaikkia tilanteita. WordPressin käyttöoikeustarkistukset
Painikkeen piilottaminen ei suojaa käsittelijää
Hallintavalikon rajaaminen on hyvä osa käyttöliittymää. Käyttäjälle ei tarvitse näyttää toimintoja, joita hän ei saa käyttää.
Varsinainen suojaus kuuluu kuitenkin palvelimelle. Pyyntö voidaan lähettää suoraan käsittelyosoitteeseen avaamatta lomakesivua lainkaan.
Sama koskee JavaScriptiä. Selaimessa tehty tarkistus parantaa käyttökokemusta, mutta käyttäjä voi muuttaa lähetettäviä arvoja tai ohittaa käyttöliittymän.
Tee tarkistukset jokaisessa tietoja muuttavassa käsittelijässä. Jos sama toiminto on käytettävissä lomakkeella, AJAX-pyynnöllä ja REST-rajapinnassa, jokaisen reitin pitää noudattaa samoja käyttöoikeusperiaatteita.
Lisää nonce lomakkeeseen
Seuraava lomake-esimerkki kuuluu oman lisäosan jo rekisteröidyn asetussivun tulostusfunktioon. Esimerkki ei yksin muodosta kokonaista lisäosaa.
function oma_lisaosa_asetussivu() {
if ( ! current_user_can( 'manage_options' ) ) {
wp_die(
'Ei käyttöoikeutta.',
'',
array( 'response' => 403 )
);
}
$otsikko = get_option( 'oma_lisaosa_otsikko', '' );
?>
<div class="wrap">
<h1>Lisäosan asetukset</h1>
<form
method="post"
action="<?php echo esc_url(
admin_url( 'admin-post.php' )
); ?>"
>
<input
type="hidden"
name="action"
value="oma_lisaosa_tallenna"
>
<?php
wp_nonce_field(
'oma_lisaosa_tallenna_asetukset',
'oma_lisaosa_nonce'
);
?>
<label for="oma-otsikko">Otsikko</label>
<input
id="oma-otsikko"
name="otsikko"
type="text"
value="<?php echo esc_attr( $otsikko ); ?>"
required
>
<?php submit_button( 'Tallenna' ); ?>
</form>
</div>
<?php
}
Piilotettu action-kenttä ohjaa pyynnön oikeaan käsittelijään. Noncen toimintotunniste ja kentän nimi ovat eri asioita: molempien täytyy vastata myöhemmässä tarkistuksessa käytettyjä arvoja.
required auttaa selaimessa, mutta palvelimen pitää silti tarkistaa kentän sisältö.
Tarkista pyyntö ennen tallentamista
Lomakkeen vastaanottava toiminto liitetään admin_post_-koukkuun:
add_action(
'admin_post_oma_lisaosa_tallenna',
'oma_lisaosa_tallenna'
);
function oma_lisaosa_tallenna() {
if ( 'POST' !== ( $_SERVER['REQUEST_METHOD'] ?? '' ) ) {
wp_die(
'Pyyntömenetelmä ei ole sallittu.',
'',
array( 'response' => 405 )
);
}
if ( ! current_user_can( 'manage_options' ) ) {
wp_die(
'Ei käyttöoikeutta.',
'',
array( 'response' => 403 )
);
}
check_admin_referer(
'oma_lisaosa_tallenna_asetukset',
'oma_lisaosa_nonce'
);
if (
! isset( $_POST['otsikko'] )
|| ! is_string( $_POST['otsikko'] )
) {
wp_die(
'Otsikko puuttuu tai on väärässä muodossa.',
'',
array( 'response' => 400 )
);
}
$otsikko = sanitize_text_field(
wp_unslash( $_POST['otsikko'] )
);
if ( '' === trim( $otsikko ) ) {
wp_die(
'Otsikko ei saa olla tyhjä.',
'',
array( 'response' => 400 )
);
}
update_option( 'oma_lisaosa_otsikko', $otsikko );
wp_safe_redirect(
admin_url( 'options-general.php?page=oma-lisaosa' )
);
exit;
}
Vaihda paluuosoitteen oma-lisaosa oman asetussivusi tunnisteeksi. Käsittelijä tallentaa tiedon vasta kaikkien tarkistusten jälkeen.
admin_post_ käsittelee kirjautuneen käyttäjän pyynnön, mutta kirjautuminen ei vielä anna asetusten muokkausoikeutta. Siksi erillinen käyttöoikeustarkistus tarvitaan. Admin-post-käsittelijän toimintaperiaate
Ymmärrä tarkistusfunktion tehtävä
check_admin_referer() tarkistaa lomakkeesta saadun noncen määriteltyä toimintoa vasten. Epäonnistuessaan se keskeyttää käsittelyn.
Nimestään huolimatta funktio ei tarkista käyttäjän ylläpitäjän oikeuksia. Sen käyttäminen ei siis korvaa current_user_can()-kutsua. check_admin_referer()-funktion dokumentaatio
Esimerkissä pyynnön menetelmä ja käyttöoikeus tarkistetaan ensin. Tämän jälkeen varmistetaan nonce ja käsitellään tallennettava tieto.
Tarkistusten sijoittaminen ennen tietokantamuutosta on olennaista. Jo suoritettua tallennusta ei voi suojata tarkistamalla nonce vasta funktion lopussa.
Erota validointi, siistiminen ja tulostus
Validointi tarkistaa, kelpaako tieto kyseiseen käyttötarkoitukseen. Siistiminen muokkaa syötettä odotettuun muotoon. Tulostuksen suojaus puolestaan riippuu siitä, mihin tieto sijoitetaan.
Esimerkin otsikossa tarkistetaan ensin, että vastaanotettu arvo on merkkijono. wp_unslash() poistaa WordPressin syötekäsittelyyn liittyvän vinoviivauksen, minkä jälkeen sanitize_text_field() käsittelee arvon tavallisena tekstinä.
Lopuksi varmistetaan, ettei tulos ole tyhjä. Jos kenttä hyväksyisi vain ennalta määritellyt vaihtoehdot, arvo pitäisi tarkistaa sallittujen vaihtoehtojen luettelosta. Syötteen käsittely WordPressissä
Tallennettu arvo suojataan uudelleen tulostuspaikan mukaan. Lomakekentän value-attribuutissa käytetään esc_attr()-funktiota. Tietojen siistiminen tallennettaessa ei poista tätä tarvetta.
AJAX ja REST tarvitsevat samat perusrajaukset
AJAX-käsittelijässä noncen tarkistamiseen käytetään tavallisesti check_ajax_referer()-funktiota. Myös siinä käyttäjän oikeudet tarkistetaan erikseen ennen muutoksia.
REST-reitissä käyttöoikeusehto sijoitetaan permission_callback-funktioon. Suojattua asetustoimintoa ei pidä avata kaikille palauttamalla siinä aina true. Omien REST-reittien käyttöoikeudet
REST-pyyntöjen tunnistautuminen riippuu käytetystä menetelmästä. Selaimen evästepohjaisessa käytössä nonce kuuluu toteutukseen eri tavalla kuin esimerkiksi ulkoisen sovelluksen tunnistautumisessa.
Älä siirrä lomake-esimerkkiä rajapintaan sellaisenaan. Säilytä samat turvallisuusperiaatteet, mutta käytä kyseisen pyyntötyypin tunnistautumis- ja vastauskäytäntöjä.
Huomioi vanheneminen ja toistuvat pyynnöt
Pitkään avoinna ollut lomake voi sisältää vanhentuneen noncen. Käyttäjälle kannattaa kertoa ymmärrettävästi, että sivu täytyy päivittää ennen uutta yritystä.
Älä ratkaise ongelmaa poistamalla tarkistusta. Selvitä myös, onko käyttäjäkohtainen lomake joutunut yhteiseen sivuvälimuistiin.
Koska WordPressin nonce ei ole kertakäyttöinen, kaksoisnapsautus voi lähettää saman pyynnön uudelleen. Rahaliikenteessä tai muussa kertaluonteisessa toiminnossa tarvitaan erillinen tapa tunnistaa jo käsitelty tapahtuma.
Kirjautumattomien käyttäjien oletusnoncet eivät myöskään yksilöi vierailijaa. Julkinen lomake tarvitsee käyttötarkoitukseensa sopivan kokonaisratkaisun, eikä nonce yksin estä automatisoitua roskapostia.
Testaa myös hylättävät tilanteet
Onnistunut tallennus on vain yksi testitapaus. Kokeile lisäksi puuttuvaa ja väärää noncea, liian vähäisiä oikeuksia sekä vääränmuotoista syötettä.
Hyödyllinen testilista sisältää:
- Oikeutettu käyttäjä ja kelvollinen pyyntö.
- Kirjautunut käyttäjä ilman vaadittua oikeutta.
- Puuttuva tai virheellinen nonce.
- GET-pyyntö POST-käsittelijään.
- Taulukko odotetun tekstikentän tilalla.
- Tyhjä arvo siistimisen jälkeen.
- Sama pyyntö lähetettynä kahdesti.
Varmista jokaisessa hylättävässä tilanteessa, ettei tallennettu tieto muutu. Näin testaus osoittaa tarkistusten suojaavan varsinaista toimintoa, eikä ainoastaan piilottavan sen käyttöliittymää.
