Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: tekstin tulostus tiedostosta

Sivun loppuun

jarpenet [19.09.2011 20:36:18]

#

Sivulla on lista otsikoita. Otsikot viittaavat eri tekstitiedostoihin. Miten otsikoihin sisältyvän tekstin saa samalle sivulle tulostettua näyttöön? Onko tekstitiedostojen tallennustavalla merkitystä? .txt, .htm jne...

Otsikot ovat siis linkkejä ja uuden otsikon valitsemisen myötä teksti myös vaihtuu. Tulostusalueeksi varattu alue on sivulle tultaessa tyhjä.

punppis [19.09.2011 20:48:34]

#

<a href="?tiedosto=eka.txt">eka.txt</a>
<a href="?tiedosto=toka.txt">toka.txt</a>

<?php
    if(isset($_GET["tiedosto"]) && !empty($_GET["tiedosto"]) && file_exists($_GET["tiedosto"]) && is_file($_GET["tiedosto"])) {
        echo file_get_contents($_GET["tiedosto"]);
    }
?>

Tiedostomuodolla ei ole väliä, sillä file_get_contents lataa tiedostn sisällön suoraan tekstinä ja palauttaa datan.

jlaire [19.09.2011 20:53:44]

#

Kaikista helpoin tapa on tuo ^, eli tee otsikoista linkkejä.

Koko sivun uudelleenlatauksen voi välttää tallentamalla tiedostojen sisällöt JavaScript-taulukkoon (jonka voi generoida PHP-skriptillä) ja vaihtamalla tulostusalueen sisällön onclick-eventeissä. Vaatii n. yhden rivi jQueryä.

Jos tiedostot ovat isoja ja tuo taulukko hidastaisi sivun latautumista liikaa, datan voi hakea palvelimelta vasta tarvittaesssa ajax-pyynnöllä. Tähän tarvitaan ehkä jopa muutama rivi koodia.

-tossu- [19.09.2011 22:48:58]

#

Punppiksen koodissa on tietoturva-aukko: se ei tarkista polkua mitenkään, joten sillä voi hakea minkä tahansa palvelimella olevan tiedoston. Lisäksi koodissa on turhan monta tarkistusta.

punppis [20.09.2011 00:29:54]

#

-tossu- kirjoitti:

Punppiksen koodissa on tietoturva-aukko: se ei tarkista polkua mitenkään, joten sillä voi hakea minkä tahansa palvelimella olevan tiedoston. Lisäksi koodissa on turhan monta tarkistusta.

Tuo koodi oli toki vain esimerkki, eikä pidä sellaisenaan käyttää.

Tarkistuksia on mielestäni juuri sopiva määrä (paitsi tietysti sen tiedoston polku olisi hyvä selvittää):

- issetillä tarkastetaan onko parametria edes annettu
- emptyllä tarkistetaan ettei anneta tyhjää syötettä
- file_exists palauttaa true myös, jos "osoitteesta" löytyy hakemisto (eli jos antaa esim. tyhjän parametrin tai hakemiston nimen niin pelkkä file_exists ei käy)
- is_filellä taas saadaan selville, onko kyseessä hakemisto vai tiedosto

Tuohon kun vielä lisää esim. in_array($_GET["tiedosto"], glob("sallitut_tiedostot/*.txt")) niin tietoturva alkaa olla kohdillaan. Toki paras olisi ehkä manuaalisesti pitää yllä tuota sallittujen tiedostojen arraytä, mutta turhan hankalaa jos käytettäviä tiedostoja on useita. Toisaalta jos hakkerilla on pääsy tiedostopalvelimelle, niin tuo manuaalisen arrayn tietoturvan hyöty on olematon, sillä yhtälailla hakkeri voi muokata php-tiedostoa sallimaan halutut filut, ellei php-tiedostot ole sitten kaikilta paitsi webbiserveriltä pannassa.

Jos nyt vielä ruvetaan hifistelemään, niin in_array tarkistuksen kanssa kaikki paitsi tuo isset-tarkistukset ovat turhia (olettaen toki että käytetään juurikin glob-funktiota).

RQ [20.09.2011 01:01:49]

#

