6

我有以下代码用于从 C# 应用程序创建一些数据库

SqlConnection myConnection = new SqlConnection(ConnectionString);
string myQuery = "CREATE DATABASE " + tbxDatabase.Text; //read from textbox
myConnection.Open();
SqlCommand myCommand = new SqlCommand(myQuery, myConnection);
myCommand.ExecuteNonQuery();

现在我担心它是否安全,C# 会接受像“A; DROP TABLE B”这样的黑客输入或类似的东西吗?如何让它更安全?

4

5 回答 5

5

表名和列名不能参数化,但作为第一道防线,用大括号等分隔符将表名包裹起来,

string myQuery = "CREATE DATABASE [" + tbxDatabase.Text + "]";

或创建一个用户定义函数来检查输入的值,例如

private bool IsValid(string tableName)
{
    // your pseudocode
    // return somthing
}

然后在你的代码上,

if (IsValid(tbxDatabase.Text))
{
    SqlConnection myConnection = new SqlConnection(ConnectionString);
    string myQuery = "CREATE DATABASE [" + tbxDatabase.Text + "]";
    myConnection.Open();
    SqlCommand myCommand = new SqlCommand(myQuery, myConnection);
    myCommand.ExecuteNonQuery();
}
else
{
    // invalid name
}
于 2013-02-26T15:08:40.460 回答
1

使用存储过程并传递参数

于 2013-02-26T15:12:16.387 回答
1

是的,您的代码非常不安全,一种替代方法是创建只接受确切参数的存储过程,以避免动态构建命令。

C# 本身不会帮助 ypu 避免这些事情,它应该嵌入到应用程序逻辑中

于 2013-02-26T15:10:14.660 回答
0

完成此操作的安全方法是使用 sql 函数 QUOTENAME() 来转义输入。

CREATE PROC example_create_db ( @db_name NVARCHAR(256) )
AS 
    BEGIN
        DECLARE @sql NVARCHAR(1000)
    /*
        QUOTENAME() adds the surrounding []'s
    */

        SET @sql = 'CREATE DATABASE ' + QUOTENAME(@db_name) 
        EXEC sp_executesql
    END
于 2013-02-26T16:23:02.357 回答
0

将实际的创建命令放在存储过程中。

不要只是将文本框中的文本粘贴到字符串中并运行它。

编辑:好的,所以事实证明 CREATE 需要一个常量表达式,所以你不能参数化命令。

但是,如果您必须在代码中执行此操作,您至少应该在将输入连接成字符串之前验证输入。在这种情况下,您不应允许任何表名包含除 a - z、A - Z 之外的任何内容。

于 2013-02-26T15:09:34.440 回答