Kirjautuminen

Haku

Tehtävät

Keskustelu: Nettisivujen teko: .htaccess tiedosto

Sivun loppuun

mika132 [21.06.2011 19:13:55]

#

Eli olen .htaccess tiedostolla yrittänyt saana ns "siistimpää" osoitetta, mutta toistaiseksi huonoin tuloksin.

Tässä on .htaccess tiedostoni:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^([a-zA-Z0-9_-]+)$ index.php?q=$1 [QSA,L]
</IfModule>

index.php tiedostossani on getillä haettavana osoite johon yritetään eli:

 <?php
	if(empty($_GET['q']) && $_GET['q'] == "")
	{
		include("etusivu.php");
	}
	else
	{
		include($_GET['q'].".php");
	}
?>

eli index.php on kaiken ydin.

Tässä vielä linkki systeemi eli:

	<a href="etusivu">Etusivu</a>
       <a href="ajankohtaista">Ajankohtaista</a>

Minun mielestä tuo .htaccess tiedosto pitäisi toimia, mutta kuitenkaan se ei niin tee.

Eli siis osoite riville olisi tarkoitus tulla:
tehogames.com/etusivu

ja .htaccessin pitäisi osata hakea tietoa index.php:stä q muuttujan avulla. (kyllä yritin selittää yksinkertaisesti)

Mod. korjasi oikeat kooditagit.

Teuro [21.06.2011 19:18:28]

#

No millainen osoite tuosta tulee? Säännöllinen lausekkeesi ei ehkä ole oikein, tai sitten se valitsee eri kohdan osoitetta, jonka kuvittelet. Käsittääkseni tarvitset vain tuon arvon tuota 'q'-muuttujaa varten?

Includen avulla tehty sivunavigaatio on ehkä huono?

Tällainen toimi omalla palvelimella:

RewriteEngine On
RewriteRule ^[a-z0-9]+$ index.php?q=$0

mika132 [21.06.2011 19:44:29]

#

ei toiminut antamasi koodi. Oppaita tässä jo lukenut muutaman tunnin, mutta kaikki oppaat neuvovat samaa. Saan tuon toimimaan jos teen näin:

<IfModule mod_rewrite.c>
	RewriteEngine On
	RewriteRule ^[a-z0-9]+$ index.php?q=profiili&id=$1
</IfModule>

nyt jos kirjoitan osoite riville 1 se menee profiili sivulle profiilin minkä ID on 1.

No siis siitä tulee osoitteeksi:
tehogames.com/etusivu/

mutta sivu heittää erroria koska se ei löydä tietokannan yhteyden avaamista ja sivu on ihan valkoinen. Eli järjestelmä ei ymmärrä, että index.php sinne mukaan, koska index.php:ssä on kaikki tietokannan yhteydenotot, ulkoasu hakua yms.

Teuro [21.06.2011 19:48:11]

#

No teepä tällainen index.php sivu

<?php
var_dump($_GET);
?>

mulla tulee tulosteeksi tällainen, kun osoite on index.php/etusivu

index.php/etusivu kirjoitti:

array
'q' => string 'etusivu' (length=7)

Tietokantayhteydet ja vastaavat tuskin liittyvät tähän kyseiseen ongelmaan. Ongelma lienee syvemmällä, kuten heikosti toteutettu rakenne tai vastaava.

Mika132 kirjoitti:

RewriteRule ^[a-z0-9]+$ index.php?q=profiili&id=$1

nyt jos kirjoitan osoite riville 1 se menee profiili sivulle profiilin minkä ID on 1.

Toimii siis aivan kuten pitääkin?

Tällainen koodi voisi olla myös paikallaan:

RewriteEngine On
RewriteRule ^([a-z0-9]+)/?([a-z0-9]+)?/?([a-z0-9]+)?$ index.php?q=$1&t=$2&f=$3

Tällöin saisit esimerkiksi osoitteen index.php/profiili/1/muokkaa ja vastaavat moniparametriset sivut toimimaan samaan tapaan.

mika132 [21.06.2011 19:59:03]

#

Ei toimi. :D

En halua, että se lyhentää profiili sivun ID:tä vaan, että se lyhentää sen q=tamantekstin

eli jos mennään sivulle index.php?q=ajankohtaista

niin osoite rivillä olisi:
tehogames.com/ajankohtaista
eikä:
tehogames.com/index.php?q=ajankohtaista

minulle tuo var_dump funktio tulosti:
array(1) { ["q"]=> string(12) "yhteydenotto" }

