Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: PHP/MySQL-lauseen syntaksin oikeellisuus

Sivun loppuun

Triton [13.03.2008 17:11:22]

#

Pitäisikö tämän lauseen toimia? Itse en sitä jostain syystä saa toimimaan, mutta ei myöskään syntax erroria heitä tai muutakaan erroria:

mysql_query("UPDATE asiakastiedot (Etunimi, Sukunimi, Email, Tunnus, Salasana, Osoite, Postinumero, Toimipaikka)
VALUES('{$etunimi}', '{$sukunimi}', '{$email}', '{$user}', '{$hashpass}', '{$osoite}', '{$postinumero}', '{$toimipaikka}' WHERE Tunnus = ('$sess_user') AND istuntoID =
('$sess_id')  LIMIT 1");}

Metabolix [13.03.2008 17:16:04]

#

SQL:ää osaamattomanakin uskallan väittää, että VALUES-listan lopusta puuttuu sulku.

ajv [13.03.2008 17:20:07]

#

Metabolix mainitsikin jo varsinaisen virheen, mutta tällainen simppeli debuggaus kannattaa pistää korvan taakse:

mysql_query("INSERT...") or exit(mysql_error());

Ja ei sitten lopulliseen versioon tuollaisia, käyttäjälle ei välttämättä ole hyvä kertoa tietokantavirheitä...

Triton [13.03.2008 17:24:48]

#

Mä oon tainu rupee tyhmäks... Noin yksinkertanen virhe! Mut mut eipäs toimi vieläkään! Ton ideana on mun palvelussa olla sellases paikaa, joka päivittää noi tiedot tietokantaan.

siirappi [13.03.2008 18:32:34]

#

Itse suosin kyselyn rivittämistä, jolloin virhetilanteissa virhe on helppo hahmottaa.

mysql_query("
UPDATE
	asiakastiedot
SET
	Etunimi = '{$etunimi}',
	Sukunimi = '{$sukunimi}',
	Email = '{$email}',
	Tunnus = '{$user}',
	Salasana = '{$hashpass}',
	Osoite = '{$osoite}',
	Postinumero = '{$postinumero}',
	Toimipaikka = '{$toimipaikka}'
WHERE
	Tunnus = '{$sess_user}'
	AND istuntoID = '{$sess_id}'
LIMIT 1
") or exit(mysql_error());

Onko tuo istuntoID merkkijono? Ja katso vaikka mitä mysql_affected_rows() sanoo.

Triton [13.03.2008 21:02:40]

#

Juu on se merkkijono... Kun siis tää juttu tulee mun nettikaupan asiakastietojen muuttumiseen, niin ton koodin avulla olis tarkotus päivittää syötetyt tiedot. Ja toi istuntoID on sitten tollanen "yhdiste" jolla tsekataan, että käyttäjä on kirjautuneena laitoin sen vaan tohon WHERE -kohtaan, että se tarkentaisi sitä..

TsaTsaTsaa [13.03.2008 21:17:34]

#

UPDATE-lauseen WHERE-kohdassa voi käyttää sellaisia kenttiä, mitkä löytyvät päivitettävästä taulusta. Siis jos asiakastiedot-taulusta ei löydy istuntoID-kenttää, niin tuo ei toimine.

ajv [13.03.2008 21:18:21]

#

Btw, näkemättä sen enmmän koodia, niin tuossa vaikuttaa olevan ihan kiva tietoturva-aukko... Ajatteleppa seuraava tilanne:

Teen oman sivun, jossa on formilla nuo samat kentät kuin sinun profiilinmuokkaussivulla - tosin kentissä on minun itseasettamani arvot ja oma formini lähtee automaattisesti sivunlatauksen jälkeen javascriptin voimalla tuonne sinun profiilinmuokkaussivulle. Sitten ujutan kauppasi käyttäjän lataamaan tuon oman sivuni silloin, kun hän on kirjautuneena.

Itse ongelmaan:

- Tee muuttuja $sql:
- kokoa tuohon muuttujaan tuo kysely (siirapin vinkki kyselyn jäsentämisestä helpottaa debuggausta)
- ajat kysely, kuten aikaisemmin mainitsin paitsi lisäät kyselyn tulostuksen virhetilanteessa: mysql_query($sql) or exit(mysql_error().'<br />'.$sql);
- tai sitten ihan vaan tulostat kysely ja katso mitä se sisältää

Metabolix [13.03.2008 21:25:18]

#

ajv kirjoitti:

Btw, näkemättä sen enmmän koodia, niin tuossa vaikuttaa olevan ihan kiva tietoturva-aukko...

Voisitkin saman tien kertoa tietämättömille, kuinka tuo hoidettaisiin järkevästi.

ajv [13.03.2008 21:28:13]

#

Eli siis kun muokataan kriittisiä tietoja, niin aina pyydetään se salasana ja tarkistetaan sen avulla, että käyttäjällä on oikeasti oikeus muokata ko. tietoja.

kayttaja-2499 [13.03.2008 21:40:28]

#

Sekä myös seuraava:
http://en.wikipedia.org/wiki/SQL_injection

Triton [28.03.2008 22:03:11]

#

ajv kirjoitti:

Eli siis kun muokataan kriittisiä tietoja, niin aina pyydetään se salasana ja tarkistetaan sen avulla, että käyttäjällä on oikeasti oikeus muokata ko. tietoja.

Näin asia on siis ollut kokoaika, että pyydetään käyttäjältä salasanaa ennen kuin tiedot annetaan päivittää... Mutta onko tässä tilanteessa mahdollista injektoitua sisään?

kayttaja-2499 [29.03.2008 09:02:46]

#

Kokeile syöttämällä etunimikenttään esimerkiksi seuraava teksti:

Keimo' WHERE 1 = 1; DELETE FROM asiakastiedot; UPDATE asiakastiedot SET etunimi = 'Keimo

HUOM! Jos tämä toimii, poistaa se kaikki rivit asiakastiedot-taulusta!

pistemies [29.03.2008 10:49:05]

#

Entä mihin sinä tarvitset tuota LIMIT 1 ?
Eihän siellä varmaan ole useampia samanlaisia tunnuksia jne...

Opiskelija [29.03.2008 12:38:10]

#

Pekka Mansikka kirjoitti:

Entä mihin sinä tarvitset tuota LIMIT 1 ?
Eihän siellä varmaan ole useampia samanlaisia tunnuksia jne...

Optimointia, tuolloin tietokanta ymmärtää että muutos halutaan vain yhteen, eikä yritä etsiä turhaan muita jotka täyttävät ehdon.

kayttaja-2791 [29.03.2008 12:43:14]

#

ajv kirjoitti:

Itse ongelmaan:

- Tee muuttuja $sql:
- kokoa tuohon muuttujaan tuo kysely (siirapin vinkki kyselyn jäsentämisestä helpottaa debuggausta)
- ajat kysely, kuten aikaisemmin mainitsin paitsi lisäät kyselyn tulostuksen virhetilanteessa: mysql_query($sql) or exit(mysql_error().'
'.$sql);

- tai sitten ihan vaan tulostat kysely ja katso mitä se sisältää

Fiksumpaa minusta on käyttää jotain erillistä kirjastoa tahi pelkkää omaa funktiota SQL-lauseiden ajamiseen, missä itse voi sitten itse määritellä kuinka virheisiin suhtaudutaan. Täten ei tarvitse kirjoittaa sataa kertaa samaa rimpsua
mysql_query($sql) or exit(mysql_error().'<br />'.$sql);
Vaan voi halutessaan ohjata virheet vaikka myöhemmin johonkin SQL-tauluun logitettavaksi, ja tarvitsee vain muuttaa sitä yhtä funktiota tai määritellä se kirjastoon tehtäväksi toimenpiteeksi.

Itse tein tuollaisen yksinkertaisen rajapintaluokan tietokannoille PHP5:lle ja MySQL:lle sille toteutuksen, mutta sitä pitäisi vielä vähän viilata ennenkuin sen kehtaa julkaista. Tosin löytyyhän noita valmiitakin, ainakin Pearilla oli jokin, ja eikös PHP5:ssäkin ole jokin fiksumpi tapa hoitaa nuo tietokanta-asioinnit?

ajv [29.03.2008 12:56:40]

#

@JTS:

Juu, jos taidot riittää, niin ehdottomasti noin. Mutta jos taidot eivät riitä debuggaamaan yhtä virheellistä SQL-lausetta, niin eipä kannata välttämättä itse lähteä omaa tietokanta-abstraktiota rakentamaan. ;)

Olen kokeillut sekä PEARin DB2:sta, että PHP5:sen PDO:ta. Aina olen kuitenkin palannut omien tietokantaluokkien käyttöön. Ne logittavat virheet nätisti tekstitiedostoihin, ja kehitysvaiheessa ne tarjoavat muitakin kivoja työkaluja pullonkaulojen selvittämiseen.

kayttaja-2791 [29.03.2008 13:31:22]

#

No joo, meni ehkä vähän turhan pitkälle...

Eli tehdä esim: tälläinen funkkari

<?php
function myMysqlQuery($query) {
  mysql_query($query) or exit("Mysql query contains errors:<br />".mysql_error());
}
?>

Ja käyttää tuota sitten niiden kyselyiden ajoon. Sitten kun on saanut koodit valmiiksi ja julkaisee sen yleisölle niin muuttaa tuon funktion virheilmoitusta, mysql-virheitä ei kannata loppukäyttäjälle asti näyttää sillä ne heikentävät tietoturvaa merkittävästi.

tsuriga [29.03.2008 13:56:35]

#

Exit/die sijaan voisi käyttää trigger_erroria, tai nykyaikaan ehkä throw new MySQLException. Sitten omalla exceptionhandlerilla kontrolloi sitä, mitä virheviestillä tehdään - tulostetaanko vai logitetaanko.


Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta