Что действительно происходит в попытке {возвращают x;} наконец {x = пустой указатель;} оператор?

Как вы можете видеть, люди предлагают вам максимально использовать подготовленные заявления. Это не так, но когда ваш запрос выполняется всего один раз за процесс, будет небольшое снижение производительности.

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

Мой подход:

  • Если вы ожидаете, что ввод будет целым, убедитесь, что он действительно целое число. В языке с переменным типом, таком как PHP, этот очень важен. Вы можете использовать, к примеру, это очень простое, но мощное решение: sprintf("SELECT 1,2,3 FROM table WHERE 4 = %u", $input);
  • Если вы ожидаете чего-то еще от целого шестнадцатеричного значения. Если вы отбросите его, вы полностью избежите ввода. В C / C ++ есть функция, называемая mysql_hex_string() , в PHP вы можете использовать bin2hex() . Не беспокойтесь о том, что экранированная строка будет иметь размер в 2 раза по сравнению с исходной длиной, потому что даже если вы используете mysql_real_escape_string, PHP должен выделять одну и ту же емкость ((2*input_length)+1), что то же самое.
  • hex метод часто используется при передаче двоичных данных, но я не вижу причин, почему бы не использовать его во всех данных для предотвращения атак SQL-инъекций. Обратите внимание, что вам необходимо предварительно добавить данные с помощью 0x или использовать функцию MySQL UNHEX.

Так, например, запрос:

SELECT password FROM users WHERE name = 'root'

Будет:

SELECT password FROM users WHERE name = 0x726f6f74

или

SELECT password FROM users WHERE name = UNHEX('726f6f74')

Hex - идеальный выход.

Разница между функцией UNHEX и префиксом 0x

В комментариях было некоторое обсуждение, поэтому я, наконец, хочу дать понять. Эти два подхода очень похожи, но в некоторых отношениях они немного различаются:

Префикс ** 0x ** может использоваться только для столбцов данных, таких как char, varchar, text, block, binary, и т. д. Кроме того, его использование немного сложно, если вы собираетесь вставить пустую строку. Вам придется полностью заменить его на '', или вы получите сообщение об ошибке.

UNHEX () работает в любом столбце; вам не нужно беспокоиться о пустой строке.


Hex-методы часто используются в качестве атак

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

Например, если вы просто делаете что-то вроде этого:

"SELECT title FROM article WHERE id = " . mysql_real_escape_string($_GET["id"])

атака может очень легко ввести вас . Рассмотрим следующий введенный код, возвращенный из вашего скрипта:

SELECT ... WHERE id = -1 union all select table_name from information_schema.tables

и теперь просто извлеките структуру таблицы:

SELECT ... WHERE id = -1 union all select column_name from information_schema.column где table_name = 0x61727469636c65

И тогда просто выберите нужные данные. Разве это не круто?

Но если кодер инъекционного сайта будет шестнадцатеричным, инъекция не будет возможна, потому что запрос будет выглядеть следующим образом: SELECT ... WHERE id = UNHEX('2d312075...3635')

251
задан John Saunders 22 January 2014 в 23:54
поделиться

4 ответа

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

т.е. подобный:

int tmp;
try {
  tmp = ...
} finally {
  ...
}
return tmp;

например (использующий отражатель):

static int Test() {
    try {
        return SomeNumber();
    } finally {
        Foo();
    }
}

компиляции к:

.method private hidebysig static int32 Test() cil managed
{
    .maxstack 1
    .locals init (
        [0] int32 CS$1$0000)
    L_0000: call int32 Program::SomeNumber()
    L_0005: stloc.0 
    L_0006: leave.s L_000e
    L_0008: call void Program::Foo()
    L_000d: endfinally 
    L_000e: ldloc.0 
    L_000f: ret 
    .try L_0000 to L_0008 finally handler L_0008 to L_000e
}

Это в основном объявляет локальную переменную (CS$1$0000), помещает значение в переменную (в обработанном блоке), затем после выхода из блока загружает переменную, затем возвращает его. Отражатель представляет это как:

private static int Test()
{
    int CS$1$0000;
    try
    {
        CS$1$0000 = SomeNumber();
    }
    finally
    {
        Foo();
    }
    return CS$1$0000;
}
230
ответ дан Marc Gravell 23 November 2019 в 02:54
поделиться

Наконец оператор выполняется, но возвращаемое значение не затронуто. Порядок выполнения:

  1. Код перед оператором возврата выполнен
  2. Выражение в ответ, оператор оценен
  3. наконец, блок выполняется
  4. , Результат, оцененный на шаге 2, возвращается

, Вот короткая программа для демонстрации:

using System;

class Test
{
    static string x;

    static void Main()
    {
        Console.WriteLine(Method());
        Console.WriteLine(x);
    }

    static string Method()
    {
        try
        {
            x = "try";
            return x;
        }
        finally
        {
            x = "finally";
        }
    }
}

Это печатает "попытку" (потому что это - то, что возвращается), и затем "наконец", потому что это - новое значение x.

, Конечно, если мы возвратим ссылку на изменяемый объект (например, StringBuilder) тогда какие-либо изменения, внесенные в объект в наконец, то блок будет видим по возврату - это не влияло на само возвращаемое значение (который является просто ссылкой).

349
ответ дан Hamid Pourjam 23 November 2019 в 02:54
поделиться

Наконец пункт выполняется после оператора возврата, но перед фактическим возвратом из функции. Это имеет мало общего с потокобезопасностью, я думаю. Это не взлом - наконец, как гарантируют, всегда выполнит, неважно, что Вы делаете в своем блоке попытки или своем блоке выгоды.

19
ответ дан Otávio Décio 23 November 2019 в 02:54
поделиться

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

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

4
ответ дан casperOne 23 November 2019 в 02:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: