【问题标题】:WPF/SQL: Replacing values with parameters?WPF/SQL:用参数替换值?
【发布时间】:2018-10-23 12:40:31
【问题描述】:

我是 C# 新手,我编写了以下代码。阅读完文档后,我意识到我的代码可能容易受到 SQL 注入的影响,因为我没有为我的值使用参数(据我了解,您可以通过 search.Text 注入不需要的查询)。我什至应该担心它,因为我基本上将我的值锁定在 "" 引号内?

我在这里找到了一些方向,但我无法让它工作: How to use string variable in sql statement

public void InvokeDataGridAddress()
{
    switch (ComboBoxSelection.Text)
    {
        case "NASLOV":
            comboBoxValue = "SELECT * FROM [cbu_naslovi] WHERE [ADDRESS] LIKE '%" + search.Text + "%' COLLATE Latin1_general_CI_AI";
            break;
        case "LASTNIK":
            comboBoxValue = "SELECT [cbu_naslovi].* FROM [cbu_deli], [cbu_naslovi] WHERE [cbu_deli].LASTNIK LIKE '%" + search.Text + "%' COLLATE Latin1_general_CI_AI AND [cbu_deli].IDX = [cbu_naslovi].ID";
            break;
        case "OBJEKT":
            comboBoxValue = "SELECT * FROM [cbu_naslovi] WHERE [SO] LIKE '%" + search.Text + "%'";
            break;
        case "PARCELA":
            comboBoxValue = "SELECT * FROM [cbu_naslovi] WHERE [P1] LIKE '%" + search.Text + "%' OR [P2] LIKE '%" + search.Text + "%' OR [P3] LIKE '%" + search.Text + "%' OR [P4] LIKE '%" + search.Text + "%' OR [P5] LIKE '%" + search.Text + "%' OR [P6] LIKE '%" + search.Text + "%' OR [P7] LIKE '%" + search.Text + "%' OR [P8] LIKE '%" + search.Text + "%' OR [P9] LIKE '%" + search.Text + "%' OR [P10] LIKE '%" + search.Text + "%' OR [P11] LIKE '%" + search.Text + "%' OR [P12] LIKE '%" + search.Text + "%' OR [P13] LIKE '%" + search.Text + "%' OR [P14] LIKE '%" + search.Text + "%' OR [P15] LIKE '%" + search.Text + "%' OR [P16] LIKE '%" + search.Text + "%' OR [P17] LIKE '%" + search.Text + "%'";
            break;
    }
    comboBoxValue = comboBoxValue + " ORDER BY [ULICA] ASC, [OBMOCJE] ASC, LEN ([HS]) ASC, [HS] ASC, [HID] ASC";
    SqlCommand cmd = new SqlCommand
    {
        CommandText = comboBoxValue,
        Connection = con
    };
    Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    dtAddress.Clear();
    da.Fill(dtAddress);
    dg_address.ItemsSource = dtAddress.DefaultView;
    Mouse.OverrideCursor = System.Windows.Input.Cursors.Arrow;
}

编辑:Olivier Belanger 和 MindSwipe 提供了可行的解决方案。我还留下了有关如何使 LIKE 使用 % 参数的参考:Use of SqlParameter in SQL LIKE clause not working

public void InvokeDataGridAddress()
{
    switch (ComboBoxSelection.Text)
    {
        case "NASLOV":
            comboBoxValue = "SELECT * FROM [cbu_naslovi] WHERE [ADDRESS] LIKE @SearchText COLLATE Latin1_general_CI_AI";
            break;
        case "LASTNIK":
            comboBoxValue = "SELECT [cbu_naslovi].* FROM [cbu_deli], [cbu_naslovi] WHERE [cbu_deli].LASTNIK LIKE @SearchText COLLATE Latin1_general_CI_AI AND [cbu_deli].IDX = [cbu_naslovi].ID";
            break;
        case "OBJEKT":
            comboBoxValue = "SELECT * FROM [cbu_naslovi] WHERE [SO] LIKE @SearchText";
            break;
        case "PARCELA":
            comboBoxValue = "SELECT * FROM [cbu_naslovi] WHERE [P1] LIKE @SearchText OR [P2] LIKE @SearchText OR [P3] LIKE @SearchText OR [P4] LIKE @SearchText OR [P5] LIKE @SearchText OR [P6] LIKE @SearchText OR [P7] LIKE @SearchText OR [P8] LIKE @SearchText OR [P9] LIKE @SearchText OR [P10] LIKE @SearchText OR [P11] LIKE @SearchText OR [P12] LIKE @SearchText OR [P13] LIKE @SearchText OR [P14] LIKE @SearchText OR [P15] LIKE @SearchText OR [P16] LIKE @SearchText OR [P17] LIKE @SearchText";
            break;
    }
    comboBoxValue = comboBoxValue + " ORDER BY [ULICA] ASC, [OBMOCJE] ASC, LEN ([HS]) ASC, [HS] ASC, [HID] ASC";
    SqlCommand cmd = new SqlCommand
    {
        CommandText = comboBoxValue,
        Connection = con
    };
    cmd.Parameters.AddWithValue("@SearchText", '%' + search.Text + '%');
    Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait;
    SqlDataAdapter da = new SqlDataAdapter(cmd);
    dtAddress.Clear();
    da.Fill(dtAddress);
    dg_address.ItemsSource = dtAddress.DefaultView;
    Mouse.OverrideCursor = System.Windows.Input.Cursors.Arrow;
}