Oon vähän sitä mieltä, että jos jotain tietoturvatonta koodinpätkää antaa, olis hyvä mainita ettei sitä kannata missään nimessä sellaisenaan käyttää.

jlaire [20.09.2011 12:44:43]

#

RQ:n kanssa samaa mieltä. Olisi parempi antaa joko oikeasti toimiva koodipätkä tai sitten pelkkä pseudokoodi tai sanallinen selitys ideasta. Syntaksiltaan validista mutta bugisesta koodista on vain haittaa (ellei tarkoitus ole opettaa kysyjälle vaikeimman kautta, että netistä ei kannata sokeasti kopioida koodeja).

punppis kirjoitti:

- issetillä tarkastetaan onko parametria edes annettu
- emptyllä tarkistetaan ettei anneta tyhjää syötettä
- file_exists palauttaa true myös, jos "osoitteesta" löytyy hakemisto (eli jos antaa esim. tyhjän parametrin tai hakemiston nimen niin pelkkä file_exists ei käy)
- is_filellä taas saadaan selville, onko kyseessä hakemisto vai tiedosto

- Onko tyhjä merkkijono useinkin validi tiedostonimi?
- is_file tarkistaa myös olemassaolon
- Miksei näin?

if (@is_file(@$_GET['tiedosto'])) { ... }

Lebe80 [20.09.2011 12:56:06]

#

jlaire kirjoitti:

- Miksei näin?

if (@is_file(@$_GET['tiedosto'])) { ... }

Koska tuolloin ei tule virheilmoituksia, jos niitä tulisi.

The Alchemist [20.09.2011 15:28:28]

#

Isset() on empty():n kanssa aina turha. Jos muuttujaa tai taulukon solua ei ole olemassa, niin empty() palauttaa edelleen falsen. Samoin is_file() tekee file_exists():n turhaksi, koska tietenkään annetussa polussa ei voi sijaita tiedostoa, jos polkua ei edes ole olemassa.

Jiairen ehdottamaan ehtolauseeseen ei tarvita kuin yksi @-merkki is_file():n eteen. Ja itsekin käyttäisin juuri tuota. Is_file ei heitä virheilmoituksia. Se vain palauttaa falsen, jos testattava polku ei ole tiedosto tai ollenkaan saavutettavissa.

pistemies [20.09.2011 17:34:51]

#

punppis kirjoitti:

<a href="?tiedosto=eka.txt">eka.txt</a>
<a href="?tiedosto=toka.txt">toka.txt</a>

Tuollaista ehdotusta ei kannattaisi missään nimessä antaa. Joku voi laittaa urliin myös tekstin http://localhost/sendmail.php ja voi sivulta laittaa roskapostia kotikoneeltaan.

Teuro [20.09.2011 18:34:53]

#

pistemies kirjoitti:

Tuollaista ehdotusta ei kannattaisi missään nimessä antaa. Joku voi laittaa urliin myös tekstin http://localhost/sendmail.php ja voi sivulta laittaa roskapostia kotikoneeltaan.

Entäs jos serverille ei ole koodattu sendmail.php tiedostoa? Eihän tuosta ole mitään riemua, eikä käyttäjän antamaan syötetteeseen muutenkaan ole kauhean fiksua luottaa.

Ja jos taas sen kirjoitaa todella osoiteriville, niin sehän osoittaa omaan koneeseesi.

pistemies [20.09.2011 20:20:59]

#

Teuro kirjoitti:

pistemies kirjoitti:

Tuollaista ehdotusta ei kannattaisi missään nimessä antaa. Joku voi laittaa urliin myös tekstin http://localhost/sendmail.php ja voi sivulta laittaa roskapostia kotikoneeltaan.

Entäs jos serverille ei ole koodattu sendmail.php tiedostoa? Eihän tuosta ole mitään riemua, eikä käyttäjän antamaan syötetteeseen muutenkaan ole kauhean fiksua luottaa.

Ja jos taas sen kirjoitaa todella osoiteriville, niin sehän osoittaa omaan koneeseesi.

pistemies [20.09.2011 20:25:19]

#

Teuro kirjoitti:

pistemies kirjoitti:

Tuollaista ehdotusta ei kannattaisi missään nimessä antaa. Joku voi laittaa urliin myös tekstin http://localhost/sendmail.php ja voi sivulta laittaa roskapostia kotikoneeltaan.

