C # и MySQL .NET Connector - Любой способ предотвратить атаки SQL-инъекций в общем классе? - PullRequest
9 голосов
/ 05 мая 2010

Моя идея состоит в том, чтобы создать некоторые общие классы для вставки / обновления / выбора через приложение C # (3.5) Winforms, взаимодействующее с базой данных MySQL через MySQL .NET Connector 6.2.2.

Например:

public void Insert(string strSQL)
{
   if (this.OpenConnection() == true)
   {
       MySqlCommand cmd = new MySqlCommand(strSQL, connection);
       cmd.ExecuteNonQuery();
       this.CloseConnection();
   }
}

Затем из любой точки программы я могу выполнить запрос с / без ввода пользователя, просто передав строку запроса SQL.

Ознакомление с SO начинает давать мне понять, что это может привести к атакам с использованием SQL-инъекций (для любых значений, вводимых пользователем). Есть ли какой-либо способ очистки введенной strSQL или мне нужно пойти и создать отдельные параметризованные запросы в каждом методе, который должен выполнять функцию базы данных?

Update1:

Мое окончательное решение выглядит примерно так:

public void Insert(string strSQL,string[,] parameterValue)
{
   if (this.OpenConnection() == true)
   {
       MySqlCommand cmd = new MySqlCommand(strSQL, connection);

       for(int i =0;i< (parameterValue.Length / 2);i++)
       {                        
       cmd.Parameters.AddWithValue(parameterValue[i,0],parameterValue[i,1]);          
       }

       cmd.ExecuteNonQuery();
       this.CloseConnection();
   }}

Ответы [ 8 ]

11 голосов
/ 05 мая 2010

Вы должны определенно использовать параметризованные запросы, чтобы обезопасить себя.

Вам не нужно каждый раз создавать вручную параметризованные запросы. Вы можете изменить предоставленный вами универсальный метод, чтобы принимать коллекцию MySqlParameters:

public void Insert(string strSQL, List<MySqlParameter> params)
{
    if(this.OpenConnection() == true)
    {
        MySqlCommand cmd = new MySqlCommand(strSQL, connection)
        foreach(MySqlParameter param in params)
            cmd.Parameters.Add(param);

        cmd.ExecuteNonQuery();
        this.CloseConnection();
    }
}

Я должен также упомянуть, что вы должны быть ОЧЕНЬ осторожны при очистке ваших соединений после того, как вы закончили их использовать (обычно это обрабатывается в блоке using, но я не вижу такого уровня детализации в вашем примере кода) .

11 голосов
/ 05 мая 2010

Параметризация очень проста. Гораздо проще, чем очистка SQL-запросов, и менее грязно или подвержено ошибкам, чем ручное экранирование.

Слегка отредактированная копия / вставка из этой страницы учебника , потому что мне лень:

// User input here
Console.WriteLine("Enter a continent e.g. 'North America', 'Europe': ");
string userInput = Console.ReadLine();

string sql = "SELECT Name, HeadOfState FROM Country WHERE Continent=@Continent";
MySqlCommand cmd = new MySqlCommand(sql, conn);
cmd.Parameters.AddWithValue("@Continent", userInput);

using (MySqlDataReader dr = cmd.ExecuteReader())
{
    // etc.
}

Это было не так сложно, правда? :)

1 голос
/ 05 мая 2010

ДА, вам нужно создавать параметризованные запросы, все остальное будет представлять риск внедрения SQL

1 голос
/ 05 мая 2010

Я бы предложил использовать объекты IDataParameter для параметризации ваших запросов.

1 голос
/ 05 мая 2010

На самом деле вы не можете этого сделать - вам нужно написать синтаксический анализатор SQL, который, по меньшей мере, нетривиален и подвержен ошибкам.

Укуси пулю и параметризовай свои запросы.

1 голос
/ 05 мая 2010

, если вы используете MySqlParameter и не генерируете запросы простых строк, вы в безопасности.

1 голос
/ 05 мая 2010

Я ожидаю, что будет довольно сложно вычистить необработанный текст, который будет использоваться для SQL. Если это вообще возможно, я бы попытался использовать параметризованные операции.

Единственное исключение может быть, если вы не открываете функцию публично и никогда не передаете строку, созданную из необработанного пользовательского ввода.

1 голос
/ 05 мая 2010

Невозможно обнаружить внедрение SQL по факту (другими словами, после того как вы построили динамическую строку запроса, невозможно отличить, что такое «настоящий» SQL от любого введенного SQL).

Если вы намерены разрешить пользователям выполнять произвольный SQL, то, похоже, вы не будете слишком беспокоиться о внедрении SQL (поскольку это цель внедрения SQL).

...