Последствия для безопасности разрешения пользователю вызывать методы php

#php

#php

Вопрос:

Каковы риски, связанные с выполнением чего-то подобного? Например, могут быть некоторые специальные символы, которые будут проходить проверки, позволяют пользователю включать нежелательные файлы или заставлять используемые здесь функции php работать неправильно или вести себя не так, как задумано, о чем я должен знать.

 //parse the uri
$uri=trim(parse_url(urldecode($_SERVER['REQUEST_URI']))['path'],'/');
$path=saferDirnameAndBasename($uri);
$class=$path->dir;
$method=$path->base;

//or it could be done with url rewritting, or just parameters, like:
//$class=$_GET['c'];
//$method=$_GET['m'];

$class=filter_var($class,FILTER_UNSAFE_RAW,FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);
$method=filter_var($method,FILTER_UNSAFE_RAW,FILTER_FLAG_STRIP_LOW|FILTER_FLAG_STRIP_HIGH);

if(preg_match('/[^a-z0-9_/-]/i',$class)||preg_match('/[^a-z0-9_]/i',$method)) exit;

$file=__DIR__.'/folder-where-public-clases-are/'.$class.'.php'; //note that it's allowing subdirs, but I don't want the user to go up
if(!file_exists($file)) exit;
include_once($file);

//remove the dashes too, my-class.php should contain myclass
$class=str_replace('-','',$class);

$path=saferDirnameAndBasename($class);
$namespace='\publicClasses\'.str_replace('/','\',$path->dir); //dir/class -> publicClassesdir
$name=$path->base;
$fullname=$namespace.'\'.$name;

if(!class_exists($fullname)) exit;
$obj=new $fullname;

if(!method_exists($obj,$method)) exit; //I know this doesn't account for visibility prior to php 7.4

call_user_func([$obj,$method]);

function saferDirnameAndBasename($path) {
    $parts=explode('/',$path);
    return (object)[
        'base'=>array_pop($parts),
        'dir'=>implode('/',$parts)
    ];
}
  

Файл в folder-where-public-clases-are будет содержать

 <?php
    namespace publicClasses;
    class myclass {
        public function test() {
        }
    }
  

Это создало бы динамический маршрутизатор, где пути не должны быть определены заранее. Частный код должен просто находиться за пределами publicClasses пространства имен.

Комментарии:

1. «Каковы риски, связанные с выполнением чего-то подобного?» — огромный .

2. Что вы имеете в виду?

3. В строке 2 вашего скрипта непроверенный пользовательский ввод передается непосредственно в dirname — я сдался в этот момент. Смотрите здесь: acunetix.com/websitesecurity/php-security-2

4. Ваш скрипт пытается очистить вводимый пользователем для имени файла с помощью регулярного выражения, но легко обойти большинство фильтров, налагаемых регулярными выражениями для имен файлов (подсказка: триграфы). Ваш скрипт обречен. ОБРЕЧЕН, Я ВАМ ГОВОРЮ!

5. Ну, это не производственный код, я написал его быстро, чтобы вызвать такого рода ответы. dirname и basename может быть легко заменен. Регулярные выражения были моей главной заботой. Спасибо.