Entäs jos serverille ei ole koodattu sendmail.php tiedostoa? Eihän tuosta ole mitään riemua, eikä käyttäjän antamaan syötetteeseen muutenkaan ole kauhean fiksua luottaa.

Ja jos taas sen kirjoitaa todella osoiteriville, niin sehän osoittaa omaan koneeseesi.

Viesti karkasi.
Jollakin muullakin voi viesti karata ihan väärään suuntaan :)
Et oivaltanut mitä tarkoitin.
Tarkoitin tällaista linkin jatketta:
www.teuro.net/index.php?tiedosto=http://localhost/sendmail.php
Roskapostin lähettäjäksi tulee teuro.net vaikka se olisi joku texasin joe.

Metabolix [20.09.2011 20:53:23]

#

pistemies kirjoitti:

Roskapostin lähettäjäksi tulee teuro.net vaikka se olisi joku texasin joe.

En edelleenkään ymmärrä, mistä se roskaposti lähtee. Missä tuo sendmail.php sinusta sijaitsee, ja millä ihmeen perusteella se lähettää roskapostia?

Teuro [20.09.2011 21:07:59]

#

pistemies kirjoitti:

Et oivaltanut mitä tarkoitin.

Ymmärsin aivan varmasti sen mitä tarkoitit

pistemies kirjoitti:

Tarkoitin tällaista linkin jatketta:
www.teuro.net/index.php?tiedosto=http://localhost/sendmail.php
Roskapostin lähettäjäksi tulee teuro.net vaikka se olisi joku texasin joe.

Mitä tuon syötteen jälkeen pitäisi tapahtua? Ei se roskaposti lähde tuolla linkillä mihinkään. Lisäksi vaikka lähtisikin, niin palveluntarjoaja luultavasti blokkaisi kyseisen saitin aika äkkiä.

Grez [20.09.2011 21:17:03]

#

Tuossa varmaankin viitattiin siihen, että jos sivulla käytettäisiin käyttäjän syötettä sellaisenaan file_get_contents -funktiolle, niin sitä voisi käyttää minkä tahansa nettisivun lataamiseen piilottaen pyynnön tekijän identitieetin.

Eli jos vaikka jollain firmalla olisi get-pyyntöjä hyväksymä palautelomake (joka tietysti itsessään on WTF) niin tälle firmalle voisi lähettää palauteviestejä siten, että niiden lähettäjä (=sivupyynnön tekijä) näyttäisi olevan tämä palvelin.

Mielestäni roskapostin lähettäminen sinänsä on huono esimerkki, mutta yleisesti on ihan hyvä pointti, ettei tuollaista "avointa proxyä" välttämättä kannata laittaa sivuilleen.

jarpenet [21.09.2011 07:03:11]

#

Kiitos ohjeista! Tuo tietoturvajuttu hämmensi kyllä tällaista noviisia! Kokeilin tosiaan sekä tuota pidempää kaavaa ja lyhyempää. Molemmat toimii, mutta onko nyt tosissaan otettava nuo varoitukset? Ja miten sellainen estetään? Nyt ei ole mahdollisuutta SQL:ään.

Teuro [21.09.2011 07:40:28]

#

Jos käyttäjät pääsevät lisäämään linkkejä sivustolle pitää syötteet tarkistaa erityisen huolella. Jos itse lisäät materiaalin, niin silloin mikään käyttäjän toimi ei aiheuta mitään vahinkoa sivuillesi.

Tarkoitan tietoturva-aukkoa ei ole, eikä tule itsestään. koodari kirjoittaa itse joka ikisen aukon ohjelmaansa. Eli jos oletetaan, että tekstit ovat tiedostoissa, niin seuraavan koodin pitäisi tehdä haluamasi tominnot.

<?php
/** Lisää itse haluamasi tarkistukset **/
function validoi_syote($s) {
	return $s;
}