Teuro [21.06.2011 20:00:41]

#

Mutta mutta siis oletko nyt ymmärtänyt tuon mod_rewriten oikein? Eihän se suinkaan muuta index.php?q=ajankohtaista muotoon index.php/ajankohtaista, vaan aivan päin vastoin.

mika132 [21.06.2011 20:03:50]

#

juu.. tiedän. :D

siis minulla on linkki joka ohjaa sivulle:

<a href="etusivu">Etusivu</a>
<a href="ajankohtaista">Ajankohtaista</a>

ja ymmärtääkseni tuo minu .htaccess tiedosto pitäisi osata lisätä tuo "etusivu" sinne q=TÄHÄN jolloin oikeasti ollaan sivulla "tehogames.com/index.php?q=etusivu" mutta osoiterivillä näkyykin tehogames.com/etusivu

Teuro [21.06.2011 20:07:47]

#

Ei ei mod_rewrite ei koske selaimen osoiteriviin. Ja tuon edellisen testin var_dump() perusteella systeemisi toimii oikein, jos todella selaimen osoiterivillä luki index.php/etusivu, eikä index.php/q=etusivu

mika132 [21.06.2011 20:10:40]

#

Testasin var_dumppia sitten väärin ja nyt koitin sitä:
tehogames.com/index.php/etusivu
ja tuli array(0)

No sitten olen totisesti ymmärtänyt väärin.

Miten tuo osoite rivi sitten pidetään "siistinä" monilla sivuilla saattaa lukea vain:
osoite.com/home
tai
osoite.com/home/profile/453212

Teuro [21.06.2011 20:16:52]

#

Osoiterivi pidetään siistinä siten, että käyttäjä syöttää siistin osoitteen. Tai sitteen systeemin omat linkit ovat siistejä. mod_rewrite muuttaa "pinnan alla" nuo parametrit (siis kauttaviivojen jälkeiset osat) omiin muuttujiin.

Siis kohta kohdalta:

Entä jos kokeilet ilman index.php tuolla osoitteessa?

qeijo [21.06.2011 20:21:00]

#

mika132 kirjoitti:

 <?php
	if(empty($_GET['q']) && $_GET['q'] == "")
	{
		include("etusivu.php");
	}
	else
	{
		include($_GET['q'].".php");
	}
?>

Joo en tiedä, mutta ethän käytä tota oikeasti.. ?

Teuro [21.06.2011 20:23:56]

#

qeijo: ainakin versio, joka päättyi hakkerointiin käytti tismalleen tuon tyyppistä metodia.

mika132 [21.06.2011 20:24:45]

#

Ilman index.php tulee erroreita eikä näy ulkoasua.

Käytän. onkos sinulla parempi vinkki, että saadaan kaikki sivut helposti yhden sivun alle niin, että jos esim vaihtaa ulkoasua ei tarvitse kuin muuttaa yhtä tiedostoa?

Teuro [21.06.2011 20:26:51]

#

mika132 katsotaanko jossakin vaiheessa vaikka kimpassa noita koodeja kuntoon tuon sivuston kanssa? fatal error johtuu siitä, että yrität käyttää olematonta instassia (oliota) luokasta PDO.

Voisit vaikka sulkea sivut, kunnes aukot on tilkitty, kuten hakkeroitu versio sivustasi kertoi.

-tossu- [21.06.2011 20:28:29]

#

Qeijo tarkoitti varmasti, että tuossa koodissa on melkoinen tietoturva-aukko, eikä sitä pitäisi siksi käyttää. Koodi sallii minkä tahansa, kuten käyttäjien tunnukset ja salasanat sisältävän, tiedoston liittämisen sivun osaksi

mika132 [21.06.2011 20:29:02]

#

Miksei erroria sitten tule:
tehogames.com/?q=etusivu
tuossa tilanteessa? =)

ja miten ajattelit katsoa koodia kanssani? =)

Teuro [21.06.2011 20:32:12]

#

Selkeästi siis tuo mod_rewrite ei toimi oikein. Onko apachesta rewrite moduuli päällä? Sitä ei kai saa päälle .htaccess:n avulla? Tässä pitäisi kai käyttää httpd.conf tiedostoa.

mika132 [21.06.2011 20:34:02]

#

jostain syystä jos käytän httpd.conf koodia koko sivusto heittää 501 errorin. Tai joku tuollainen errori se oli. En ole nyt ihan varma mikä, mutta kuitenkin jokin serveriin liittyvä.

Teuro [21.06.2011 20:36:11]

#

