我目前正在perl中编写一个小脚本来连接到我的数据库,检索一些数据并将其显示给用户。检索的数据取决于用户给出的参数。
我使用dbh->quote
来逃避引号:
...
my $dbh=DBI->connect(***);
my $myquery="SELECT * FROM customers WHERE clientName =".$dbh->quote(param('name')) . " AND pass =".$dbh->quote(param('pass'));
my $sth=$dbh->prepare($myquery);
$sth->execute();
my $output=$sth->fetch();
if ($output){
print @$output;
}
...
一位朋友告诉我,这可能不安全,并且他读到有人发现了一个漏洞。我刚开始使用perl,但我想了解这个漏洞是什么。
经过一番挖掘,我发现this document (pdf)似乎在谈论它,但我无法重现这个错误。
答案 0 :(得分:9)
问题主要不在于quote
本身。如果使用得当,quote
是安全的(尽管在这种情况下它不是最佳选择)。但是,如果param
是来自CGI.pm的param
,或者来自其他任何具有相似行为的内容,则会遇到很大问题。
您看,param
与上下文相关。在标量上下文中,如果参数具有单个值(name=foo
),则返回该值,如果参数具有多个值(name=foo&name=bar
),则返回arrayref。在 list 上下文中,它返回值列表,无论是零,一还是多。方法的参数列表(例如quote
)是列表上下文。这意味着使用您的应用的用户可以quote
接收两个值,而quote
的可选第二个参数是SQL数据类型,第一个参数应该被视为。如果数据类型是非NUMERIC
类型的非字符串类型,则quote
将通过传递其第一个参数,而不引用任何引号。这构成了SQL注入的机会。
建议:
虽然正确使用quote
是安全的,但占位符更好,更安全,更难以使用错误。尽可能使用DBI占位符,而不是quote
。
不要在参数列表,哈希构造函数或任何其他可能返回意外数量的项目并破坏您的日期的地方使用CGI的param
。将scalar
放在前面,分配标量或分配给数组。或者,更好的是,完全避免使用CGI.pm和workalike接口。
不要将密码作为纯文本存储在数据库中。如果任何人 都可以访问您数据库的某些部分,那么您的用户密码就会暴露给他们。密码应该是hashed,并且有一些好的,易于使用的Perl模块(Authen::Passphrase可以想到)。
不要将密码作为URL参数传递。 URL很容易通过HTTP引用,浏览器历史记录,粗心的复制/粘贴等泄露。密码应以表格形式发布,最好通过安全连接。
答案 1 :(得分:0)
您可能希望与dbi-users mailing list联系,询问存在哪些漏洞。只要你逃避它们,添加引用并不会使事情变得糟糕。您仍然确保了解所有SQL injections attacks。您可能还希望避免将密码作为url GET参数传递(更喜欢POST请求),因为url(以及任何参数)未加密且可以轻松读取。