/**
	* Rajoittunut muotoilufunktio
	* Vähänkään monimutkaisempi teksti ei onnistu
	* Saat kuitenkin tehtyä esimerkiksi kappaleet p|sisältö tai otsikot hx|sisältö
**/
function muotoile($s) {
	$rivit = explode("\r\n", $s);
	$maara = count($rivit);
	$matsku = "";

	for ($i = 0; $i < $maara; ++$i) {
		$matsku .= preg_replace("/([a-z0-9]{1,2})\\|(.*)/", "<$1>$2</$1>", $rivit[$i]);
	}

	return $matsku;
}

Ja sitten käyttäesimerkki

<?php
	/** Täällä määritellään tarvittavat funktiot **/
	require_once("funktiot.php");

	if (isset($_GET['sivu'])) {
		$sivu = validoi_syote($_GET['sivu']);
	} else {
		$sivu = "index.txt";
	}

	$materiaali = file_get_contents($sivu);
	$materiaali = muotoile($materiaali);
?>
<!DOCTYPE html>
<html>
	<head>
		<title>Dynaaminen sisältö</title>
	</head>
	<body>
<?php echo $materiaali; ?>
	</body>
</html>

pwc [21.09.2011 08:58:00]

#

Mitäh? Eihän tässä ole enää päätä eikä häntää. Itse tehdyt sisällöt sivuihin ovatkin nyt tietoturva-aukko?

Html:n siistimistä tehdessä kannattaa tutustua funktioihin strip_tags ja htmlspecialchars.

Grez [21.09.2011 09:07:58]

#

pwc kirjoitti:

Mitäh? Eihän tässä ole enää päätä eikä häntää. Itse tehdyt sisällöt sivuihin ovatkin nyt tietoturva-aukko?

Viestissäsi ei ole "päätä eikä häntää". Nähdäkseni kukaan ei ole sanonut, että itse tehdyt sisällöt sinällään olisi tietoturva-aukko.

echo file_get_contents($_GET["tiedosto"]); # on tietoturva-aukko

Tai sitten voisit poimia lainaukseksi sen viestin kohdan johon viittaat.

Grez [21.09.2011 09:16:15]

#

Teuro kirjoitti:

Tarkoitan tietoturva-aukkoa ei ole, eikä tule itsestään. koodari kirjoittaa itse joka ikisen aukon ohjelmaansa.
...

<?php
/** Lisää itse haluamasi tarkistukset **/
function validoi_syote($s) {
	return $s;
}
//...
$materiaali = file_get_contents($sivu);
//...

Mutta onko järkevää laittaa tietoturva-aukollinen koodi esimerkiksi? Vaikka kirjoitatkin sinne kommentin, että "lisää itse haluamasi tarkistukset" niin eikö olisi parempi lisätä sinne jokin oletustarkistus siltä varalta, että joku kuitenkin kopioi sen sellaisenaan.

Eli mieluummin vaikka:

<?php
/** Lisää itse haluamasi tarkistukset **/
function validoi_syote($s) {
	//Sisältötiedostojen nimissä sallitaan merkit a-z ja .
	return preg_replace( '/[^a-z.]/' , '', $s);
}
//...
$materiaali = file_get_contents("../sisallot/$sivu");
//...

Teuro [21.09.2011 09:18:03]

#

pwc kirjoitti:

Mitäh? Eihän tässä ole enää päätä eikä häntää. Itse tehdyt sisällöt sivuihin ovatkin nyt tietoturva-aukko?

Kyllä ne ovat, jos sinne kirjoittaa tietoturva-aukon. Jos sitä taasen ei sinne kirjoita, niin ei sitä sinne itsestäänkään tule.

@Grez olet oikeassa olisi pitänyt vaivautua kirjoittamaan moinen itsekin.

pistemies [21.09.2011 12:40:22]

#

Näyttää siltä että eivät kaikki näytä oikein tajuavan mistä on kyse.

Kerrompa siis oman kokemukseni ajalta, jolloin vasta opettelin php:ta ja kuvittelin olevani kai jokin fiksu.

Sivullani oli vastaavanlainen linkki. Tosin se otti sisällön txt-tiedostosta icludella.
Meni suunnilleen vuosi, niin siitä osoitteesta laitettiin runsaasti roskapostia maailmalle. Sivut meni kiinni muutamaksi tunniksi. Palveluntarjoja sitten kertoi, missä on tietoturva-aukko. Tesatsin sitten itsekin... ja muuttamalla get-muuttujaan jonkin url-osoitteen sen ulkoisen nettisivun sisällöstä tuli osa minun sivuani.