Varmaankin error 500 internal server error erittäin yleinen, jos tumpuloit noiden tiedostojen kanssa. Kannattaa olla tarkkana näiden kanssa. Onko httpd.conf tiedostossa tällainen rivi?

httpd.conf kirjoitti:

LoadModule rewrite_module modules/mod_rewrite.so

mika132 [21.06.2011 20:42:18]

#

Ymmärsin siis tuonkin väärin!

En löydä mistään serveristä httpd.conf tiedostoa? Shellitti palveluntarjoajana? Teenkö sen itse ja pitääkö siellä olla mitä rivejä?

Teuro [21.06.2011 20:44:46]

#

Hmm jos et näe tätä tiedostoa et voi sitä silloin muokata, eikä uuden luominenkaan auta, koska serveri ei sitä takuulla käsittele. Lisäksi se on pitkä (satoja rivejä), etkä luultavasti ymmärrä suurimmasta osasta niistä mitään.

Kannattaa kysellä palveluntarjoajalta onko kyseinen ominaisuus käytettävissä. Useinkaan näitä tiedostoja ei ole saatavilla, mutta mietin että miten olet voinut muokata tuota tiedostoa, kuten pari viestiä sitten väitit?

Vai tarkoititko, että olet laittanut nuo httpd.conf koodit .htaccess tiedostoon?

mika132 [21.06.2011 20:48:37]

#

Sanoinkin juuri että "ymmärsin siis tuonkin väärin".

kirjoitin .htaccess tiedostooni tälläisen rivin:
grep -i AccessFileName httpd.conf

ja ymmärsin vahinkossa, että tarkoitit tuota riviä, mutta et tarkoittanutkaan. Ja tuo rivi kun kirjoitin .htaccess tiedostoon heitti tuon "500 internal server error" anteeksi mokani. =)

Teuro [21.06.2011 20:58:54]

#

Eli varmistapa nyt vielä, että tuo moduuli on tosiaan ladattu ja, että se on toimintavalmis. Sitten lataa jokin WAMP tai vastaava omalle koneella, jolla kehität tuon sivuston ja julkaiset siitä vasta stabiilin version nettiin.

dartvaneri [21.06.2011 23:32:13]

#

Kertokaapa joku nyt oikee kunnolla mikä tietoturva-aukko tossa koodissa on, ja miten se murretaan :P ja sitten sekin että mitä vikaa getissä on? sen tiedon voi tarkistaa kunnolla, ja tietääkseni sillon se on turvallinen.

Jos tämä ei toimi niin se on palvelimen asetuksista kiinni, koska ainakin mulla toimii moitteettomasti:

<IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^(.*)$ index.php?q=$1 [QSA,L]
</IfModule>

-tossu- [21.06.2011 23:44:13]

#

dartvaneri kirjoitti:

Kertokaapa joku nyt oikee kunnolla mikä tietoturva-aukko tossa koodissa on, ja miten se murretaan :P

Vika on siinä, ettei koodi tarkista q-parametrin arvoa mitenkään, joten skriptin avulla pystyy hakemaan minkä tahansa tiedoston, johon skriptillä on pääsy.

Esim: Sinulla on käyttäjien tunnukset ja salasanat tiedostossa salaiset/tunnukset.dat ja olet estänyt pääsyn salaiset-kansioon .htaccessilla. Käyttäjä voi kuitenkin mennä osoitteeseen index.php?q=salaiset/tunnukset.dat, jolloin hän näkee kaikkien tunnukset ja salasanat ilman mitään estettä.

Samalla tavalla tuon skriptin avulla voi hakea tiedostoja jopa wwwrootin ulkopuolelta.

Grez [21.06.2011 23:46:56]

#

dartvaneri kirjoitti:

Kertokaapa joku nyt oikee kunnolla mikä tietoturva-aukko tossa koodissa on

Unohditko kenties laittaa koodin? Näen vain rewrite-määrityksiä.

dartvaneri [21.06.2011 23:47:48]

#

Joo no toi kyllä varmaan on käyttökelpoinen, ku tarkistetaan se mitä se q sisältää, vaikka lista, sallituista tiedostoista vai?

-tossu- kirjoitti:

Samalla tavalla tuon skriptin avulla voi hakea tiedostoja jopa wwwrootin ulkopuolelta.

Meinaatko "../" menetelmää?

-Grez- kirjoitti:

Unohditko kenties laittaa koodin? Näen vain rewrite-määrityksiä.

En unohtanut, mutta unhdin sanoa että mika132:sen koodisaa.

