GET parametresi sayfası eklemek için güvenli bir yol?

5 Cevap php

Ben bir set up URL'ler çizgisinde nerede olacak üzerinde çalışıyorum:

http://example.com/index.php?page=about

Gerçekte onlar daha basit bir URL'den olduğunu için yazılmış olacaktır. index.php bu kodu kullanarak, başka bir sayfa içerecektir:

if ( isset( $_GET['page'] ) )
{
	$page = $_SERVER['DOCUMENT_ROOT'] . '/pages/' . $_GET['page'] . '.php';
	if ( is_file( $page ) )
		include $page;
	else
		echo 'That page doesn\'t exist.';
}

Sayfalar klasöründeki her şeyi varsayarak dahil edilmesi tamamen güvenlidir, bu kod güvenli? I page=../../.passwd kullanarak tanınmış dizin kesmek, yani karşı korumalı ettik. Ben dikkatli olması gereken başka bir şey var mı?

5 Cevap

kod kullanmadan önce parametre doğrulamak gerektiğini dışında, ok:

if(!preg_match("~^\w+$~", $_GET['page']))
   die("page id must be alphanumeric!");

bu dinamiğini kullanarak bütün mesele içeren bir esneklik azalır, çünkü ben, "switch" yaklaşımı tavsiye olmaz.

geçmek durum muhtemelen daha iyi

$page_name = $_GET['page'];

switch($page_name) {
case 'about':
 $page = $_SERVER['DOCUMENT_ROOT'] . '/pages/about.php';
 break;        
case 'home': //fall through to default
case default:
 $page = $_SERVER['DOCUMENT_ROOT'] . '/pages/home.php';
}

include $page;

Bu şekilde, herhangi bir enjeksiyon sorun yok.

Edit

Başka bir çözüm adresi sayfa adının dönüşüm işleme adanmış bir sınıf kurmak olacaktır.

class Page {
  static private $pages = array ("about", "home");

  const DEFAULT_PAGE = "home";

  static public function includePage($page_name) {
    if (!in_array($page_name, self::$pages)) {
      $page_name = self::DEFAULT_PAGE;
    }
    include ($_SERVER['DOCUMENT_ROOT'] . '/pages/'.$page_name.'.php';);
  }
}

Bu şekilde, bu tek bir sınıf içinde yönetilir ve gelecek değişiklikler diğer kod kazma olmadan yapmak daha kolay

isteğini yansıtmak için yukarıdaki düzenlenebilir.

Ayrıca CodeIgniter sizin için her şeyi ve her zaman iyi bir şey olduğunu, bazı kodlama standartları benimseyerek sizi zorlar gibi bir çerçeveye geçiş yapabilirsiniz.

Sayfaları keyfi bir dizi işleme zaman SEO dostu dosya adlarına sahip olmak için iyi olabilir. Ben tire veya alt alfanümerik dosya adları öneriyoruz:

define(DOCROOT, $_SERVER['DOCUMENT_ROOT']);

// assume you do not include file extensions in $_GET['page']
$page = trim(preg_replace('~[^\\pL\d]+~u', '-', $_GET['page']), '-');
if (is_file($page)) {
   include DOCROOT . $page;
}

Bunu yapmak için çok güvenli bir yol ilk construct a list of directory contents, o listede ve use the value from the list for the include için kullanıcı girişi maç olacaktır. Hatlarında bir şey:

$sdir = $_SERVER['DOCUMENT_ROOT'].'/pages/';
$targetfile = $_GET['page'].'.php';
$filenames = scandir($sdir); // returns an array of directory contents
foreach ($files as $filename) {
  if (($filename[0] != '.')
     && ($filename == $targetfile)
     && (is_file($sdir.$filename)) {
        include $sdir.$filename;
        break;
  }
}

Yoksa sadece bunu yapabiliriz:

$targetfile = $_GET['page'].'.php';
$sdir = $_SERVER['DOCUMENT_ROOT'].'/pages/';
$filenames = scandir($sdir);
if (in_array($targetfile,$filenames)) {
   include $sdir.$filename;
}

Ama ikinci durumda really sure Eğer onay koşulları sağ olsun, ve aynı zamanda regex check suggested in another answer kullanmak olmalıdır. Birinci durumda, sadece dizin içeriği inşa listeden dahil ediyoruz, böylece kullanıcı kontroller aracılığıyla bazı garip giriş almak için yönetir bile güvenli olacak.