Teuro [21.09.2011 12:44:26]

#

pistemies kirjoitti:

Näyttää siltä että eivät kaikki näytä oikein tajuavan mistä on kyse.

Katso peiliin se olet sinä :)

pistemies kirjoitti:

Sivullani oli vastaavanlainen linkki. Tosin se otti sisällön txt-tiedostosta icludella. Meni suunnilleen vuosi, niin siitä osoitteesta laitettiin runsaasti roskapostia maailmalle. Sivut meni kiinni muutamaksi tunniksi. Palveluntarjoja sitten kertoi, missä on tietoturva-aukko. Tesatsin sitten itsekin... ja muuttamalla get-muuttujaan jonkin url-osoitteen sen ulkoisen nettisivun sisällöstä tuli osa minun sivuani.

Lue vastaukseni uudelleen, niin ymmärrät itsekin, että ei se(kään) tietoturva-aukko sinne itsestään tullut. Sinä ihan itse olet tuollaisen mahdollistanut tekemällä huonon toteuksen asiaan. Tällaisella koodinpätkällä on melkoisen hankalaa saada mitään kovin vakavaa aikaan.

<?php
/** Ladataan tiedostosta **/
$data = file_get_contents("salainen.txt");

/** Muunnetaan teksti sopivaksi **/
echo htmlspecialchars($data);
}
?>

Grez [21.09.2011 13:26:49]

#

Teuro kirjoitti:

Tällaisella koodinpätkällä on melkoisen hankalaa saada mitään kovin vakavaa aikaan.

Toisaalta tuo oli ensimmäinen kerta kun tuollainen koodinpätkä (johon käyttäjän syöte ei vaikuta mitenkään) tuli esille tässä ketjussa.

Tietenkään tietoturva-aukkoja ei synny tyhjästä, mutta niitä syntyy helposti tahattomasti, jos koodaaja ei ole tarkkanata tai ei osaa.

punppis [26.09.2011 19:06:42]

#

The Alchemist kirjoitti:

Isset() on empty():n kanssa aina turha.
Samoin is_file() tekee file_exists():n turhaksi.

Totta. Enpä ole huomannut aikaisemmin että empty() ei luo virhettä jos muuttujaa ei ole olemassa. Noh, joka päivä oppii jotain uutta.

punppis [26.09.2011 19:20:22]

#

RQ kirjoitti:

Oon vähän sitä mieltä, että jos jotain tietoturvatonta koodinpätkää antaa, olis hyvä mainita ettei sitä kannata missään nimessä sellaisenaan käyttää.

Mielestäni foorumeilla voi antaa suurpiirteistä koodia, josta AP voi katsoa kuinka asiat tehdään suurinpiirtein ja luoda omat ratkaisunsa siihen päälle. Tietenkään mihinkään valmiiseen koodiin ei kannata sokeana luottaa.

The Alchemist [26.09.2011 19:48:20]

#

punppis kirjoitti:

RQ kirjoitti:

Oon vähän sitä mieltä, että jos jotain tietoturvatonta koodinpätkää antaa, olis hyvä mainita ettei sitä kannata missään nimessä sellaisenaan käyttää.

Mielestäni foorumeilla voi antaa suurpiirteistä koodia, josta AP voi katsoa kuinka asiat tehdään suurinpiirtein ja luoda omat ratkaisunsa siihen päälle. Tietenkään mihinkään valmiiseen koodiin ei kannata sokeana luottaa.

Kun ihminen tulee tänne hakemaan apua, koska ei osaa jotain tehdä, niin kaikista kauhein ratkaisu on tyrkätä hänelle puolivalmis ratkaisu käteen. Millä perustein voidaan olettaa, että hänellä olisi mitään käsitystä siitä, kuinka tietoturvan käsite implementoidaan ohjelmakoodiin, kun lähtötilanne oli se, ettei hän osannut edes sitä toista puolta kasata itse?

Huonoista vastauksista saa vain sen käsityksen, ettei vastanneellakaan ollut ymmärrystä kuin ongelman toisesta puolikkaasta.


Sivun alkuun

Vastaus

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

Tietoa sivustosta