如何拒绝使用危险的PHP函数?

如何拒绝使用危险的PHP函数?,php,Php,可能重复: 您好,这是我的情况:我必须让我的客户输入PHP代码,但只有安全的函数,如字符串函数,日期函数等。所以我需要危险的PHP函数列表,以删除他们使用字符串替换之前保存到PHP文件。有什么建议吗?别提了。可靠的函数白名单在php中是不可能的。例如: $x = 'e' . str_replace('y', 'x', 'yec'); ...lots of code... $x('format c:'); 现实的选择是 禁用功能() 沙箱(参见) 给用户输入PHP代码的可能性是非常危险的。在

可能重复:


您好,这是我的情况:我必须让我的客户输入PHP代码,但只有安全的函数,如字符串函数,日期函数等。所以我需要危险的PHP函数列表,以删除他们使用字符串替换之前保存到PHP文件。有什么建议吗?

别提了。可靠的函数白名单在php中是不可能的。例如:

$x = 'e' . str_replace('y', 'x', 'yec');
...lots of code...
$x('format c:');
现实的选择是

  • 禁用功能()
  • 沙箱(参见)

    • 给用户输入PHP代码的可能性是非常危险的。在实现这一点之前,考虑所有其他选项。某种PHP代码生成器。灵感来源于查询生成器


      如果您决定允许客户端使用PHP代码,最好使用白名单。您应该使用正则表达式从发布的代码中提取这些函数。

      如果您想正确执行,您需要做的是非常艰苦的工作。我将从输入的php代码开始,检查每个被调用的函数,完全禁止,等等


      换句话说:如果你想允许一个子集的PHP,你必须实现你自己的(即使PHP为你提供了一个开箱即用的工具)。

      据我所知,你只能使用黑名单方法:

      当然,您必须考虑如何维护所有可能扩展定义的所有构建函数的更新列表。

      我能想到的另一种可能性是编写一个简单的标记器:

      然后,您可以对照白名单检查所使用的函数


      更新:我错误地认为
      token\u get\u all()。它们都是
      T_STRING
      s.

      最安全和易于维护的选项是用php编写专用的“迷你语言”。您可以将其作为php的一个子集,或使其看起来像Excel公式,甚至可以发明自己的公式。这样,您将始终能够完全控制正在发生的事情

      //

      只是为了好玩,这里有一个小口齿不清给你

      function lisp($x) {
      
          if(is_string($x)) {
              $re = '~\(([^()]*)\)~';
              while(preg_match($re, $x))
                  $x = preg_replace_callback($re, 'lisp', $x);
              return trim($x);
          }
      
          $x = preg_split('~\s+~', $x[1]);
          $e = array_shift($x);
          if(!$x)
              return is_numeric($e) ?  floatval($e) : $e;
      
          switch($e) {
              case '+':  return lisp($x[0]) + lisp($x[1]);
              case '-':  return lisp($x[0]) - lisp($x[1]);
              case '*':  return lisp($x[0]) * lisp($x[1]);
              case '/':  return lisp($x[0]) / lisp($x[1]);
      
              case 'concat':  return lisp($x[0]) . lisp($x[1]);
          }
      
          return function_exists($e) ?
              call_user_func_array($e, array_map('lisp', $x)) : '';
      }
      
      $input = '
          (strtolower 
              (concat
                  (strrev olleh) 
                  (+ 22 20)))';
      
      echo lisp($input); // hello42
      

      ())

      PHP不是一种正规语言。@Gumbo:请解释这与这种情况有什么关系?@Stegeman你不能在一种非正规语言上使用正则表达式。也许我错了,但他说的是enter,据我理解,这意味着他将发布代码。在这种情况下,代码只是一个字符串,可以在字符串上使用正则表达式,不是吗?如果他想上传代码,我知道我错了。只是想了解和学习一下:)@Stegeman:当然你可以在字符串上使用正则表达式。但是字符串中的数据(即PHP代码)不是常规语言。只需考虑删除PHP代码中的
      foobar
      函数调用:
      @stereofrog,这就是我不推荐它的原因。请随意编辑我的答案,以减少混淆。我不擅长解释,难道这不应该是“可靠的函数白名单在PHP中是不可能的”吗?因为禁用函数可以将其列入黑名单。没有注意到,我会编辑它:p.+1,我不明白为什么人们会将这些问题过于复杂,过于复杂并不会使其更安全,请坚持使用原始方法,例如
      禁用函数
      禁用类
      @stereofrog,我已经明白了你的意思(你并没有说),并相应地编辑了我的文章。PHP.net的令牌文档非常缺乏。他们遗漏了某些标记,也错误地定义了一些标记——或者是这些标记,或者它们的用法是由
      token\u get\u all()
      和PHP的警告/错误消息所决定的,它们是由后者决定的。@stereofrog:当然,你是对的。这甚至不值得尝试。这可能需要大量的工作。您可以制作一个动态范围的lisp-1。你不必告诉他们这是口齿不清。或者,如果您愿意,您可以使用LIME for PHP实现中缀代数,也许可以在[方括号]中实现,并制作类似于TCL的东西。为什么它必须看起来像PHP?或者您可以在PHP中编写PHP子集的解析器,并只运行选定的函数!:D