You are here: TUTWiki>Tietoturva/Tutkielmat>Tutkielmat?>PhpHyokkaykset (revision 1)

TTY / Tietoturvallisuuden jatkokurssi / Harjoitustyö 2012 / Luonnosvaihe

Sampo Tolvanen

PHP-hyökkäykset

Johdanto

PHP (Hypertext Processor) on suosittu, alkuperäisesti dynaamisten www-sivujen luontiin suunniteltu skriptikieli. Web-sovellusten tietoturva on tärkeää, sillä ne ovat usein yhteydessä suuriin tietokantoihin sekä ne voivat olla saatavissa suurelle määrälle käyttäjiä. Web-sovellusten yleisien tietoturva-asioiden lisäksi PHP-kielen ominaisuudet aiheuttavat lisätarpeita tietoturvasta huolehtimiseen. Työn tarkoituksena on antaa lukijalle kuva erilaisilla tasoilla olevista tietoturvauhkista ja siitä miten niihin voi varautua.

Vapaamuotoinen syöte

Käyttäjä voi antaa PHP:lle syötettä lukuisilla eri tavoilla. Yleisimmät näistä ovat muuttujat $_GET ja $_POST. Muuttuja $_GET saa tyypillisesti arvonsa lomakkeen tai selaimen osoiterivin kautta. Muuttujan $_POST on tarkoitus sisältää käyttäjän lähettämiä lomaketietoja. Ei tule kuitenkaan unohtaa että muissakin käyttäjältä saaduissa tiedoissa, kuten selaimen versiossa voi olla vapaamuotoista syötettä. Yleisimpien tapojen joukossa hyökätä näitä muuttujia käyttäen ovat esimerkiksi tietokantasovellusten SQL-injektiot sekä XSS eli Cross Site Scripting.

Yksi tärkeimmistä ohjeista on että käyttäjän syötteeseen ei pidä luottaa. Syötteen tarkistaminen on erityisen tärkeää silloin kun siitä muodostetaan suoritettavaa koodia. Myös esimerkiksi muuttujien alustus johonkin järkevään arvoon voi parantaa tietoturvaa. PHP on heikosti tyypitelty kieli, eli muuttujan tyyppi voi vaihtua kesken suorituksen. PHP:n suorituksen aikana tapahtuneita virheilmoituksia ei pidä myöskään tulostaa suoraan selaimeen, sillä ne voivat paljasta tietoa järjestelmän toiminnasta.

SQL-injektioissa käyttäjä rikkoutuu syötteen avulla ulos SQL-kyselyn rakenteesta ja pääsee muokkaamaan kyselyä haluamakseen. SQL-injektioiden ehkäiseminen on yksinkertaista esimerkiksi käyttäen PHP:n mysqli- tai pdo-laajennusta. PHP:n mysql-laajennuksen käyttämistä ei enää suositella. Uudemmat laajennukset mahdollistavat SQL-kyselyt muodostamisen käyttäen valmisteltuja lausekkeita (Prepared statements), joissa SQL-kyselyyn kirjoitetaan käyttäjän syötteiden sijaan merkkejä, jotka kertovat missä kohtaa kyselyä käyttäjän syötteiden tulee olla. Kyselyn suoritusvaiheessa syötteet sijoitetaan kyselyyn niille määritetyssä järjestyksessä. Seuraavassa koodiesimerkissä näytetään PDO-kysely.

<?php
$sth = $db->prepare('SELECT * FROM products WHERE category = ? AND price < ?');
$sth->execute(array('potato', '4')); 

Valmisteltuja lausekkeita hyödyntävän kirjaston käyttäminen ei kuitenkaan takaa SQL-injektioita mahdottomaksi, jos esimerkiksi olettaa jonkin tiedon olevan käyttäjän muokkaamattomissa ja syöttää sen suoraan kyselyyn.

Kaikki käyttäjältä saatava tulostettava syöte on käsiteltävä, jottei sivulle saa sisällytettyä HTML:ää eikä javascriptiä. XSS:n torjumiseen PHP:ssä voi käyttää esimerkiksi funktiota htmlspecialchars, joka muuttaa HTML-merkit entititeeteiksi eli merkkiviittauksiksi, jotka näkyvät käyttäjälle tulostettuina selaimessa. Laajoissa projekteissa kaiken käyttäjän syötteen ohjaaminen käsin tällaisen funktion kautta on kuitenkin työlästä ja virhealtista. Käyttäen mallinejärjestelmää, sivun rakenteen voi rakentaa erillistä merkintäkieltä käyttäen, jossa syötteet käsitellään automaattisesti. Seuraavassa yksinkertaisessa esimerkissä näytetään miten merkintäkieltä voi käyttää.

Username: {$username}
Description: {$userdescription}

