hei,
olen vähän uusi php-ohjelmoinnin kanssa ja kysyisinkin mielipidettänne alla olevan koodin tietoturva-asioista. eli minulla on MySqL-kanta, johon kyseinen php-ohjelma tekee tietueen talletuksen www-sivulla olevalta lomakkeelta saamiensa tietojen perusteella:
<?php require "../../funktiot.php"; $yhteys = AvaaTietokanta(); $sivuotsikko; $teksti; //LOMAKKEEN KAIKKIIN KENTTIIN VAADITAAN ARVO if ((!empty($_POST['merkki'])) and (!empty($_POST['malli'])) and (!empty($_POST['vuosi'])) and (!empty($_POST['km'])) and (!empty($_POST['hinta']))) { $merkki = $_POST['merkki']; $malli = $_POST['malli']; $vuosi = $_POST['vuosi']; $km = $_POST['km']; $hinta = $_POST['hinta']; $okmerkki = mysql_real_escape_string(stripslashes($merkki)); $okmalli = mysql_real_escape_string(stripslashes($malli)); $okvuosi = mysql_real_escape_string(stripslashes($vuosi)); $okkm = mysql_real_escape_string(stripslashes($km)); $okhinta = mysql_real_escape_string(stripslashes($hinta)); // SQL-kysely - auton lisäys $sql="INSERT INTO autot (merkki, malli, vuosi, km, hinta) VALUES ('$okmerkki','$okmalli','$okvuosi','$okkm','$okhinta')"; if (!mysql_query($sql,$yhteys)) { $sivuotsikko = "Tallennus epäonnistui! "; $teksti = "Virhe: " . mysql_error(); } else { $sivuotsikko = "Tietojen tallennus onnistui "; $teksti = " Auton tiedot talletettu tietokantaan <br>"; $teksti .= "Merkki: " . $okmerkki . "<br>"; $teksti .= "Malli: " . $okmalli . "<br>"; $teksti .= "Vuosi: " . $okvuosi . "<br>"; $teksti .= "Km: " . $okkm . "<br>"; $teksti .= "Hinta: " . $okhinta . "<br>"; } } else { $sivuotsikko = "Tallennus epäonnistui! "; $teksti = "Virhe: Lomakkeen kaikkiin kenttiin on annettava arvo!"; } ?> <html> <head> <title><?php print "$sivuotsikko"; ?></title> </head> <body bgcolor="#ffffff"> <h2><?php print "$sivuotsikko"; ?></h2> <?php print "$teksti"; ?> <p> <a href="index.html">Takaisin etusivulle</a> </body> </html>
Mod. lisäsi kooditagit
SQL-injektion mahdollisuutta ei nähdäkseni ole, mutta XSS-aukko löytyy. Tutustu funktioon htmlspecialchars.
hei,
lueskelin tuosta htmlspecialchars-funktiosta ja olenko oikeassa, että ongelma liittyy php-sivun lopussa olevaan html-osioon?
voisitko hieman valottaa lisää tätä ongelmaa ja (mikä parasta) näyttää pienen esimerkin avulla miten ongelmsta pääsisi eroon.
olisiko ohjelman yksinkertaistamisen kannalta mielekästä poistaa php-osuudesta muuttujat $xxxxxx ja laittaa $_POST['yyyyy'] muuttujat suoraan mysql_real_escape_string() funktion sisään? onko sillä vaikutusta tietoturvaan?
$merkki = $_POST['merkki']; $malli = $_POST['malli']; $vuosi = $_POST['vuosi']; $km = $_POST['km']; $hinta = $_POST['hinta']; $okmerkki = mysql_real_escape_string(stripslashes($merkki)); $okmalli = mysql_real_escape_string(stripslashes($malli)); $okvuosi = mysql_real_escape_string(stripslashes($vuosi)); $okkm = mysql_real_escape_string(stripslashes($km)); $okhinta = mysql_real_escape_string(stripslashes($hinta));
volume kirjoitti:
lueskelin tuosta htmlspecialchars-funktiosta ja olenko oikeassa, että ongelma liittyy php-sivun lopussa olevaan html-osioon?
Kyllä.
volume kirjoitti:
voisitko hieman valottaa lisää tätä ongelmaa ja (mikä parasta) näyttää pienen esimerkin avulla miten ongelmsta pääsisi eroon.
Käyttäjä tallettaa tietokantaan esimerkiksi tiedon <Audi>
. Tulostuksessa ei näy mitään, koska selain tulkitsee tuon HTML-tagiksi. Samalla tavalla käyttäjä voi tulostaa sivujesi kautta mitä vain, HTML-muotoiluja, haitallista JavaScriptiä jne. Funktio htmlspecialchars
korvaa HTML:ssä niin sanotut erikoismerkit, jolloin esimerkiksi <
ja >
korvataan niiden vastaavilla HTML-entiteeteillä, jolloin ne tulostuvat.
Ongelmasta pääsee yksinkertaisesti eroon ajamalla kaikki ulkopuolelta tulevat tulostukset kyseisen funktion läpi.
volume kirjoitti:
olisiko ohjelman yksinkertaistamisen kannalta mielekästä poistaa php-osuudesta muuttujat $xxxxxx ja laittaa $_POST['yyyyy'] muuttujat suoraan mysql_real_escape_string() funktion sisään? onko sillä vaikutusta tietoturvaan?
Voit kutsua funktiota suoraan $_POST-alkiolla, sillä ei ole vaikutusta tietoturvaan.
missähän mättää kun tulostaminen näyttää tältä ilman htmlspecialchars-funktiota
Tietojen tallennus onnistui
Auton tiedot talletettu tietokantaan
Merkki: Porche
Malli: Boxer
Vuosi: 2000
Km: 100000
Hinta: 45000
Takaisin etusivulle
ja taas tältä kun käytän htmlspecialchars-funktiota:
Tietojen tallennus onnistui
Auton tiedot talletettu tietokantaan <br>Merkki: Porche<br>Malli: Boxer<br>Vuosi: 2000<br>Km: 155000<br>Hinta: 32500<br>
Takaisin etusivulle
tässä vielä miten liitän funktion koodiin:
<?php // ... { $sivuotsikko = "Tallennus epäonnistui! "; $teksti = "Virhe: Lomakkeen kaikkiin kenttiin on annettava arvo!"; } $okteksti = htmlspecialchars($teksti); ?> <html> <head> <title><?php print "$sivuotsikko"; ?></title> </head> <body bgcolor="#ffffff"> <h2><?php print "$sivuotsikko"; ?></h2> <?php print "$okteksti"; ?> <p> <a href="index.html">Takaisin etusivulle</a> </body> </html>
Mod. lisäsi kooditagit
Omia tekstejäsi ei tarvitse kyseisen funktion läpi ajaa, vain ne, joiden sisällöstä et ole varma. Sama periaate kuin tuon mysql_real_escape_string
-funktion kanssa, ethän senkään läpi aja koko kyselyä.
hei,
käsittääkseni en aja funktiota omille teksteilleni, vaan sille merkkijonolle, joka muodostetaan kantaan talletetusta datasta.
mielestäni ongelma johtuu siitä, että merkkijonossa on sisällytettynä html-merkkejä (<br>), jotka sitten jotenkin muuttuvat htmlspecialchars-funktiossa.
alla koodi...
<?php // ... // SQL-kysely - auton lisäys $sql="INSERT INTO autot (merkki, malli, vuosi, km, hinta) VALUES ('$okmerkki','$okmalli','$okvuosi','$okkm','$okhinta')"; if (!mysql_query($sql,$yhteys)) { $sivuotsikko = "Tallennus epäonnistui! "; $teksti = "Virhe: " . mysql_error(); } else { $sivuotsikko = "Tietojen tallennus onnistui "; $teksti = " Auton tiedot talletettu tietokantaan <br>"; $teksti .= "Merkki: " . $okmerkki . "<br>"; $teksti .= "Malli: " . $okmalli . "<br>"; $teksti .= "Vuosi: " . $okvuosi . "<br>"; $teksti .= "Km: " . $okkm . "<br>"; $teksti .= "Hinta: " . $okhinta . "<br>"; } } else { $sivuotsikko = "Tallennus epäonnistui! "; $teksti = "Virhe: Lomakkeen kaikkiin kenttiin on annettava arvo!"; } $okteksti = htmlspecialchars($teksti); ?> <html> <head> <title><?php print "$sivuotsikko"; ?></title> </head> <body bgcolor="#ffffff"> <h2><?php print "$sivuotsikko"; ?></h2> <?php print "$okteksti"; ?> <p> <a href="index.html">Takaisin etusivulle</a> </body> </html>
Mod. lisäsi kooditagit
Kyllä tuo ajetaan myös omille teksteille. Alla esimerkki.
$teksti .= "Merkki: " . htmlspecialchars($okmerkki) . "<br>";
tuolla muutoksella ohjelma OK! Kiitos avituksesta :-)
<?php $sivuotsikko = "Tietojen tallennus onnistui "; $teksti = " Auton tiedot talletettu tietokantaan: <br>"; $teksti .= "Merkki: " . htmlspecialchars($okmerkki) . "<br>"; $teksti .= "Malli: " . htmlspecialchars($okmalli) . "<br>"; $teksti .= "Vuosi: " . htmlspecialchars($okvuosi) . "<br>"; $teksti .= "Km: " . htmlspecialchars($okkm) . "<br>"; $teksti .= "Hinta: " . htmlspecialchars($okhinta) . "<br>"; ?>
ilmeisesti tietoturva on näillä muutoksilla sellaisella tasolla kuin sen pitää olla!
vielä tuli mieleen sellainen juttu, että nettiä selatessa tulee vastaan vaikka kuinka paljon sellaisia MySqL ja PHP ohjesivustoja, joissa lomakkeen syttötietoja pusketaan kantaan suoraan ilman minkäänlaista tarkastamista. jos niitä sivuja sattuu lukemaan joku sellainen (niin kuin minä), joka ei ole perillä tietoturva-asioista niin pellolle menee että kolisee.
jopa itseään kunnioittavia oppikirjojakin löytyy, joissa lomaketietoja ei tarkasteta mitenkään. sanoisin että miltei edesvastuutonta!!!
PHP:ssä oli aiemmin oletuksena käytössä magic quotes -ominaisuus, joka lisäsi lomaketietoihin automaattisesti kenoviivoja. Tällöin tietojen liittäminen suoraan kyselyyn ei ollut samalla tavalla vaarallista. Tämä selittää osan ohjeissa olevista puutteista, vaikka lukijan on tietenkin vaikeaa tietää tätä.
vielä palaan tähän asiaan:
tietoturvaahan yllä olevassa php-ohjelmassa voi varmistaa myös esim:
<?php preg_match('/^[a-zA-ZäöÄÖ]+$/',$_POST['muuttuja'])) ?>
miksi käyttää mysql_real_escape_string(stripslashes() sekä htmlspecialchars(), kun preg_match yllä olevalla käsittääkseni hoitaa saman?
volume kirjoitti:
miksi käyttää mysql_real_escape_string(stripslashes() sekä htmlspecialchars(), kun preg_match yllä olevalla käsittääkseni hoitaa saman?
Miksi käyttää säännöllisiä lausekkeita, jos tehtävään on valmis funktio, joka kaiken lisäksi toimii paremmin. Tuohan sallii vain nuo mainitut merkit.
Jos tarkoitus on sallia vain suomen kielen aakkoset, esittämäsi ratkaisu on hyvä. Usein kuitenkin tekstissä saa olla mitä tahansa, mutta se pitää kuitenkin tallentaa tietokantaan ja näyttää sivulla.
Aihe on jo aika vanha, joten et voi enää vastata siihen.