-tossu- [21.06.2011 23:54:35]

#

dartvaneri kirjoitti:

Joo no toi kyllä varmaan on käyttökelpoinen, ku tarkistetaan se mitä se q sisältää, vaikka lista, sallituista tiedostoista vai?

Joko tuolla tavalla, tai sitten joku kehittyneempi systeemi, joka tarkistaa, että tiedosto sijaitsee oikeassa hakemistossa. Taisin viimeksi eilen kertoa siitä ja realpath-funktiosta.

dartvaneri kirjoitti:

Meinaatko "../" menetelmää?

Joko ../-menetelmällä tai antamalla absoluuttinen polku tyyliin /etc/passwd.

dartvaneri [22.06.2011 00:02:59]

#

Oisko tässä jotain ideaa, jos ei tarvitse hyppiä kansiosta toiseen?

<?php
 if(empty($_GET['sivu']) && $_GET['sivu'] == "")
 {
include("etusivu.php");
}
else
{
$sivu = $_GET['sivu'];

$sivu = preg_replace("/[^a-zA-Z0-9_]/", "_",$sivu);

include($sivu.".php");
}
?>

Millä muuten voi estää jos on esimerkiksi
http://sivu.com/
sivun osoitteena, niin ei voi laittaa
http://sivu.com/../jotain
?
toi ?sivu=jotain on helppo estää, mutta miten toi? Saako jollai .httacess kikkailulla?

Edit. korvataankin erikoismerkit "_" eikä tyhjällä.

-tossu- [22.06.2011 00:21:57]

#

dartvaneri kirjoitti:

Oisko tässä jotain ideaa, jos ei tarvitse hyppiä kansiosta toiseen?

Oishan siinä. Itse käyttäisin preg_replacen tilalla preg_matchia siten, että mikäli sivu-parametrissa on kiellettyjä merkkejä, näytetään virhesivu. Koodissa on myös kaksi melkein samaa ehtoa, joista toisen voi poistaa.

$sivu = empty ($_GET ['sivu']) ? "etusivu" : $_GET ['sivu'];

if (!preg_match ("/^[a-zA-Z0-9_]+$/", $sivu))
	echo "Virheellinen osoite!";
else
	include ("$sivu.php");

Viimeaikaisten tapahtumien takia pitää varoittaa, että koodi on yökoodia, jonka laatu on joskun vähän niin ja näin. :) Olen kuitenkin lähes varma, ettei siinä ole mitään vikaa.

Edit:

dartvaneri kirjoitti:

Millä muuten voi estää jos on esimerkiksi
http://sivu.com/
sivun osoitteena, niin ei voi laittaa
http://sivu.com/../jotain

Sitä ei tarvitse estää tavallisilla sivuilla, koska www-palvelin hoitaa eston ihan itse. Tietysti jos käytät mod_rewriteä, ei palvelin välitä tarkista urlia, joten se pitää estää PHP:n avulla.

dartvaneri [22.06.2011 00:41:52]

#

En tiedä, mutta itse olen sitä mieltä, että on järkevämpää korjata käyttäjän virhe, ku ilmoittaa virheestä, sillä kuitenkin tämä ko. koodi näyttää vain index.php:ssä olevan koodin, jos sivua ei löydy.

Tai oikeestaan ihan miten tykkää, ei toikaan paha ole, kun se heittää ton virhe ilmoituksen siihen mihin tulee se tuotava sivu, eikä koko sivun tilalle :)

voiko tän ohittaa?:

Options -indexes

The Alchemist [22.06.2011 07:25:07]

#

Dartvaneri: Älä häsellä.

$page = empty($_GET['page']) ? 'frontpage' : basename($_GET['page']);
$path = sprintf('pages/%s.php', $page);

if (!is_file($path))
  exit('404 - Not found');

include($path);

Noin se pitää tehdä, jos haluaa tietoturvallisen ja järkevän ratkaisun.

On aika jo mainita tuosta basename():sta, kun kumpikaan ei sitä näytä tuntevan. Regexeillä leikkiminen on tässä tilanteessa täysin väärä ratkaisu. Sovelluksen ei myöskään pidä arpoa sen suhteen, mitä käyttäjä on yrittänyt sanoa vaan toimia niin kuin annetun syötteen perusteella pitää toimia. Epäkelpo syöte tulkitaan virheeksi ja näytetään virhesivu. Hakukoneetkaan tuskin tykkäävät, jos mikä tahansa väärennetty linkki johtaa aina kelvolliselle sivulle.

