Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: [PHP] Hakusanojen erittely

Sivun loppuun

combo [31.03.2011 17:17:47]

#

En ole löytänyt kunnolla vastausta / ratkaisua ongelmaani. Minulla on hakusanat -kenttä, johon kirjoitetaan hakusanoja ja ne erotellaan toisistaan pilkuilla.

Nyt pitäisi ennen tietokantaan lisäämistä muuttaa ne aina omaksi linkikseen.

Esimerkki:

Kenttään kirjoitettu: mansikka, mustikka, vadelma

ja tietokantaan lisätään muodossa:

<a href="../hakusana?=mansikka">mansikka</a> <a href="../hakusana?=mustikka">mustikka</a> <a href="../hakusana?=vadelma">vadelma</a>

AkeMake [31.03.2011 17:33:24]

#

$hakusanat = explode(", ", $_POST['hakusanat']);
foreach($hakusanat as $key => $value) {
	$value = "<a href=\"../hakusana?=".htmlspecialchars($value)."\">".htmlspecialchars($value)."</a>";
}
$hakusanat = implode(" ", $hakusanat);

Nyt tuossa on hakusanat -muuttuja, jonka voi heittää tietokantaan. Ei ole testattu, joten virheitä saattaa hyvinkin löytyä. Idea on kuitenkin tuossa.

combo [31.03.2011 19:29:52]

#

Eipäs tuolla koodilla mitään linkkejä tullut?

AkeMake [31.03.2011 19:54:02]

#

Juu, olen sen verran harvoin tuon foreach:n kanssa tekemisissä, etten sitä osaa käyttää kovinkaan hyvin. Piti käydä vähän tarkemmin tutkimassa sen toimintaa ja löytyihän tuo toimiva koodi. Nyt se on myös testattu, joten pitäisi toimia.

$hakusanat = explode(", ", $_POST['hakusanat']);
foreach($hakusanat as &$value) {
    $value = "<a href=\"../hakusana?=".htmlspecialchars($value)."\">".htmlspecialchars($value)."</a>";
}
$hakusanat = implode(" ", $hakusanat);

Metabolix [31.03.2011 20:23:59]

#

combo kirjoitti:

Nyt pitäisi ennen tietokantaan lisäämistä muuttaa ne aina omaksi linkikseen.

HTML-koodi tietokannassa on useimmissa tapauksissa huono ratkaisu, koska sitä on vaikeampi muokata jälkikäteen. Mikset vain laita sanoja pilkutettuna listana tietokantaan ja muunna niitä tulostusvaiheessa?

combo [31.03.2011 21:07:48]

#

Metabolix kirjoitti:

combo kirjoitti:

Nyt pitäisi ennen tietokantaan lisäämistä muuttaa ne aina omaksi linkikseen.

HTML-koodi tietokannassa on useimmissa tapauksissa huono ratkaisu, koska sitä on vaikeampi muokata jälkikäteen. Mikset vain laita sanoja pilkutettuna listana tietokantaan ja muunna niitä tulostusvaiheessa?

Oikeastaan niin ajattelin sitten jälkikäteen tehdä.

Ja nyt toimii tuo AkeMake:n koodi!


Kiitos!

The Alchemist [31.03.2011 22:32:05]

#

Muistahan sitten varmistaa tiedot ennen kuin kirjoitat ne kantaan ja altistat koko sivustosi XSS-hyökkäyksille. Maken koodi kun ei siihen auta.

combo [31.03.2011 22:39:43]

#

The Alchemist kirjoitti:

Muistahan sitten varmistaa tiedot ennen kuin kirjoitat ne kantaan ja altistat koko sivustosi XSS-hyökkäyksille. Maken koodi kun ei siihen auta.

Osaatko tarkentaa? Olen vähän pihalla :/

Othnos [31.03.2011 22:57:34]

#

Itse en ainakaan löydä kyseisestä koodista Xss-aukkoa. Tosin en silti tuolla tyylillä lähtisi toteuttamaan.

The Alchemist [01.04.2011 07:04:24]

#

foreach ($_POST['hakusanat'] as $v) {
  $v = mysql_real_escape_string($v);
  mysql_query("INSERT INTO ... $v ...");
}

Ihan siis yksinkertaisimmillaan tuota tarkoitin.

makumaku [01.04.2011 08:27:12]

#

Eli tarkoitit siis SQL-injektiota?

The Alchemist [01.04.2011 12:39:00]

#

makumaku kirjoitti:

Eli tarkoitit siis SQL-injektiota?

Mikäli sekaannuksen syy oli käyttämäni termi, niin kyllähän tietokantainjektioitakin voi käyttää XSS-hyökkäyksiin.

Othnos [01.04.2011 12:55:18]

#

The Alchemist kirjoitti:

makumaku kirjoitti:

Eli tarkoitit siis SQL-injektiota?

Mikäli sekaannuksen syy oli käyttämäni termi, niin kyllähän tietokantainjektioitakin voi käyttää XSS-hyökkäyksiin.

