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>
$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.
Eipäs tuolla koodilla mitään linkkejä tullut?
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);
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?
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!
Muistahan sitten varmistaa tiedot ennen kuin kirjoitat ne kantaan ja altistat koko sivustosi XSS-hyökkäyksille. Maken koodi kun ei siihen auta.
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 :/
Itse en ainakaan löydä kyseisestä koodista Xss-aukkoa. Tosin en silti tuolla tyylillä lähtisi toteuttamaan.
foreach ($_POST['hakusanat'] as $v) { $v = mysql_real_escape_string($v); mysql_query("INSERT INTO ... $v ..."); }
Ihan siis yksinkertaisimmillaan tuota tarkoitin.
Eli tarkoitit siis SQL-injektiota?
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.
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.
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.
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.
PHP mysql_query ei tue turvallisuussyistä kuin yhtä statementtia kerrallaan, joten tuo ; terminointi ei toimi.
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.
Aihe on jo aika vanha, joten et voi enää vastata siihen.