Mikäli syötettävään polkuun täytyy saada tuki alihakemistoille (eli /-merkeille), niin tällöin täytyy turvautua johonkin tällaiseen:

define('SAFE_ROOT', '/home/user/web-docs/restricted');

$page = empty($_GET['page']) ? 'frontpage' : trim($_GET['page']);
$path = realpath(sprintf('restricted/%s.php', $page));

// Täytyy käyttää !==-operaattoria, koska tuloksen pitää olla (int)0.
if (strpos($path, SAFE_ROOT) !== 0 || !is_file($path))
  exit('404 - Not found');

include($path);

Asioita ei pidä tehdä monimutkaisemmiksi kuin on tarve, joten käytä allaolevaa ratkaisua VAIN jos tarvitset tuen alihakemistoille. Lisäksi kannattaa tarkistaa tuon koodin järkevyys, kun kirjoitin sen kylmiltäni tähän.

-tossu- [22.06.2011 12:42:36]

#

The Alchemist kirjoitti:

Sovelluksen ei myöskään pidä arpoa sen suhteen, mitä käyttäjä on yrittänyt sanoa vaan toimia niin kuin annetun syötteen perusteella pitää toimia. Epäkelpo syöte tulkitaan virheeksi ja näytetään virhesivu.

The Alchemist kirjoitti:

On aika jo mainita tuosta basename():sta, kun kumpikaan ei sitä näytä tuntevan.

Basename-funktiohan tietyssä tapauksessa "arpoo", mitä käyttäjä on yrittänyt sanoa. Esim. page=foo/sivu muuttuu basenamen jäkelkeen muotoon page=sivu.

Metabolix [22.06.2011 13:09:39]

#

-tossu-, mitä ihmettä? Kyllä minulla basename("a=b/c") palauttaa ihan odotetusti tekstin "c".

-tossu- [22.06.2011 13:18:15]

#

Metabolix kirjoitti:

-tossu-, mitä ihmettä? Kyllä minulla basename("a=b/c") palauttaa ihan odotetusti tekstin "c".

Taisin selittää vähän huonosti. Tarkoitin, että jos käyttäjä menee sivulle index.php?page=foo/sivu, vastaa se basenamen kanssa sitä, että käyttäjä menisi sivulle index.php?page=sivu.

Metabolix [22.06.2011 13:32:36]

#

Niin, ei tietenkään pelkkä basenamen ottaminen ole järkevä ratkaisu, mutta sitä voi helposti käyttää tarkistukseen:

if (basename($path) != $path) {
  // 404 Not Found tai 400 Bad Request
  die();
}
if (!file_exists("sivut/{$path}")) {
  // 404 Not Found
  die();
}
require("sivut/{$path}");

Kannattaa silti vähän miettiä myös, mitä ihmeen hyötyä on pyöräyttää kaikki sivut index.php:n kautta. Minusta se vain sotkee koodia ja vaikeuttaa esim. virhetilanteiden järkevää hallintaa. Yhteisen yläosan ja alaosan tekemiseen on parempiakin tapoja, esimerkiksi erilliset funktiot tulosta_ylaosa($otsikko) ja tulosta_alaosa().

The Alchemist [22.06.2011 16:46:51]

#

-tossu- kirjoitti:

The Alchemist kirjoitti:

Sovelluksen ei myöskään pidä arpoa sen suhteen, mitä käyttäjä on yrittänyt sanoa vaan toimia niin kuin annetun syötteen perusteella pitää toimia. Epäkelpo syöte tulkitaan virheeksi ja näytetään virhesivu.

The Alchemist kirjoitti:

On aika jo mainita tuosta basename():sta, kun kumpikaan ei sitä näytä tuntevan.

Basename-funktiohan tietyssä tapauksessa "arpoo", mitä käyttäjä on yrittänyt sanoa. Esim. page=foo/sivu muuttuu basenamen jäkelkeen muotoon page=sivu.

Sekoitat nyt tietoturvallisuuden ja arpomisen, mutta valitettavasti monille PHP-koodareille tietoturvallisuus on arpomista, joten annetaan armon käydä oikeudesta.

Basename() on luotettavin keino riisua syötetystä polusta kaikki "häxöröinnit". Okei, on semanttisempaa todellakin verrata arvoja basename($page) ja $page ja tulostaa virheilmoitus myös silloin, kun ne ovat eri arvoja.

qeijo [22.06.2011 19:29:15]

#

else {
     header("HTTP/1.0 404 Not Found");
}

Sivun alkuun

Vastaus

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

Tietoa sivustosta