Bir dizin başka bir klasöre bir alt dizin Testi ise

4 Cevap php

Benim düşük seviyeli bazı dizinlerin erişimi engellemek olacak bir işlev oluşturmak için çalışıyorum. Sitemde inşa ederken Örneğin, ben kodlama yaparken /var/www/html/site/uploads/ ben bir hata yapmak gerekir yüklenenler daha alt yüklenmesine izin vermek istemiyorum. Bu da önbellek dosyaları falan çıkarırken bir dizin silme yazım hatası önlemeye yardımcı olacaktır.

Bu kolayca realpath() ve strcasecmp () ile yapılır.

Sorun yoktur dizinleri ile bu işlev için herhangi bir çağrı FALSE dönecektir, çünkü ben mutlak bir yol oluşturmak için () realpath kullanamazsınız olmasıdır. Aşağıda onları doğrulamak için yolları bakarak benim en iyi girişimdir.

function is_sub_dir($path = NULL, $parent_folder = NULL) {

    //Convert both to real paths
    //Fails if they both don't exist
    //$path = realpath($path);
    //$parent_folder = realpath($parent_folder);

    //Neither path is valid
    if( !$path OR !$parent_folder ) {
    	return FALSE;
    }

    //Standarize the paths
    $path = str_replace('\\', '/', $path);
    $parent_folder = str_replace('\\', '/', $parent_folder);

    //Any evil parent directory requests?
    if(strpos($path, '/..') !== FALSE) {
    	return FALSE;
    }

    //If the path is greater
    if( strcasecmp($path, $parent_folder) > 0 ) {
    	return $path;
    }

    return FALSE;
}

//BAD FOLDER!!!
var_dump(is_sub_dir('/var/www/html/site/uploads/../', '/var/www/html/site/uploads/'));

Herkes düzgün düşük seviyeli klasör erişime karşı korumak için bir yerde dosya yolu blokları koymak nasıl biliyor mu?

: GÜNCEL:

Ben daha bu kontrol yöntemi, birden sunucularının kullanılan yanı sıra belirli bir dizinin daha yüksek dizin oluşturulması olacağını açıklamak istiyorum.

Örneğin, benim yüklenenler dizine ben yöneticiler gibi ...uploads/sub/ gibi yeni alt dizinleri oluşturmak için izin istiyoruz. Benim adminleri yüklenenler klasöründe dosya sistemi ile çalışmak için izin daha güvenli hissediyorum - Verilen dizin is in fact higher üst dizinin daha sigortalamak için güvenilir bir yol bulmaktan.

Yani uploads/sub Tekrar yok, çünkü ben o uploads/sub) Bunu ben (realpath kullanamazsınız oluşturmak uploads/ eskisinden daha yüksektir doğrulamak gerekebilir beri .

PHP ile anında figürlü yüklenenler klasörünün gerçek konumunu gelince.

define('UPLOAD_PATH', realpath(dirname(__FILE__)));

: GÜNCELLEME 2:

Bir fikrim var, ne tam yolunu eksi son dizin kesimi karşılaştırmak için realpath kullanmak olsaydı. Sonra bu son dizin kesimi hala oluşturulan gereken bile - yolun geri kalanı asgari üst dizini maç zorunda olabilir?

4 Cevap

Yolunda son dizin henüz yoksa bile aşağıdaki kod çalışır. Herhangi bir faul veya ek eksik dizinleri döndürür false.

Bu işleve sınırı sadece vb standart İngilizce karakterleri (/. HTS /, / files.90.3r3 /, / my_photos /) kullanılarak (çoğunlukla) zaten mevcut yolları ve dizin adları ile çalışır.)

function is_sub_dir($path = NULL, $parent_folder = SITE_PATH) {

    //Get directory path minus last folder
    $dir = dirname($path);
    $folder = substr($path, strlen($dir));

    //Check the the base dir is valid
    $dir = realpath($dir);

    //Only allow valid filename characters
    $folder = preg_replace('/[^a-z0-9\.\-_]/i', '', $folder);

    //If this is a bad path or a bad end folder name
    if( !$dir OR !$folder OR $folder === '.') {
    	return FALSE;
    }

    //Rebuild path
    $path = $dir. DS. $folder;

    //If this path is higher than the parent folder
    if( strcasecmp($path, $parent_folder) > 0 ) {
    	return $path;
    }

    return FALSE;
}

