为什么连接失败时 PDO 会打印我的密码?

发布于 2024-11-16 20:36:27 字数 816 浏览 0 评论 0原文

我有一个简单的网站,我使用 PDO 与 MySQL 服务器建立连接。

$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306',
               'USER',
               'SECRET', 
               array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

我的网站上有一些流量,并且已达到服务器的连接限制,并且网站抛出此错误,其中包含我的明文密码!

致命错误:未捕获的异常 带有消息的“PDOException” 'SQLSTATE[08004] [1040] 太多 连接'在 /home/domain/html/index.php:xxx 堆栈跟踪:#0 /home/domain/html/index.php(64): PDO->__construct('mysql:host=loca...', “用户”、“秘密”、数组)#1 {main} 投入 /home/domain/html/index.php 上 第64行

具有讽刺意味的是,出于安全原因,我切换到了 PDO,所以这确实让我感到震惊,因为在大多数站点上使用简单的 HTTP 泛洪很容易引发这个确切的错误。

我现在已将连接包装在 try/catch 块中,但我仍然认为这是灾难性的!

我是 PDO 新手,所以我的问题是:我必须做什么才能确保安全?如何以安全的方式建立连接?是否还有其他类似的已知安全漏洞需要我注意?

I have a simple website where I establish a connection to a MySQL server using PDO.

$dbh = new PDO('mysql:host=localhost;dbname=DB;port=3306',
               'USER',
               'SECRET', 
               array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));

I had some traffic on my site and the server's connection limit was reached, and the website throws this error, with my plain password in it!

Fatal error: Uncaught exception
'PDOException' with message
'SQLSTATE[08004] [1040] Too many
connections' in
/home/domain/html/index.php:xxx
Stack trace: #0
/home/domain/html/index.php(64):
PDO->__construct('mysql:host=loca...',
'USER', 'SECRET', Array) #1
{main} thrown in
/home/domain/html/index.php on
line 64

Ironically I switched to PDO for security reasons, so this really shocked me, because this exact error is something you can provoke very easily on most sites using simple HTTP flooding.

I have now wrapped my connection in a try/catch block, but still I think this is catastrophic!

I am new to PDO and so my question is: what do I have to do to consider to be safe? How do I establish a connection in a secure way? Are there other known security holes like this one that I have to be aware of?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

恬淡成诗 2024-11-23 20:36:27

无论如何,您应该在 PHP.ini 中设置 display_errors = off 以避免此问题。除了 PDO 之外,揭示此类详细信息的错误还来自许多地方。

是的,您还应该将其放在 try/catch 块中。

您还可以 $pdo->setAttribute(PDO::ERRMODE_SILENT),但是您需要手动检查错误代码,而不是使用 try/catch 块。请参阅http://php.net/manual/en/pdo.setattribute.php 了解更多误差常数。

You should have display_errors = off in your PHP.ini anyway to avoid this problem. Errors that reveal details like these come from many places, in addition to PDO.

Yes, you should also have it in a try/catch block.

You can also $pdo->setAttribute(PDO::ERRMODE_SILENT), but then you need to be checking the error codes manually rather than using a try/catch block. See http://php.net/manual/en/pdo.setattribute.php for more error constants.

向地狱狂奔 2024-11-23 20:36:27

一个简单的解决方法是捕获 PDO 构造函数抛出的 PDOException:

try {
    $dbh  =  new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER',
    'SECRET', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
} catch (PDOException $e) {
    throw new Exception($e->getMessage());
}

A simple workaround is to catch the PDOException thrown by the PDO constructor:

try {
    $dbh  =  new PDO('mysql:host=localhost;dbname=DB;port=3306', 'USER',
    'SECRET', array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
} catch (PDOException $e) {
    throw new Exception($e->getMessage());
}
山田美奈子 2024-11-23 20:36:27

好吧,这让我咯咯笑了一点。错误报告的使用是为了调试目的,它可以让您快速找到并修复问题。

当您处于实时环境中时,您的服务器应该配置为仅用于内部日志记录,而不是直接输出,因此基本上您需要关闭 php.ini 中的错误输出。

display_errors = Off

但是,当您处于测试环境中时,该堆栈只是一个可以帮助您的工具并且是可配置的。

当实时环境中发生错误时,它们会被记录下来,因此您应该始终检查日志文件,然后进行相应的修复。

人们可能会指定您可以管理 PHP 应用程序中的错误,但根据个人喜好,我认为这是错误的方法。为您的 Web 服务器和 MySQL / SQL Server 配置 INI 和配置文件将导致更精确的管理。

如果您的应用程序是公共应用程序,那么处理应用程序内的错误也是一个好主意,因为很大一部分客户端可能位于共享托管上并且无法完全访问服务器配置。

Ok, this made me giggle a little. The usage of error reporting is for debugging purposes, and it allows you to quickly find and fix issues.

When you're within a live environment your server should be configured for internal logging only, and not direct output, so basically you will need to turn off the output of errors within your php.ini.

display_errors = Off

But while you're within your test environment, this stack is merely a tool to help you and is configurable.

When errors occur within a live environment they would be logged, so you should always be checking your log files and then fix accordingly.

People may specify that you can manage errors within your PHP application, but by personal preference I think this is the wrong way to go about it. Configuring the INI and configuration files for your web-server and MySQL / SQL Server will result in more acute management.

If your application is a public application then it would also be a good idea to handle errors within the application as a large percentage of clients may be on shared hosting and not have full access to server configurations.

陌路终见情 2024-11-23 20:36:27

我们使用编码的用户名和密码,并在 PDO 构造函数中对其进行解码。然后我们捕获 PDOException 并抛出一个新的 PDOException 以及旧异常的消息,以便跟踪将仅显示编码的用户名和密码。

一个好的 PHP 加密库是 defuse/php-encryption

示例代码:

<?php
class myPDOWrapper extends PDO
    {

        public function __construct(string $dns, string $encodedUser, string $encodedPassword)
        {
            try {
                parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword),
                    [
                        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    ]
                );
            }
            catch (PDOException $exception) {
                throw new PDOException($exception->getMessage());
            }
        }

        private function decodeFunction(string $encoded): string
        {
            return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey());
        }

        private function decodeKey(): \Defuse\Crypto\Key
        {
            static $key = null;

            if(null === $key) {
                $key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY'));
            }

            return $key;
        }
    }

We use encoded username and passwords, and decode those in the PDO constructor. Then we catch the PDOException and throw a new PDOException with the old exception its message, so that the trace will show only the encoded username and password.

A good encryption library for PHP is defuse/php-encryption.

Example code:

<?php
class myPDOWrapper extends PDO
    {

        public function __construct(string $dns, string $encodedUser, string $encodedPassword)
        {
            try {
                parent::__construct($dns, $this->decodeFunction($encodedUser), $this->decodeFunction($encodedPassword),
                    [
                        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                    ]
                );
            }
            catch (PDOException $exception) {
                throw new PDOException($exception->getMessage());
            }
        }

        private function decodeFunction(string $encoded): string
        {
            return \Defuse\Crypto\Crypto::decrypt($encoded, $this->decodeKey());
        }

        private function decodeKey(): \Defuse\Crypto\Key
        {
            static $key = null;

            if(null === $key) {
                $key = \Defuse\Crypto\Key::loadFromAsciiSafeString(getenv('MY_PDO_DECODE_KEY'));
            }

            return $key;
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文