Tulostusvaiheessa mallinejärjestelmälle syötetyt muuttujien arvot sijoitetaan oikeille kohdilleen. PHP:n sisäänrakennettujen funktioiden avulla on saatu aikaan runsaasti erilaisia tietoturva-aukkoja. Haavoittuvuutta käyttäen voi olla mahdollista päästä esimerkiksi suorittamaan käyttäjän koodia, aiheuttaa XSS-aukkoja, puskurin ylivuotoja, muistin korruptoitumista tai Denial of Service-hyökkäyksiä. PHP-ohjelmoijan on hyvä olla tietoinen haavoittuvuuksista, varsinkin jos käyttää vanhaa PHP-versiota. Mikäli käytössä on haavoittuva PHP:n versio, se on altis hyökkäyksille, koska myös hyökkääjät tarkastelevat haavoittuvuuksien listaa. Vanha ja haavoittuva PHP-versio on syytä päivittää uudempaan. Mikäli mahdollinen ulkoinen palveluntarjoaja ei toteuta päivitystoimenpiteitä, sivuston voi harkita sijoittavansa muualle.

Sivustolta vastaanotettavat lomakevastaukset

Sivujen suunnittelussa lomakkeiden tiedoille annetaan tietty rakenne, jossa käyttäjän syöttämä tieto halutaan vastaanottaa. PHP-ohjelmoija ei kuitenkaan voi olettaa että vastaanotettujen tietojen rakenne on edelleen sama kuin se on käyttäjälle annettu. Käyttäjä pystyy muokkaamaan lomakkeita haluamallaan tavalla. Web-selaimen toiminnot eivät ole pakollisia. HTMLlomakkeita voi muokata kuitenkin helposti selaimessa käyttämässä erillisiä lisäosia. Kaikki näistä hyökkäyksistä voidaan kuitenkin ehkäistä kirjoittamalla koodi huolellisesti ja tarkastaen syötteen tyyppi. Esimerkiksi HTML:n text-tyyppisen input-elementin tyypin voi vaihtaa tyypiksi textarea, jolloin syötteeseen voi lisätä myös rivinvaihtoja. Esimerkiksi seuraavanlaista sähköpostin lähettämiseen tarkoitettua lomaketta voidaan käyttää roskapostin lähettämiseen.

<?php
if ($_POST['sendmail']) {
  $fromname = $_POST['fromname'];
  $from = $_POST['from'];
  $to = 'repicient@somemail.xxx';
  $subject = 'the subject';
  $message = 'hello';
  $headers = 'From: ' . $fromname . "\r\n" .
   'Reply-To: ' . $from ."\r\n" .
   'X-Mailer: PHP/' . phpversion();

  mail($to, $subject, $message, $headers);
}

Käyttäjä voi injektoida tällä tavoin haluamiaan headereita. $_POST['from']:n sisältö voisi olla esimerkiksi ”sender@othermail.xxx Cc: victim@anothermail.xxx”. Hyökkäys on luonteeltaan hyvin yksinkertainen eikä mitenkään erityinen. PHP-ohjelmoijalle voi syntyä harhakuvitelma selaimen mahdollisuuksien perusteella. Tässä tapauksessa käyttäjän syötteen voisi vielä tarkastaa säännöllisellä lausekkeella (Regular expression), jotta käyttäjän syöte on halutussa muodossa. Hyökkäys voi toimia myös esimerkiksi muuttamalla tavallinen tekstikenttä taulukkomuotoon esimerkiksi multiple select -elementillä. Seuraava koodinpätkä havainnoi tietynlaisen flatfile-tietokannan hyökkäystä.

<?php

if ($_POST['form']) {

  if (strlen($_POST['somecolumn']) < 100) {
      include 'data/messages.php';
      $data['somecolumn'] = $_POST['somecolumn'];
      $file = '<?php \n' . '$data = ' . var_export($data, true) . ';';
      $f = fopen(”data/messages.php”, ”w”);
      fwrite($f, $file);
      fclose($f);
  }
}

Hyökkääjä voi aiheuttaa sen että viestit näyttävä sivu saa aikaan jokainen kerta noticen, kun käsillään taulukkoa vaikka oletuksena tiedon piti olla tekstiä. Lisäksi funktio strlen ei laske tekstin pituutta toivotulla tavalla, vaan kertoo merkkijonon ”Array” pituuden. Tällä tavoin hyökkääjä voi aiheuttaa Denial of Service -hyökkäyksen, koska dataa voi tallentaa tietorakenteeseen nopeasti PHP:n post_max_size -direktiivin määrittämän rajan mukaisen määrän tietoa, joka on oletuksena 8 megatavua [1]. Tämän ongelman voi ratkaista testaamalla onko saatu syöte taulukkomuotoinen.

Injektioiden ja rakenteen muokkaamisen lisäksi lomakkeen arvoja voidaan muokata. Esimerkiksi foorumiohjelmistossa voi olla modetaattoreille suunnattu toiminto, jossa moderaattori voi siirtää useita keskusteluaiheita kerralla keskustelualueelta toiselle. Käyttäjälle näytetään lista keskusteluaiheen otsikoista, joista käyttäjä valitsee haluamansa sekä myös alueen johon aiheet siirretään. Tässä välissä käyttäjä muokkaa monivalintaelementin id-arvoja sellaisia aiheita vastaaviksi, joihin hänellä ei ole näkyvyyttä eikä lukuoikeutta. Mikäli ohjelma ei erikseen tarkista jokaisen siirrettävän aiheen oikeuksia, käyttäjä voi näin onnistua saamaan itselleen tietoa johon hänen ei ollut tarkoitus päästä käsiksi.

