MySQL 是否比 PostgreSQL(在 Perl/DBI 下)更能抵抗 SQL 注入攻击?

发布于 2024-08-20 19:55:51 字数 937 浏览 9 评论 0原文

我正在审查一个基于 Linux 的 Perl Web 应用程序,该应用程序包含一个登录处理程序,其中包含无处不在的

my $sth = $DB->prepare("从 userid='$userid'" 的密码中选择密码") or die; $sth->执行或死亡; ...

其中 $userid 是根据(不安全、未过滤的)Web 用户输入初始化的。

众所周知,DBI 文档建议将此代码更改为使用占位符“?”为了安全起见,代替“$userid”。

出于安全审查的目的,此代码按原样隔离在离网设备上。互联网服务器上的此类代码最终将被破解,因为现在有机器人扫描此漏洞。访问控制对于保护任何重要内容也是无效的,因为已知的注入可以删除数据库、插入不良数据或新用户,或者绕过访问控制以允许访问 Web 应用程序。

由于应用程序可以配置为使用 PostgreSQL 或 MySQL,并且提出了有关比较漏洞的问题,因此我尝试了这两个数据库,并通过一些 SQL 注入尝试测试了每个配置。

在 PostgreSQL 下输入 ';在这里做坏事;和这里;会按预期崩溃登录 cgi 并执行坏的东西。

出乎意料的是MySQL竟然抵抗住了这次攻击。这让我想知道 DBD::MySQL 或其他地方是否有某种设置限制每次调用准备 1 个语句,或者 MySQL 以其他方式抵抗。

据我了解,MySQL 通常不抵抗 SQL 注入。

这不仅仅是一个关于消除 SQL 注入技术的问题;而是一个关于消除 SQL 注入的技术问题。为此,也许请参阅如何避免 SQL 注入攻击?

问题是:在 PERL DBI 下,MySQL 是否比 PostgreSQL 更能抵抗 SQL 注入攻击?为什么会出现这种情况?

I am reviewing a Linux based perl web application that contains a login handler with the ubiquitous

my $sth = $DB->prepare("SELECT password from passwords where userid='$userid'") or die; $sth->execute or die; ...

where $userid is initialized from (unsafe, unfiltered) web user input.

It is well known that the DBI documentation recommends that this code should be changed to use the placeholder "?" in place of '$userid' for security.

This code was isolated on an off network box, as-is, for the purpose of a security review. Code like this on an internet server will eventually be cracked as there are bots now that scan for this vulnerability. The access control is also ineffective for protecting anything important because known injections can delete databases, insert bad data or new users, or bypass the access control to allow entry to the web application.

As the application can be configured to use either PostgreSQL or MySQL and questions were raised about comparative vulnerability I tried out both databases and tested each configuration with some SQL injection attempts.

Under PostgreSQL an input of '; do bad stuff here; and here; would crash the login cgi as expected and execute the bad stuff.

What was unexpected was that MySQL resisted this attack. This got me to wonder if there was a setting of some sort for DBD::MySQL or elsewhere that limited prepare to 1 statement per call, or was MySQL resistant in some other way.

As I understand it MySQL is not SQL-injection resistant in general.

This is not a question purely about techniques for eliminating SQL injection; for that perhaps see How can I avoid SQL injection attacks?.

The question is: Is MySQL somehow more resistant than PostgreSQL to SQL injection attack under the PERL DBI and why might this be the case?

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

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

发布评论

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

评论(4

巡山小妖精 2024-08-27 19:55:51

防范注入攻击不是数据库的责任,而是开发人员的责任。如果开发人员编写通过连接从用户输入派生的字符串来创建查询的代码,则生成的查询将容易受到注入攻击,并且所有用于清理等的代码,恕我直言都是浪费时间。如果编写代码以使用参数化查询,并且将用户输入降级为用作参数值,则生成的查询将相当安全,免受注入攻击。 (我有兴趣了解如何通过参数值进行注入攻击)。

分享并享受。

Guarding against injection attacks is not the responsibility of the database, it's the responsibility of the developer. If the developer writes code that creates queries by concatenating strings derived from user input the resulting queries will be vulnerable to injection attacks, and all the code spent on sanitization, etc, is IMHO a waste of time. If the code is written to use parameterized queries, and user input is relegated to being used as parameter values, the resulting queries will be reasonably safe from injection attacks. (And I'd be interested in hearing how it might be possible to do an injection attack through a parameter value).

Share and enjoy.

余罪 2024-08-27 19:55:51

默认情况下,MySQL 客户端库似乎限制每次调用一条语句(我在 PHP 中遇到过)。

但这不应该成为使用 MySQL 而不是 PostgreSQL 的理由,因为您仍然可以通过使用子查询进行注入。

The MySQL client library seems to limit to one statement per call by default (I encountered it with PHP).

But that's shouldn't be a reason to use MySQL over PostgreSQL, since you can still inject by using subqueries.

哀由 2024-08-27 19:55:51

不,事实上,MySQL 几乎绝对不安全,在这种情况下,似乎准备语句根本没有在服务器上完成。

准备好的语句支持(服务器
侧面准备)从 3.0002_1 开始,服务器
侧面准备声明是由
默认(如果您的服务器 >= 4.1.3)。
从 3.0009 开始,它们默认处于关闭状态
再次由于准备的问题
语句 API(所有其他 mysql
连接器以这种方式设置,直到 C
API 问题已解决)。这
使用准备好的语句的要求
仍然存在您有一个服务器 '>= 4.1.3'

使用服务器端准备
声明,您需要做的就是设置
变量 mysql_server_prepare 中
连接:

$dbh = DBI->连接(
“DBI:mysql:数据库=测试;主机=本地主机;mysql_server_prepare=1”,
"", "", { RaiseError =>; 1、自动提交
=> 1 } );

  • 注意:此参数的分隔符为“;”

使用有很多好处
服务器端准备语句,主要是
如果您正在执行多次插入
因为这个事实
声明准备接受
多个插入值。

确保“进行测试”步骤
测试服务器准备是否有效,
你只需要导出环境
变量 MYSQL_SERVER_PREPARE:

导出 MYSQL_SERVER_PREPARE=1

据推测,它们是在 PostgreSQL 的服务器上准备的。

就安全性而言,您只是做错了:正如您所说,使用 ? 。否则你只是在利用 Postgres 可以准备多个语句:这并不是什么负面的事情。我相信 MySQL 也可以做到这一点,这里唯一的区别是 DBD::MySQL 声称 C API 问题妨碍了服务器端准备的使用,因此它们依赖于其他一些来源作为服务器的权威。现在 DBD::MySQL 可能在 mysql 库中使用 C 函数,该函数早于 MySQL 进行服务器端准备(我的猜测是 4.1.3 之前)。

No, in fact, MySQL is almost categoricially less secure, in this case it appears as if the prepare statements are not done on the server at all.

Prepared statement support (server
side prepare) As of 3.0002_1, server
side prepare statements were on by
default (if your server was >= 4.1.3).
As of 3.0009, they were off by default
again due to issues with the prepared
statement API (all other mysql
connectors are set this way until C
API issues are resolved). The
requirement to use prepared statements
still remains that you have a server '>= 4.1.3'

To use server side prepared
statements, all you need to do is set
the variable mysql_server_prepare in
the connect:

$dbh = DBI->connect(
"DBI:mysql:database=test;host=localhost;mysql_server_prepare=1",
"", "", { RaiseError => 1, AutoCommit
=> 1 } );

  • Note: delimiter for this param is ';'

There are many benefits to using
server side prepare statements, mostly
if you are performing many inserts
because of that fact that a single
statement is prepared to accept
multiple insert values.

To make sure that the 'make test' step
tests whether server prepare works,
you just need to export the env
variable MYSQL_SERVER_PREPARE:

export MYSQL_SERVER_PREPARE=1

Presumably, they are prepared on the server in PostgreSQL.

So far as security is concerned, you're simply doing it wrong: use ? as you've said. Otherwise you're just exploiting that Postgres can prepare multiple statements: and that isn't something negative. I believe MySQL can probably do this too, the only difference here is DBD::MySQL is claiming that C API issues preclude the use of the server-side prepares so they're relying on some other source as being authoritative for the server. Right now DBD::MySQL is probably using C function in a mysql library that predates MySQL having server-side prepares (pre 4.1.3 is my guess).

小梨窩很甜 2024-08-27 19:55:51

拥有针对 SQL 注入的通用清理工具即使不是不可能,也可能很困难。

添加[正如评论的那样,正确使用 DBI 并在 DB 客户端库的帮助下,在准备 SQL 语句方面肯定可以最大程度地减少注入。但是,请务必记住,清理用户输入还涉及独立于所使用的数据库的应用程序逻辑。例如,使用其他用户的凭据可能会提供有效且安全的声明,但会带来意想不到的后果。无论如何,这比提出的问题更进一步。]

已删除[您最好自己清理输入,而不是对客户端对此类攻击的抵抗有任何虚假的安全感。并不是说您不应该使用它们,只是不要假设它们对攻击提供的帮助超过最小限度。]

It might be difficult, if not impossible, to have a generic sanitizer against SQL injections.

Added [As commented, using the DBI correctly and with the help of the DB's client library, the injections can certainly be minimized with respect to preparing the SQL statement. However, it's important to keep in mind that sanitizing user input also involves application logic which is independent of the DB used. For example, using another user's credentials may provide a valid and safe statement, but with unintended consequences. Anyway, that's going further than the question asked.]

Removed [You're better off sanitizing the input yourself rather than having any sense of false security on the client's resistance to these types of attacks. Not that you shouldn't use them, just don't assume they provide more than minimal help against the attacks.]

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