从本地文件读取SQL,然后对其进行评估。安全吗?

时间:2018-01-24 15:23:40

标签: mysql perl

我继承了代码中包含非常大的SQL查询的代码,通常在heredocs中,并且内插的变量会动态选择一个或多个表,如下所示:

    my $query = <<"SQL";
SELECT foo
FROM $some_table
WHERE bar = 'baz'
SQL

一些SQL查询非常大。问题是这使得我的Perl文件不必要地长而且难以阅读。代码分析和突出显示工具也无法解析heredoc SQL。

我想将SQL保存在实际的SQL文件中并更改上面的Perl代码以从本地目录中读取文件:

my $query = eval(get_sql('some-file.sql'));

... eval - 这样可以扩展所有范围内的变量。

其中一些将发生在用户传递参数的Web可访问脚本中。绝对所有变量都被清理了,我在所有条件子句中使用了参数化语句(WHERE,AND等)

关于使用eval()有很多FUD,所以我想知道:我的解决方案在Web应用程序中使用是否安全?

修改 ...
我应该进一步提到get_sql()函数可能看起来像这样:

sub get_sql {
    my ($filename) = @_;

    my $sql = slurp("/path/to/file/$filename.sql");
    my $query = qq|return qq{| . $sql . qq|};|;
    return $query;
}

我知道引号运算符不能出现在将返回的SQL字符串中。

EDIT2 ...
给定任意数量的用例和/或约束,这是一个非常合理的问题。 Downvotes ......没有理由,伙计们。

1 个答案:

答案 0 :(得分:2)

首先,

my $query = <<"SQL";
SELECT foo
FROM $some_table
WHERE bar = 'baz'
SQL

患有注射虫。它应该是

my $some_table_lit = $dbh->quote_identifier($some_table);

my $query = <<"SQL";
SELECT foo
FROM $some_table_lit
WHERE bar = 'baz'
SQL

您的模板系统非常糟糕。这相当于锤击螺钉的CS。它使编写不安全的代码变得非常容易(正如您已经完成的那样),它引入了高耦合,并使代码非常脆弱。

您应该使用比您当前使用的更好的模板系统(有或没有eval)。

以下是使用Template-Toolkit的示例:

my $tt = Template->new();

$tt->process('some-file.sql', {
   some_table => $dbh->quote_identifier($some_table),
})
   or die $template->error();

SELECT foo
FROM [% some_table %]
WHERE bar = 'baz'