Değil bir acil sorunun cevabı ancak never gerçek bir güvenlik ortamında kara liste kullanmak gerekir.

Eğer dizin düzenleri değiştirmek ancak kara listeden güncellemek için unutmak olabilir çünkü güvenlik iktidarsız bırakarak bulunuyor.

Beyaz liste ile, onlar yüklemek için izin konum yerleri listeler. Eğer düzenini değiştirmek ve beyaz listeyi değiştirmek için unutursanız, güvenlik aslında increased, azalmış değil. Ve kullanıcıların protesto uluyor sizin unutkanlık için sizi uyaracaktır.

Alt düzey dizinlere erişim izin vermeme açısından, ben (ile gerçek yolunu almanın basit bir mesele düşünürdüm tüm bu ./ ve ../ ve \\ o ile başlarsa bundan sonra bir daha / karakter varsa bir normalleştirilmiş forma dönüştürülmüş) ve ardından, /var/www/html/site/uploads/, başarısız.

Ben daha önce bu normalleşme yaptık ve bu temelde (bellek) oluşur:

  1. Tüm \\ olarak değiştirin / (yani UNIX-izm kullanır).
  2. O / ile başlamazsa, ön baz dizin eklemek (bu yüzden her zaman mutlak bir yol var).
  3. / (hamle "geçerli dizin kalış" yararsız kurtulur) tüm /./ olarak değiştirin.
  4. Tüm /X/../ olarak değiştirin / X olmayan herhangi bir / karakter (aşağı-yukarı dizin hamle kurtulur) olduğu.
  5. Then, geçerli bir yeri olduğundan emin olun.

(../.. için quivalent olarak gördüğüm ...) kullanılabilir daha dizin hareket komutları olup olmadığına bağlı olarak kenar durumlar olabilir ama ne sol, genellikle kullanımı güvenlidir. Sizin kilometre değişebilir.

Bildiğim en iyi yolu, sadece web sunucusu olarak çalışan kullanıcı tarafından yükleme dizini ama her şey yazılamaz yapmaktır. Örneğin, Debian, Apache user www-data olarak çalışır. Yani, Apache dışındaki bazı kullanıcı tarafından sahip olunan dünya okunabilir / yürütülebilir, www-data olarak hizmet olabilir tüm dizinleri emin olun, ve bu kullanıcıya (ya da bazı yönetici grubu) tarafından sadece yazılabilir. Bir dizin web sunucusu tarafından yazılabilir olmalıdır eğer, ben de grup veya sahibi tarafından, www-data tarafından yazılabilir yapmak.

Eğer mümkünse, bu ana sunucu ağacının dışında yazılabilir dizinleri taşımak için de iyi bir fikirdir. Ben sunucu kontrol ederseniz, ben açıkça bu amaçla /var/lib altında bir dizin oluşturun. Ben sunucu kontrol etmezseniz, ben bir sonraki hizmet dizinlere koydu. Örneğin, /var/www/site, ben başka bir düzey eklemek istiyorum sizin örneğini kullanarak, söylemek /var/www/site/html (doğrudan hizmet HTML ve üst düzey komut için), /var/www/site/scripts ( için yüklenen veri için include() ed PHP betikleri) ve /var/www/site/data (). Eğer yüklenen verileri hizmet gerekiyorsa tabii ki, sen onları hizmet ya da altına koymak için bir PHP sarıcı yazmak gerekiyor ya /var/www/site/html/uploads, şimdi bir şeyler yaptığınızı nasıl benzer.

Bu kadar kolay mı?

const UPLOAD_DIR = '/var/www/site/uploads/';

Her zaman size yükleyebilirsiniz tek bir yer var gibi geliyor çünkü sadece sürekli kullanmak kullanmak gerekir. Bu şekilde kolayca berbat olamaz.

if ($dir != UPLOAD_DIR) {
   // No access; Error
}

Bazen kendinizi korumak için sadece uyanık olmak zorunda. Sadece tüm dosya erişimi önce is_sub_dir () aramak için emin olun.

EDIT:

Şimdi soru daha net olduğunu, benim cevabım hayır mantıklı görüyorum. =) Benim sadece diğer tavsiyem ne söylediler yinelemek için:, sterilize sterilize sterilize.