我正在开发一个相对较小的应用程序来与 PostgreSQL 对话,并希望获得一些反馈,说明在防止 SQL 注入方面还有多远。
该应用程序在 Perl 中,不使用任何 ORM 模块(仅 DBI)。SQL 语句是用占位符以典型方式构造的:
my $sql = "SELECT * FROM $cfg->{tablename} WHERE foo = ?";
my $sth = $dbh->prepare($sql);
$sth->execute('bar');
插入表名的原因是应用程序必须对多个表执行相同的操作,所有表都有一个列“foo”。
使用 ?占位符可防止大多数简单的 SQL 注入攻击。我的问题是关于表名,你不能使用占位符。该表来自配置文件,但应用程序支持 --configfile 开关以使用备用配置文件。
数据库凭据存储在配置文件中。因此,如果攻击者可以使用 $cfg->{tablename} 替换为恶意内容的配置文件(或替换默认文件),则可能会“诱骗”应用程序运行恶意代码。
对于攻击者来说,他们必须已经拥有有效的数据库凭据,否则应用程序将无法连接。如果他们有凭据,那么他们可以使用 DBI 编写自己的代码或使用 psql cli 执行恶意操作。
我看到了两种可能的方法来防止这种情况:
- 切换到 ORM,在这种情况下,我会按照 $orm->get_class_for_table($cfg->{tablename}
- 在准备 SQL 语句之前使用正则表达式清理表名
- 使用 $dbh->quote_identifier()
显然第二种方式是“便宜又快乐”的方式。但是鉴于上面关于凭据的声明,这些方法中的任何一种真的有必要吗?在迫使攻击者只使用备用攻击向量(与实际阻止攻击的努力相反?