【问题标题】:Would displaying PHP Exception Message be a security risk?显示 PHP 异常消息会带来安全风险吗?
【发布时间】:2016-07-02 23:05:27
【问题描述】:

当我在 Laravel 5.1 中抛出错误时,我想设置一条自定义消息显示给用户。例如,在控制器中我可能有:

if(!has_access()){
    abort('401', 'please contact support to gain access to this item.');
}

然后我的自定义错误页面将显示错误:

$exception->getMessage();

但是,如果出现 SQL 错误或其他事件怎么办?那不是也设置了我会在我的错误页面上不知不觉地输出的异常消息吗?

PHP docs for getMessage() 没有详细说明这一点。

如何在不引入任何安全风险的情况下设置特定的异常消息?

【问题讨论】:

  • 我不了解 laravel,但我使用的所有框架都包含一个 HttpException 类(派生自 Exception),并且 catch 块仅捕获该类的异常 @987654326 @。所以,我猜 Laravel 也是如此,因为它已经成为框架的一种普遍做法
  • 可能是的,因为它可能会根据异常显示安全信息,例如用户登录详细信息....但是无论如何您都不应该在生产环境中显示堆栈跟踪,禁用您的应用程序调试设置
  • 确实如此。我只是根据OP的具体函数调用$exception->getMessage()回复的

标签: php security laravel exception-handling laravel-5.1


【解决方案1】:

如果您访问您的app.php 文件:

  'debug' => env('APP_DEBUG', false),

在您的生产环境中,将此设置为 false。这将确保在生产环境中不会显示任何调试错误。

设置完成后,您可以通过控制器响应正常异常。除此之外,laravel 不会显示错误页面。

【讨论】:

  • 也许我做错了什么,但是当我将 APP_DEBUG 设置为 false 然后更改我的数据库配置以使用不正确的 SQL 密码时,$exception->getMessage() 返回:The details are: SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost' (using password: YES) 这正是类型我不希望用户看到的错误。
  • 如果您打开调试并尝试访问任何需要与数据库连接的页面,如果密码错误,则会向最终用户显示异常。但在这种情况下,由于您关闭了调试模式,默认消息将是Something went wrong。 Laravel 会隐藏之前与数据库相关的错误信息。这将阻止您的数据库信息显示给用户。在您的示例中,您明确尝试访问异常并显示它。
  • 对。我正在覆盖“出现问题”错误页面并使用我自己的自定义错误页面(包括错误消息)。我希望我可以抑制系统消息并只显示我手动设置的消息。
  • 所以在这种情况下,您应该检查异常类型并调用相应的页面:例如:如果找不到用户,请致电abort(404),任何与付款相关的错误,请致电abort(501),...
  • 是的,我想调用 abort(401) 但我还想向用户传递一条动态消息,解释确切原因。
【解决方案2】:

但是,如果出现 SQL 错误或其他事件怎么办?那不是也设置了我会在我的错误页面上不知不觉地输出的异常消息吗?

可能,是的。 PHP 不保证向用户显示异常消息的内容是“安全的”,并且某些类很可能会抛出异常,其中包含敏感信息消息。

如果您想使用异常向用户显示错误,请为这些异常使用Exception 的特定子类,并且仅当异常是该子类的实例时才打印消息,eg

class UserVisibleException extends Exception {
    // You don't need any code in here, but you could add a custom constructor
    // if you wanted to.
}

// Then, in your abort() function...
throw new UserVisibleException($message);

// Then, in your exception handler...
if ($exc instanceof UserVisibleException) {
    print $exc->getMessage();
} else {
    print "An internal error occurred.";
}

【讨论】:

    【解决方案3】:

    是的,

    $e->getMessage() 如果您以类似的方式使用它,则可能会显示有关您的代码的更多信息:

    try {
        $executeSomethingHereForWhichYouExpectAnException();  
    // Basic \Exception that reports everything  
    } catch (\Exception $e) {
        $error = $e->getMessage();
    }
    

    即使在app.php 中使用'debug' => false。例如,如果您的代码有错误 $error 会显示它 - 基本上是任何类型的错误(PHP、MYSQL、ETC);

    但是,有一个修复方法 - 捕获您的 CustomException 消息并防止出现典型错误(如果您像这样使用它):

    try {
        $executeSomethingHereForWhichYouExpectAnException();
    // Our custom exception that throws only the messages we want
    } catch (\CustomException $e) {
        // Would contain only 'my_custom_message_here'
        $error = $e->getMessage();
    }
    

    您可能会问有什么不同 - 不同之处在于我们使用 \CustomException 类而不是基本错误报告,而是您从 $executeSomethingHereForWhichYouExpectAnException() 函数中抛出的:

    executeSomethingHereForWhichYouExpectAnException(){
       if (something) {
         throw new CustomException("my_custom_message_here", 1);
       }
    }
    

    如果您有更多例外,您可以像这样包含它们(从 PHP7.1 开始):

    try {
       something();
    } catch(\CustomException | \SecondCustomException $e) {
      // custom exceptions
    } catch(\Exception $e) {
      // basic exception containing everything
    }
    

    【讨论】:

      猜你喜欢
      • 2010-12-28
      • 1970-01-01
      • 2020-11-03
      • 2012-08-19
      • 2014-11-24
      • 1970-01-01
      • 2013-05-03
      • 1970-01-01
      • 2015-04-25
      相关资源
      最近更新 更多