Şablon dili olarak PHP Kullanımı

5 Cevap php

Edit: Harika noktaları çevresinde, özel çiftleşmiş dil açıkçası gitmek için yoludur. Teşekkürler!

Ben PHP ile çiftleşmiş yapmak için bu hızlı sınıf yazdı - Ben kullanıcılara çiftleşmiş açmak hiç olsaydı, bu kolayca işletilebilir olup olmadığını merak (değil acil planı, ama yolda düşünme) oldu.

class Template {

private $allowed_methods = array(
    'if', 
    'switch', 
    'foreach',
    'for', 
    'while'
);

private function secure_code($template_code) {
    $php_section_pattern = '/\<\?(.*?)\?\>/';
    $php_method_pattern = '/([a-zA-Z0-9_]+)[\s]*\(/';
    preg_match_all($php_section_pattern, $template_code, $matches);
    foreach (array_unique($matches[1]) as $index => $code_chunk) {
        preg_match_all($php_method_pattern, $code_chunk, $sub_matches);
        $code_allowed = true;
        foreach ($sub_matches[1] as $method_name) {
            if (!in_array($method_name, $this->allowed_methods)) {
                $code_allowed = false;
                break;
            }
        }
        if (!$code_allowed) {
            $template_code = str_replace($matches[0][$index], '', $template_code);
        }
    }
    return $template_code;      
}

public function render($template_code, $params) {
    extract($params);
    ob_start();
    eval('?>'.$this->secure_code($template_code).'<?php ');
    $result = ob_get_contents();
    ob_end_clean();
    return $result;     
}

}

Örnek kullanım:

$template_code = '<?= $title ?><? foreach ($photos as $photo): ?><img src="<?= $photo ?>"><? endforeach ?>';
$params = array('title' => 'My Title', 'photos' => array('img1.jpg', 'img2.jpg'));
$template = new Template;
echo $template->render($template_code, $params);

Burada fikir, ben veritabanındaki şablonları (PHP kodu) depolamak ve daha sonra (eğer, vb) yalnızca izin izin yöntemleri için normal ifadeler kullanır sınıfı aracılığıyla çalıştırmak istiyorum olmasıdır. Herkes bu istismar ve keyfi PHP çalıştırmak için belirgin bir yol görüyor musun? Eğer öyleyse, muhtemelen böyle Smarty gibi bir çiftleşmiş dilin daha standart yol gidersiniz ...

5 Cevap

Tabii ..

$template_code = '<?= `rm -rf *`; ?>';

Edit:

Hemen başka bir şey düşünemiyorum. Ama işlemek zamankinden daha üzerinde birden çok kez aynı Template örneği denir EĞER sizin kapsamı tehlikeye bilmeli.

Örneğin, render('<?php $this->allowed_methods[] = "eval"; ?>') .. Daha sonra bu örneği Template eval hale gelecek için kabul edilebilir bir fonksiyon olarak olacak eğer .. ;)

Bu iyi bir fikir değil. Eğer acil güvenlik açıkları düzeltmek bile, şüphesiz sen kaçırmış diğerleri olacak. Eğer gerçekten, kullanıcılara bu olanağı vermek gibi Smarty gibi gerçek bir şablon dili kullanmak, veya kendi yazmak isterseniz ben söyleyebilirim. PHP iç kullanım için bir çiftleşmiş dil olarak büyük değil, ama tüm kullanıcıların kullanabileceği açık biri olarak. Bu tüm bunları yakalamak bile, gerçek bir çiftleşmiş motoru yazma daha fazla iş yapmak istiyorum sömürdü alabilirsiniz sadece çok yolu vardır.

Kullanmak {ve} değişkenleri ile ve herhangi bir işlevi çalıştırabilirsiniz.

$template_code = '<?php $f = "phpinfo"; ${"f"}(); ?>';

Sadece kod çalıştıran çünkü Ayrıca, bu işlev hale erişebilirsiniz tüm değişkenler erişim olurdu. hemen hemen her yerde ya da $ _SESSION (böyle bir seçenek oturum açma bilgilerini tutan ve başka bir siteye ajax aracılığıyla göndermek için javascript kullanarak oturum değişkenleri olabilir) gibi super globallerinin değişkenleri değiştirmek için küresel çağrı dahil.

$a = "hello";
$template_code = '<?php global $a; $a = "test"; ?>';
$params = array('title' => 'My Title', 'photos' => array('img1.jpg', 'img2.jpg'));
$template = new Template;
echo $template->render($template_code, $params);
echo $a;

izin verilen işlev olarak aynı ad ve herhangi bir işlev adının değerine sahip bir değişken yaparak izin fonksiyonları kötüye başka biri.

$template_code = '<?php $if="phpinfo"; $if(); ?>';

Böyle bir şey çalışır düşünerek yanlış mıyım?

<?php
/* ?> trick your parser by using a comment */
// do whatever unfiltered

Eğer gerçekten böyle bir şey yapmak istiyorsanız, kaynak ayrıştırmak için tokenizer kullanın. Ama bunu tavsiye etmiyoruz. Aslında, ben onu vazgeçirmek!

Eğer içeriği katkıda kullanıcımız var ve bu kullanıcılar tamamen güvenilir değilse, ben whitelisting yerine blacklisting biçimlendirme tavsiye ederim.

Örneğin, yığın taşması tarafından izin Markdown biçimlendirme düşünün. Bu biçimlendirme seçenekleri çok kısa bir listesini destekleyen ve her şey edebi metin olarak kabul edilir. Çoğu kullanıcı yerine diyor bir arayüzü basit bir arayüzü ile mutlu olan "app kırmak için değil, istediğiniz herhangi bir kod yazın! Ama dikkatli olun!"

Zaman kural geçerli: allow users to enter data and content; never allow users to enter code.