use*_*433 3 sql-server sql-injection dynamic-sql t-sql
考虑:
Declare @stringsvar varchar(1000)
Declare @Emp_id int
DECLARE @strvar SYSNAME = 'Employee_test'
SET @stringsvar = ('select * from' + ' ' + @strvar + ' where emp_id' + ' =' + @Emp_id)
Print @stringsvar
Run Code Online (Sandbox Code Playgroud)
上面的查询给出了如下所述的错误:
将 nvarchar 值 'select * from Employee_test where emp_id =' 转换为数据类型 int 时,消息 245,级别 16,状态 1,第 17 行转换失败。
在这种情况下需要做什么?
Eri*_*ing 13
George 的回答确实解决了您的问题,但它让您对SQL 注入攻击持开放态度。
虽然将 an 转换INT为 aVARCHAR 11可能不会导致任何问题,但sysname相当于 an NVARCHAR 128,并且您可以在其中塞入大量额外代码。
为了使您的代码完全安全,您需要这样做:
DECLARE @stringsvar NVARCHAR(1000) = '';
DECLARE @Emp_id INT = 1;
DECLARE @strvar sysname = N'Employee_test';
SET @stringsvar = ( N'select * from '
+ QUOTENAME(@strvar)
+ N' where emp_id'
+ N' = @iEmp_id' );
PRINT @stringsvar;
EXEC sys.sp_executesql @stringsvar,
N'@iEmp_id INT',
@iEmp_id = @Emp_id;
Run Code Online (Sandbox Code Playgroud)
使用sp_executesql发出参数化的动态 SQL,使用quotename使表名成为不可执行的代码是更安全的选择。
如需更多参考,我建议前往此处:动态 SQL 的诅咒和祝福
问题归结为数据类型优先级。
在这种情况下,INT数据类型具有更高的优先级,因此在这种情况下将数据类型VARCHAR转换(或尝试转换)为更高优先级的数据类型 ( INT)。
一个简单的 CASTVARCHAR应该可以解决这个问题,如下所示
Declare @stringsvar varchar(1000)
Declare @Emp_id int
DECLARE @strvar SYSNAME = 'Employee_test'
SET @stringsvar = ('select * from' + ' ' + QUOTENAME(@strvar) + ' where emp_id' + ' =' + CAST(@Emp_id AS VARCHAR(11)))
Print @stringsvar
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
601 次 |
| 最近记录: |