当查询未参数化时,如何使用 OdbcCommand 防止 SQL 注入?

发布于 2025-01-07 19:14:06 字数 343 浏览 5 评论 0原文

我正在编写一个通用的 sqldump 实用程序,它采用 DSN 和表名并将内容转储到文件中。这是一个内部应用程序,因此 SQL 注入并不是一个严重的威胁,但我不想担心它。问题是,查询的变量部分实际上是表名,因此查询将如下所示:

select * from [tablename];

...我认为这不会与 OdbcCommand 的参数化查询支持很好地配合。我还尝试尽可能普遍地支持所有类型的 DSN,无论 DSN 另一端的驱动程序如何。

是否有某种通用方法可以清理我的 tablename 输入,以防止使用 OdbcCommand 对象进行所有 SQL 注入?

I am writing a generic sqldump utility that takes a DSN and a table name and dumps the contents to a file. It's an internal app so SQL Injection is not a serious threat, but I don't want to have to worry about it. The thing is, the variable part of the query is actually the tablename, so the query is going to look like:

select * from [tablename];

...which I don't imagine will work well with the OdbcCommand's parameterized query support. I am also trying to support all types of DSN's as generically as I can, regardless of the driver on the other side of the DSN.

Is there some universal way to sanitize my tablename input to protect against all SQL Injection using the OdbcCommand object?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

踏月而来 2025-01-14 19:14:06

我会根据您知道的表列表检查用户输入,使用大致类似于发布的代码 此处 检索表列表(为后代提供的链接中的代码):

class Program
{
  static void Main(string[] args)
  {
  string connectionString = GetConnectionString();
  using (SqlConnection connection = new SqlConnection(connectionString))
  {
   // Connect to the database then retrieve the schema information.
   connection.Open();
   DataTable table = connection.GetSchema("Tables");

   // Display the contents of the table.
   DisplayData(table);
   Console.WriteLine("Press any key to continue.");
   Console.ReadKey();
   }
 }

也就是说,我同意上面的@KeithS。这可能是一个坏主意。

I'd check the user input against the list of tables you know are there, using code roughly like what's posted here to retrieve the table list (code from the link included for posterity):

class Program
{
  static void Main(string[] args)
  {
  string connectionString = GetConnectionString();
  using (SqlConnection connection = new SqlConnection(connectionString))
  {
   // Connect to the database then retrieve the schema information.
   connection.Open();
   DataTable table = connection.GetSchema("Tables");

   // Display the contents of the table.
   DisplayData(table);
   Console.WriteLine("Press any key to continue.");
   Console.ReadKey();
   }
 }

That said, I agree with @KeithS above. This is probably a Bad Idea.

无敌元气妹 2025-01-14 19:14:06

SQL Server 的 [] 带引号的标识符中唯一的特殊字符是 ],并且可以通过传递 ]] 对其进行转义。因此, "select * from [" + tableName.Replace("]", "]]") + "];" 应该是安全的。然而,其他系统可能使用其他转义机制,因此如果您想连接到不同类型的数据库,这不是完整的解决方案。

或者,考虑每个字符,并查看它是否是您希望支持的表名称的有效字符。如果你说表名只包含字母、数字和/或空格,那么 SQL 注入是不可能的,因为你永远无法取消引用 [quoted table name]

The only special character in a [] quoted identifier for SQL Server is ], and it can be escaped by passing ]]. So for that, "select * from [" + tableName.Replace("]", "]]") + "];" should be safe. Other systems, however, may use other escape mechanisms, so this is not a full solution if you want to connect to a different type of database.

Alternatively, consider each character, and see if it is a valid character for table names you wish to support. If you say table names only contain letters, digits, and/or whitespace, then SQL injection is not possible, because you'll never be able to unquote the [quoted table name].

漫漫岁月 2025-01-14 19:14:06

您可以首先查询 information_schema 来查明该表是否存在:

select * 
from information_schema.tables 
where table_schema = @your_database_name and table_name = @table_name

此查询可以参数化,并且不容易受到 SQL 注入。

接下来,您可以发出 select * from @table_name 查询。

You could first query the information_schema to find out if the table exists:

select * 
from information_schema.tables 
where table_schema = @your_database_name and table_name = @table_name

This query can be parameterized and is NOT prone to SQL injections.

Following that, you can issue your select * from @table_name query.

丑丑阿 2025-01-14 19:14:06

如果表名包含在 [ ] 中,则不允许表名包含 "]"] 可能被恶意者用来终止 sql 命令并引入危险代码。

如果您像这样构造 sql

string sql = "SELECT * FROM [" + tablename + "]"; 

,并且 tablename 定义如下,则

string tablename = "tablename]; DELETE FROM [tablename";

生成的 sql 变为:

SELECT * FROM [tablename]; DELETE FROM [tablename]; 

但是,只有当表名称包含 ] 时,这才是可能的。


注意:

如果您要像这样替换字符串值,那么用两个单引号替换一个单引号也可以保证安全。

string sql = "SELECT * FROM tbl WHERE Name = '" + input.Replace("'","''") + "'";

If the table name is enclosed in [ ] then just do not allow table names to contain "]". ] could be used by malicious people to terminated the sql command and to introduce dangerous code.

If you are constructing the sql like this

string sql = "SELECT * FROM [" + tablename + "]"; 

and the tablename is defined like this

string tablename = "tablename]; DELETE FROM [tablename";

The resulting sql becomes

SELECT * FROM [tablename]; DELETE FROM [tablename]; 

However, this is only possible if the table name contains a ].


Note:

If you are replacing string values like this, then replacing a single quote by two single quotes makes it safe too.

string sql = "SELECT * FROM tbl WHERE Name = '" + input.Replace("'","''") + "'";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文