Могут ли мои пользователи вводить мой динамический sql? - PullRequest
6 голосов
/ 28 августа 2010

Я разработчик настольных систем, пишу для внутренних пользователей, поэтому я не беспокоюсь о злонамеренных хакерах, но я хотел бы знать, есть ли что-нибудь, что они могли бы ввести при обновлении значения, которое будет выполнять sql на сервере.

Бизнес определяет свою схему контента, и у меня есть для них приложение CRUD, которое не нужно менять при изменении их схемы, поскольку детали проверки основаны на таблицах, а обновления - с помощью динамического SQL.Я должен поддерживать одинарные кавычки в их вводе данных, поэтому, когда они вводятся, я удваиваю их перед выполнением SQL на сервере.Из того, что я прочитал, однако, этого не должно быть достаточно, чтобы остановить инъекцию.

Поэтому мой вопрос заключается в том, какой текст они могли бы ввести в текстовое поле произвольной формы, которое могло бы что-то изменить на сервере.вместо того, чтобы быть сохраненным как литеральное значение?

По сути, я строю инструкцию SQL во время выполнения, которая следует шаблону:

обновить поле набора таблиц = значение, где pkField = pkVal

с этим кодом VB.NET:

Friend Function updateVal(ByVal newVal As String) As Integer
    Dim params As Collection
    Dim SQL As String
    Dim ret As Integer

    SQL = _updateSQL(newVal)
    params = New Collection
    params.Add(SQLClientAccess.instance.sqlParam("@SQL", DbType.String, 0, SQL))
    Try
        ret = SQLClientAccess.instance.execSP("usp_execSQL", params)
    Catch ex As Exception
        Throw New Exception(ex.Message)
    End Try
    Return ret
End Function

Private Function _updateSQL(ByVal newVal As String) As String
    Dim SQL As String
    Dim useDelimiter As Boolean = (_formatType = DisplaySet.formatTypes.text)
    Dim position As Integer = InStr(newVal, "'")
    Do Until position = 0
        newVal = Left(newVal, position) + Mid(newVal, position)       ' double embedded single quotes '
        position = InStr(position + 2, newVal, "'")
    Loop
    If _formatType = DisplaySet.formatTypes.memo Then
        SQL = "declare @ptrval binary(16)"
        SQL = SQL & " select @ptrval = textptr(" & _fieldName & ")"
        SQL = SQL & " from " & _updateTableName & _PKWhereClauses
        SQL = SQL & " updatetext " & _updateTableName & "." & _fieldName & " @ptrval 0 null '" & newVal & "'"
    Else
        SQL = "Update " & _updateTableName & " set " & _fieldName & " = "
        If useDelimiter Then
            SQL = SQL & "'"
        End If
        SQL = SQL & newVal
        If useDelimiter Then
            SQL = SQL & "'"
        End If
        SQL = SQL & _PKWhereClauses
    End If
    Return SQL
End Function

при обновлении текстового поля до значения

Redmond ';удалить таблицу OrdersTable -

, которая генерирует:

Update caseFile set notes = 'Redmond''; drop table OrdersTable--' where guardianshipID = '001168-3'

и обновляет значение до введенного ими буквального значения.

Что еще они могли бы ввести,впрыскивать SQL?

Опять же, я не беспокоюсь, что кто-то хочет взломать сервер на своей работе, но хотел бы знать, как, если бы они могли случайно вставить текст откуда-то еще и что-то сломать.

Спасибо.

Ответы [ 6 ]

2 голосов
/ 28 августа 2010

Вы также можете оценить альтернативное решение.Динамическая генерация SQL с параметрами.Как то так:

// snippet just for get the idea
var parameters = new Dictionary<string, object>();
GetParametersFromUI(parameters);


if (parameters.ContainsKey("@id")) {
    whereBuilder.Append(" AND id = @id");
    cmd.Parameters.AddWithValue("@id", parameters["@id"]);
}
...
2 голосов
/ 28 августа 2010

Независимо от того, как вы очищаете вводимые пользователем данные, увеличение поверхности атаки является реальной проблемой того, что вы делаете.Если вы посмотрите на историю SQL-инъекций, то заметите, что со временем появились новые и даже более креативные способы нанести ущерб.В то время как вы, возможно, избегали известного, это всегда скрывается за углом, что делает этот тип кода трудным для производства.Тебе лучше просто использовать другой подход.

1 голос
/ 28 августа 2010

Вы никогда и никогда не захотите построить оператор SQL с использованием пользовательского ввода, который затем будет выполнен напрямую. Как вы обнаружили, это приводит к атакам с использованием SQL-инъекций. Кто-то может просто бросить таблицу в вашей базе данных, как вы описали.

Вы хотите использовать параметризованные запросы, где вы строите строку SQL с использованием заполнителей для значений, а затем передаете значения для этих параметров.

Используя VB, вы сделаете что-то вроде:

'Define our sql query'
Dim sSQL As String = "SELECT FirstName, LastName, Title " & _
                     "FROM Employees " & _
                     "WHERE ((EmployeeID > ? AND HireDate > ?) AND Country = ?)"

'Populate Command Object'
Dim oCmd As New OledbCommand(sSQL, oCnn)

'Add up the parameter, associated it with its value'
oCmd.Parameters.Add("EmployeeID", sEmpId)
oCmd.Parameters.Add("HireDate", sHireDate)
oCmd.Parameters.Add("Country", sCountry)

(пример взят из здесь ) (также не я не программист на VB, так что это может быть неправильный синтаксис, но он понимает суть)

1 голос
/ 28 августа 2010

Единственное безопасное допущение состоит в том, что если вы не используете параметризованные запросы (и здесь не только потому, что объединяете входную строку в свой sql), то вы 'не безопасно.

1 голос
/ 28 августа 2010

Каким бы уродливым не был ваш код для удвоения (: p - попробуйте String.Replace .) Я почти уверен, что сработает.

1 голос
/ 28 августа 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...