PHP:n file upload -toiminnallisuus

PHP-kielessä on mahdollisuus tallentaa palvelimelle käyttäjän lähettämiä tiedostoja. Huolimattomasti tehdyn tiedostonlähettämislomakkeen avulla voi kuitenkin auheuttaa vakavia tietoturva-ongelmia, kuten mahdollisuuden päästä suorittamaan koodia tai aiheuttaa Denial of service -hyökkäyksen. PHP:n manuaalin ohjeisto ei ole riittävä, jotta pystyisi rakentamaan turvallisen tiedostojen lähettämiseen tarkoitetun lomakkeen. Esimerkiksi tiedostojen siirtämiseen käytettävän funktion koodiesimerkeissä [2] esiintyy oikeastaan kaikki puutteet mitä tiedostojenlähetyslomakkeessa voi esiintyä.

Mikäli upload-lomakkeella lähetettyjen tiedostojen tulee olla vapaasti selattavissa kansiorakenteessa, tiedostot eivät saa olla suoritettavissa. Käyttäjälle ei pidä sallia lähettää Apache-palvelimelle .htaccess -tiedostoa, sillä tällöin käyttäjä voi päästä suorittamaan koodia, vaikka tiedoston pääte ei olisikaan PHP-suoritettavien tiedostopäätteiden listassa. Joissakin PHP-konfiguraatioissa myös tuplatiedostopäätteiset tiedostot voivat päätyä suoritettaviksi. Ongelman ratkaisuna on tarkistaa tiedostonimi säännöllisellä lausekkeella, joka varmistaa että tiedostonimessä on ainoastaan sallittuja merkkejä ja tiedostopääte on sallittujen joukossa. PHP:n upload-komento ylikirjoittaa tiedoston mikäli se on jo valmiiksi olemassa.

Lisäksi tulee olla tarkkana miten tiedostoja sisällyttää näytettävälle sivulle. Esimerkiksi PHP:n funktiot include ja require suorittavat kohdetiedostossa olevan PHP-koodin tiedostopäätteestä huolimatta. Sen sijaan esimerkiksi funktio readfile ei koskaan suorita PHP-koodia. Palvelimelle ladattavan tiedoston ei kuitenkaan välttämättä tarvitse olla tiedostopäätteeltään tietynlainen jotta käyttäjä pääsisi suorittamaan palvelimella haluamaansa koodia. Löydettyään remote file inclusion -pohjaisen tietoturva-aukon hyökkääjä pääsee ajamaan koodia tiedostopäätteestä huolimatta.

Koodia voi upottaa myös tiedostoihin joiden tapauksessa sen ei olettaisi olevan mahdollista. Esimerkiksi jpg-kuvan exif-tageihin voi upottaa PHP-koodia niin että se pysyy tekstimuotoisena [3]. Kenttiin on mahdollista sisällyttää myös HTML:ää tai javascript-koodia, joka voi tulla suoritetuksi, jos kentän sisältö tulostetaan selaimessa eikä ohjelmoija ole ohjannut tulostetta esimerkiksi htmlspecialchars-funktion läpi. Tiedoston mime-tyyppi on myös väärennettävissä käyttäjän puolelta. Kuvatiedostojen tarkastamiseen saatetaan joskus käyttää PHP:n getimagesize-funktiota, joka ei kuitenkaan yksinään takaa että tiedosto on turvallinen, sillä kuva voi toimia tavallisesti siihen upotetusta koodista huolimatta.

Päätelmät / yhteenveto

PHP-kieleen liittyvien tietoturvauhkien torjunnassa käyttäjän syötteen tarkistaminen ja käsittely ovat etusijalla, sillä moni uhkista aiheutuu alun perin odottamattoman syötteen takia. PHP:n ja sen ominaisuuksista on tärkeää olla tietoinen, jotta uhkiin ylipäätään osaa varautua. Kaikki tietoturvauhkat eivät suinkaan välttämättä aiheudu ohjelmoijan kirjoittamasta koodista, jos ohjelmistoylläpito laiminlyödään. Moni PHP:ssä esiintyvistä tietoturvauhkista on mahdollinen myös muiden dynaamisia web-sivuja tuottavien ohjelmointi- ja skriptikielien tapauksessa.

Lähteet

SivuTiedotLaajennettu edit

Vaativuus Jatko
Valmius Valmisteilla
Tyyppi Ydin
Luokitus Uhkat
Mitä Luottamuksellisuus
Miltä Ihmisetön uhka
Missä Organisaatio
Kuka Titu-ammattilainen
Milloin Ennakolta
Miksi Hyvä tapa
Print version |  PDF  | History: r4 < r3 < r2 < r1 | 
Topic revision: r1 - 01 Nov 2012 - 23:45:37 - SampoTolvanen?
 

TUTWiki

Copyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TUTWiki? Send feedback