我正在开发一个相对较小的应用程序来与PostgreSQL交谈,并希望得到一些关于防止SQL注入的距离太远的反馈。
应用程序在Perl中,不使用任何ORM模块(只是DBI)。 SQL语句以典型的方式使用占位符构建:
my $sql = "SELECT * FROM $cfg->{tablename} WHERE foo = ?";
my $sth = $dbh->prepare($sql);
$sth->execute('bar');
对tablename进行插值的原因是应用程序必须对多个表执行相同的操作,所有表都有一个列'foo'。
使用?占位符可以防止大多数简单的SQL注入攻击。我的问题是在tablename周围,你不能使用占位符。该表来自配置文件,但该应用程序支持--configfile开关以使用备用配置文件。
数据库凭据存储在配置文件中。因此,如果攻击者可以创建一个配置文件(或替换默认配置文件),其中$ cfg-> {tablename}被恶意代替,那么应用程序可能会被“欺骗”以运行恶意代码。
对于攻击者来说,他们必须拥有有效的数据库凭据,否则应用程序将无法连接。如果他们有凭证,那么他们可以使用DBI制作自己的代码或使用psql cli做恶意的事情。
我看到两种可能的方法来防止这种情况:
显然第二种方式是“便宜又开朗”的方式。但鉴于上述证书的陈述,这些方法中的任何一种都是真的有必要吗?在迫使攻击者只使用备用攻击向量时(与实际阻止攻击的努力相反),需要付出多少努力呢?
答案 0 :(得分:10)
my $sql = "SELECT * FROM ".
$dbh->quote_identifier($cfg->{tablename}).
" WHERE foo = ?";
答案 1 :(得分:1)
在这些情况下,我创建了自己的占位符版本,并检查我将作为表名插入的值,以确保它是我期望的表名。这意味着不只是检查表是否存在;某些操作应该只影响某些表而不影响其他表。
我不会使用正则表达式来清理名称。要么是正确的,要么是在允许的名字列表中,要么是错了,你就给错了。