Kaukaa haettua, mutta kyseisessä tapauksessa näin voitaisiin tehdä, jos käyttäjän syötettä ei escapetoida. Senkin takia järkevämpää tallentaa tiedot sellaisenaan kantaan, kuten Metabolix jo aiemmin ilmaisi, ja muotoilla niistä vasta tulostus vaiheessa tarvittavat linkit jolloin kaikki tietokannasta tuleva tieto voidaan ajaa esim. htmlspecialchars-funktion lävitse jolloin XSS-aukkoa ei jää vaikka SQL-injektion mahdollisuus olisi.

Metabolix [01.04.2011 13:21:30]

#

Jos tuosta XSS-asiasta on vielä epäselvyyttä, miettikääpä seuraavaa syötettä:

' + CHAR(1,2,3) + '

Tuloksena muuttujaan $hakusanat tulee seuraavaa:

$hakusanat = "<a href=\"../hakusana?=' + CHAR(1,2,3) + '\">' + CHAR(1,2,3) + '</a>";

SQL-kyselystä tulee silloin suunnilleen tällainen:

INSERT INTO taulu (hakusanat) VALUES ('<a href="../hakusana?=' + CHAR(1,2,3) + '">' + CHAR(1,2,3) + '</a>')

Kohdan 1,2,3 tilalle voi laittaa mitä tahansa tekstiä (esim. HTML- ja JS-koodia) ASCII-koodeina.

Othnos kirjoitti:

tieto voidaan ajaa esim. htmlspecialchars-funktion lävitse jolloin XSS-aukkoa ei jää

Tuo on hyvä lähtökohta, mutta tosiasiassa pelkkä htmlspecialchars ei pelasta, jos HTML on huonosti kirjoitettu. Esimerkki:

$data = "lol onclick=eval(unescape(this.name)) name=alert%28%22XSS%22%29";
$data = htmlspecialchars($data); // Ei vaikuta lainkaan.
echo "<a href=haku.php?x=$data>jee</a>";
<a href=haku.php?x=lol onclick=eval(unescape(this.name)) name=alert%28%22XSS%22%29>jee</a>

Siksipä attribuuteissa kannattaa aina käyttää lainausmerkkejä. Toinen hyvä syy on toki XML-yhteensopivuus ja yhteinäinen tyyli.

Othnos [01.04.2011 13:50:17]

#

Aina oppii uutta. Mutta moniko nykyaikainen standardi sallii attribuuttien arvot ilman lainausmerkkejä? Jos käytän esimerkiksi xhtml 1.0 ja ajan sivuni w3.orgin html-validatorin lävitse niin pääseekö kyseistä aukkoa syntymään?

Mutta kerta SQL-injektioihin mentiin mainittakoon vielä, että mysql_real_escape_string ei aina riitä. Esimerkiksi tapauksessa jossa tietoja päivitetään tietylle id:lle ja lainausmerkit jätetään id:n ympärille laittamatta.

$query = "UPDATE taulu SET arvo = '" . mysql_real_escape_string($arvo) . "' WHERE id = " . mysql_real_escape_string($id);

Jos id:ksi syötetään esimerkiksi

1; DROP TABLES taulu

muuttuu kysely muotoon

UPDATE taulu SET arvo = 'arvo' WHERE id = 1; DROP TABLES taulu;

Numeraalisia tietoja tallennettaessa kannattaakin käyttää intval-funktiota tai liukulukujen kanssa floatval-funktiota jne.

esajeejee [01.04.2011 16:13:16]

#

PHP mysql_query ei tue turvallisuussyistä kuin yhtä statementtia kerrallaan, joten tuo ; terminointi ei toimi.

Metabolix [01.04.2011 17:48:53]

#

Othnos kirjoitti:

Mutta moniko nykyaikainen standardi sallii attribuuttien arvot ilman lainausmerkkejä?

HTML sallii. Siis jopa HTML5 sallii. Rajoituksena sisällön puolesta ovat tietenkin välilyönnit ja >-merkki sekä attribuutin alussa " ja '.

Othnos kirjoitti:

Jos käytän esimerkiksi xhtml 1.0 ja ajan sivuni w3.orgin html-validatorin lävitse niin pääseekö kyseistä aukkoa syntymään?

Ei pääse, ellei satu niin hassusti, että PHP-koodisi toiminta riippuu tietokannassa olevasta datasta ja et tule testanneeksi validaattorin kanssa juuri kyseistä koodilohkoa. Jos sivu on tarjoiltu selaimelle XML-tyyppisenä, selaimenkin pitäisi hylätä virheellinen sivu, mutta monethan käyttävät text/html-MIME-tyyppiä, jolloin selain tapaa kelpuuttaa mitä tahansa.

Othnos kirjoitti:

[Jos] lainausmerkit jätetään id:n ympärille laittamatta

Lainausmerkit eivät kuulu lukuarvojen ympärille, vaikka MySQL ne kiltisti kelpuuttaakin.


Sivun alkuun

Vastaus

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

Tietoa sivustosta