Jos nyt otetaan esimerkiksi hakuskripti. Käyttäjä kirjoittaa hakuruutuun tekstiä ja painaa ENTER, jolloin tiedot laitetaan eteenpäin. Käyttäjä on voinut täydentää hakusanaansa esimerkiksi '- ja ´-merkein, jolloin oletettavasti palautetaan virhe. Miten vältän siis virheen, vaikka käyttäjä laittaisi '-merkin hakusanaansa? Toki voin PHP:llä karsia kyseiset merkit pois, mutta onko muita "häiritseviä" merkkejä kuin ' ja ´.
Selkeytettynä siis:
WHERE Jotain = 'Haku'sanani'
palauttaisi virheen
No ei siinä mitään että palauttaa virheen, mutta mitäpä jos se kirjoittaisikin siihen vaikka:
' OR ''='
Näin voisi tulla sellaisetkin rivit mitä ei haluta näyttää.
Olet siis toteuttanut tietoturva-aukon jota kutsutaan SQL-injektioksi. Kannattaa tutustua miten siltä vältytään. Aiheesta: http://xkcd.com/327/
Yksi hyvä apuväline on mysql_real_escape_string tai jonkin ORMin tai parametrisoituja kyselyitä käyttävän kirjaston käyttö.
Öhm... Pystyykö tätä selittämään mitenkään selvemmin? :O
Ja tuosta antamastasi osoitteesta löysin vaan jonkun sarjakuvastripin. En tiedä miten se nyt tähän liittyy. Kertoo taulun poistamisesta?
Petja kirjoitti:
Öhm... Pystyykö tätä selittämään mitenkään selvemmin? :O
No, jos ei kiinnosta ymmärtää mitä on tekemässä niin riittää kun laitat sen syötteen mysql_real_escape_string funktion läpi.
Petja kirjoitti:
Kertoo taulun poistamisesta?
Niin, periaatteessa tapasi kirjoittaa koodia mahdollistaisi kenelle tahansa sivulliselle taulun poistamisen tietokannasta, jos vaan arvaa taulun nimen.
Onneksesi PHP ei kuitenkaan salli useamman kyselyn suorittamista samalla mysql_query:llä.
Aaa... Eli siis:
mysql_real_escape_string("Kysely tulee tähän..."); mysql_query .....
Ymmärsin oikein?
En?
Ei kun se pelkkä käyttäjän syöte, ei koko kyselystringiä.
Eli esim.
$sql = "SELECT Blaa FROM Blöö WHERE Jotain='" . mysql_real_escape_string($_POST['Haku']) . "'"; $result = mysql_query($sql);
Ihan vinkkinä vastaisen varalle, että jos joku neuvoo käyttämään jotain funktiota, niin PHP:n funktioiden ohessa on usein esimerkkikoodia, ja tässäkin tapauksessa oikea tapa käyttää funktiota olisi sieltäkin löytynyt: https://www.php.net/manual/en/function.mysql-real-escape-string.php
PDO on nykyaikaa. Ei enää kannata itse ruveta säätämään kyselyjen turvaamisen kanssa.
Kyselyn suorittaminen PDO:lla menisi suurin piirtein näin:
*** TAPA I *** $db = new PDO('mysql:dbname=Mun_Kanta', $username, $password); $q = $db->prepare('SELECT id, phone, address FROM users WHERE name = ?'); $q->bindParam(1, $_GET['userData'], PDO::PARAM_STR); // Huomaa 1-indeksointi! $q->execute(); $results = $q->fetchAll(PDO::FETCH_ASSOC); foreach ($results as $r) { printf("ID: %d, osoite: %s, puhelin: %s\n", $r['id'], $r['address'], $r['phone']); }
*** TAPA II *** $db = new PDO('mysql:dbname=Mun_Kanta', $username, $password); $q = $db->prepare('SELECT id, phone, address FROM users WHERE name = :nimi'); $q->execute( array(':nimi' => $_GET['user']) ); $results = $q->fetchAll(PDO::FETCH_ASSOC); ...
Syötettävän datan kelvollisuutta ei prepare-metodia käyttäessä itse varmistaa mitenkään. Kyselyt voi myös suorittaa suoraan PDO::query()-funktiolla, mutta tällöin varmistus tulee tehdä itse esim. PDO::quote'lla.
IMO, relaatiokantojen kanssa ORMit on nykyaikaa.
Mutta toki PDO on tyhjää parempi, varsinkin kun PHP on oliokieleksi (ja muutenkin) onneton (jälleen IMO). Eli PHP:llä ei todellakaan saa ORMeista kaikkea iloa irti. PDO:han viittasinkin jo tuossa alkuperäisessa vastauksessani (eli PDO on yksi parametrisoituja kyselyjä tukeva vaihtoehto)
Ja täytyy sanoa etten kyllä yhtään tykkää PDOsta. Aloin tekemään yhtä projektia PHP+PDO yhdistelmällä ja vähän päästä totesin että teen sen sittenkin vaikka Javalla+Hibernatella.
Grez kirjoitti:
Mutta toki PDO on tyhjää parempi, varsinkin kun PHP on oliokieleksi (ja muutenkin) onneton (jälleen IMO).
Ei faktoja tarvitse esittää mielipiteinä...
Aihe on jo aika vanha, joten et voi enää vastata siihen.