允许用户调用php方法的安全含义

允许用户调用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

这样做有什么风险?例如,可能有一些特殊字符会通过验证,允许用户包含不需要的文件,或使此处使用的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 -> \publicClasses\dir
$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)
    ];
}
公共类所在的
文件夹中的文件将包含

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

“这样做有什么风险?”-太大了。你是什么意思?脚本的第2行有未经验证的用户输入被直接传递到
dirname
-我当时放弃了。请参见此处:您的脚本尝试使用正则表达式对文件名的用户输入进行清理,但解决大多数正则表达式对文件名施加的过滤器(提示:trigraphs)很简单。你的剧本注定要失败。我告诉你!好吧,这不是生产代码,我快速编写它是为了触发这种答案
dirname
basename
可以轻松替换。Regex是我最关心的问题。非常感谢。