table 架构和名称的正则表达式验证

Regex validation of table schema and name

我有一个 API 对调用者指定的 table 执行一些查询。 table 名称通过字符串替换放置在查询中,因此存在 SQL 注入的风险。

示例:

tableName = req.body.tableName;

sql = "SELECT * FROM <<TABLE_NAME>>;";
sql = sql.replace("<<TABLE_NAME>>", tableName);

我需要保持此查询动态,因为我们不想在每次添加新 table 时都重新部署此代码。换句话说,我不能只维护一个有效 table 名称的列表。

因此,为了防止 sql 注入,对 table 名称进行正则表达式验证是否足够?我们可以确定 table 名称将始终采用 schema.table_name 格式,其中 table_name 将仅为 a-z、0-9、-、_

是否有任何 sql 注入可以绕过此 table 名称正则表达式?

^myschema\.[a-zA-Z0-9-_]+$

减号不能用作SQL中的标识符。对于 table 名称,我认为不会导致 SQL 注入攻击,但如果允许在列名称中使用减号,则可以注入减法。 在 MySQL 的情况下,以下 SQL 语句将 return 所有用户,而不仅仅是 'tom'。这是因为从字符串中减去时会发生隐式类型转换。

SELECT * FROM users WHERE myschema.user-0 = 'tom'

解决方法是排除减号或引用标识符。以下不会导致 SQL 注入攻击。

SELECT * FROM users WHERE `myschema`.`user-0` = 'tom'.

以上是MySQL的写法,标准SQL的写法如下

SELECT * FROM users WHERE "myschema"."user-0" = 'tom'

由于减号不是 table 名称中的有效字符,您可以将正则表达式更改为:

^myschema\.\w+$

\w 等同于 [a-zA-Z0-9_]

无注射风险


如果使用特殊语法,大多数数据库允许在 table 名称中使用特殊字符,甚至是空格和减号,例如

MySQL: `my stupid table-name!`
Postgres: "my stupid table-name!"
SQL Server: [my stupid table-name!]

一开始就允许在名称中使用非标准字符是不好的做法,在您的情况下拒绝此类名称会很好。