【问题讨论】:

  • 请详细说明,如上所述,我是 C# 和一般编程新手。
  • @Fildor 我使用了不同的代码结构,没有 cmd。附件。我尝试在 CommandText 下添加Parameter.Add("@Search", search.Text) 并将search.Text 替换为(@)Search,但无法正常工作。这对于有经验的人来说可能是合乎逻辑的,但对于新手来说却不是。
  • 是的,您绝对应该担心这一点。这很容易预防,否则对任何人来说都是一个非常开放的漏洞。我不会说从不经常,但从不在 SQL 语句中使用不干净的值。使用参数(或者在许多情况下更好:Entity Framework 可以为您处理大部分 SQL 管道)
  • @Adephx 您有什么特别不清楚的地方?这个答案可以以任何方式改进,所以它会更有用吗?

标签: c# sql .net wpf


【解决方案1】:

简短的回答,是的,你总是需要担心 SQL 注入,你不会相信一些黑客在这些方面有多么有创意。
尽管我在 C# 方面非常有经验,但我从未在 C# 中使用过直接 SQL,但我一直将 EF 与 LINQ 一起用于数据库
无论如何,这里是:

using (var con = new SqlClient.SqlConnection(conectionString))
using (var cmd = SqlClient.SqlCommand())
{
    con.Open();
    cmd.Connection = con;
    cmd.CommandType = CommandType.Text;
    cmd.CommandText = "SELECT * FROM [cbu_naslovi] WHERE [ADDRESS] LIKE '%@Title%' COLLATE Latin1_general_CI_AI";
    cmd.Parameters.Add("@Title", search.Text);
}

一些解释:
using: using 关键字非常简单。基本上你放在括号之间的任何东西(例如Class c = new Class();)都需要实现IDisposable,这个变量在花括号之后被释放
Syntatic Candy:通常需要跟进using()通过花括号 { },除非它是单个语句或另一个 using 语句
Sql Stuff: con.Open 打开我们到数据库的连接,我们将其设置为我们的命令将与cmd.Connection = con 一起使用。
现在我们需要说明它是什么类型的命令。通过执行cmd.CommandType = CommandType.Text,我们告诉命令它是一个 SQL 查询。
现在我们需要实际定义我们的查询,但不是将字符串与+ 连接,而是使用@987654329 @ 作为占位符。
最后我们通过执行 cmd.Parameters.Add("@SomeName", value)@SomeName 替换为实际值,其中 @SomeName 可以是任何值,但它必须与我们想要的占位符相同在 SQL 查询中替换
这是我们真正保护自己免受 SQL 注入攻击的地方,因为 cmd.Parameters.Add() 可以完成我们需要的一切,否则我们需要手动完成

希望这对您有所帮助,不会再让您感到困惑

注意:如果您对实体框架 (EF) 或 LINQ 感兴趣,这里是一个很好的来源:EF Database First tutorial

【讨论】:

  • 您能否详细说明具有参数 '%@Text%' 和直接包含值 - '%" + search.Text + "%' 之间的区别?我一直认为单引号基本上将值锁定为文本,因此不可能用“BILLY AND TRUNCATE TABLE TABLE_NAME”之类的内容填充搜索TextBox?这种类型的注入是如何工作的?
  • 使用'%" + search.Text + "%' 方法,攻击者只需将' 放在他的字符串前面即可完成引号
【解决方案2】:

您很容易受到 SQL 注入的攻击。

首先,最好在选择中列举你想要的内容,如下所示:

SELECT Name, Address, City FROM [YourTable] 而不是SELECT * FROM [YourTable]

其次,您应该像这样在查询中插入参数:

SELECT Name, Address, City FROM [YourTable] WHERE Name = @Name

在你的命令下:

cmd.Parameters.AddWithValue("@Name", YourValue)

希望对你有帮助,

这里有一些链接: What are good ways to prevent SQL injection? https://www.codeproject.com/Tips/706692/Preventing-SQL-Injection-Attacks

【讨论】:

  • 是否应该枚举即使我想选择每一列,因为我选择了大约 12 列?
  • 是的。 select * 几乎总是一个坏主意。 @Adephx
  • 选择命名字段而不是“Select *”并不能防止 SQL 注入。
  • @Peregrine “不要选择 * - 规则”不是为了防止 SQL 注入。这还有其他含义。只需添加一列,您的所有陈述都可能被破坏......(仅举一个例子)。
  • 我从来没有说过“选择 *”是一个好习惯,但是这个问题和这个答案是专门关于 SQL 注入的
猜你喜欢
  • 2016-12-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
  • 2013-11-17
  • 2010-12-10
  • 1970-01-01
  • 2015-08-27
相关资源
最近更新 更多