Добрый вечер, друзья
Решил написать новичкамв этом плане о том, как защитить себя, поправочка, свои скрипты
от
SQL-Injection и
XSS(Cross Site Scripting)
Писать буду опираясь на свой собственный опыт
Ничего из сторонних сайтов брать не буду
И так, приступим
Начнем пожалуй из чисел, особенно которые передаются через метод GET
Пример этому служит постраничная навигация
http://ololo.ru/index.php?page=1
Стоит помнить, что злоумышленник, может передать вместо числа, строку, что может запороть скрипт
Чтобы избежать этого, данные нужно проверять функцией
is_numeric()
Пример:
<?php
if (is_numeric($_GET[\'page\'])==true){//Если значение true
//Код
}
?>
Функция возвращает true если данные являются числом, НО и это ещё не всё
Вот проверили мы, возвратило true, но что, если это дробное число (1.5 к примеру)
Это дробное число может запороть нам весь скрипт
Для понятности приведу пример кода постраничной навигации которой пользуюсь я:
<?php
$cop=10;//Количество обьектов на страницу
$ca=mysql_result(mysql_query(\"SELECT COUNT(*) FROM `chat`\"
,0);//Считаем сколько записей в базе
$cp=ceil($ca/$cop);//Узнаем сколько страниц, делим общее количество на количество на страницу, и закруглим это к большей части, именно к большей, и чтобы была вторая страница(на ней остальные 6 записей, а на первой 10), т.к может быть 16 записей
if(isset($_GET[\'page\']) && is_numeric($_GET[\'page\'])){//Если присутствует параметр page и это число
$page = $_GET[\'page\'];//Присваиваем значение переменной $page( для удобства )
if($page>$cp) $page=$cp; // Если пользователь указал параметр 3, а у нас всего 2 страницы присваиваем ему число всех страниц, то есть последнюю страницу
if($_GET[\'page\']<1)$page=1;//Если переданное число меньше единицы, присваеваем переменной значение 1
}else{//Иначе если параметр page отсутствует
$page=1;
}
$start=$page*$cop-$cop;//Узнаем начало вывода записей
$q=mysql_query(\"SELECT * FROM `chat` ORDER BY `id` DESC LIMIT $start,$cop\"
;//Выбрать $cop записей начиная из $start
while ($result=mysql_fetch_assoc($q)){//Создаем цикл
echo $result[\'msg\'];//Выводим запись
}
//Ну и навигация
echo \'
Страницы
\';
if($page-1>0){
echo \'<a href=\"?page=\'.($page-1).\'\"><</a> \';
}
if($page-1>0){
echo \'<a href=\"?page=\'.($page-1).\'\">\'.($page-1).\'</a> \';
}
echo \'<b>\'.$page.\'</b>\';
if($page+1<=$cp){
echo \' <a href=\"?page=\'.($page+1).\'\">\'.($page+1).\'</a>\';
}
if($page+1<=$cp){
echo \' <a href=\"?page=\'.($page+1).\'\">></a>\';
}
?>
Надеюсь вы поняли
Чтобы избежать дробных чисел, нужно выделять из него целую часть
Для этого используем функцию
intval() Пример:
<?php
$number=1.6;
$number=intval($number);//Переменной присвоится значение 1
?>
И вообще, функцией
intval() я рекоменду фильтровать все входящие ЦЕЛЫЕ числа
Впринцыпе всё о числах, числа переданные с помощью POST фильтруйте так же
Теперь о строках
Строки - основной метод взлома, как через XSS так и через SQL-Injection
В основном используется SQL-Injection, так как это дает доступ к базе данных, в следствии, злоумышленник может сделать с вашей базой данных всё, что ему захочется - от простого изменения значения полей, вплоть до удаления таблиц
И так пример
Есть код поиска по имени:
<?php
$name=$_GET[\'name\'];
mysql_query(\"SELECT * FROM `table` WHERE `name`=$name\"
;
?>
делаем запрос
http://ololo.ru/page.php?name=Bohdan
Всё нормально, теперь сделаем так:
http://ololo.ru/page.php?name=Bohdan\'
Скрипт поймет это так:
SELECT * FROM `table` WHERE `name`=Bohdan\'
Выдаст ошибку, всё дело в том, что параметр можно передавать в запрос в таком виде: `param`=$variable или в таком `param`=\'$variable\'
Всё дело в том что если если написать так: `name`=Bohdan\' скрипт не найдет первой кавычки, и посчитает это за синтаксическую ошибку, естественно, выведет нам её на экран
Так злоумышленник может узнать есть ли в скрипте SQL-Injection
Ну а дальше уже пусть думает ваша фантазия, что он может зделать используя команду UNION для обьединения нескольких запросов...
Конечно, можно проверять входящую строку на наличие запрещенных символов к примеру вот так:
<?php
if (preg_match(\"/[^(\\w)|(\\x7F-\\xFF-)|(\\s)]/\",$_GET[\'name\'])){//Нужно знать регулярные выражения, чтобы пользоваться этой функцией
echo \'Используются запрещенные символы\';
}
?>
Но это не дает 100% защиту
И так как же защититя от этого
Для этого в языке программирования ПЫХ-ПЫХ
предусмотрена функция
mysql_real_escape_string()
Она экранирует специальные символы в строке перед использованием её в запросе
Вот как это выглядит:
<?php
$name=mysql_real_escape_string($_GET[\'name\']);//Экранируем спец-символы
mysql_query(\"SELECT * FROM `table` WHERE `name`=$name\"
;
?>
Можно считать, что мы защищены от иньекций
Возможно есть и способы обхода этой функции, но я о таких не слышал
Считайте друзья, что мы защитились от иньекций, но это еще не всё
Давайте теперь поговорим о выводе данных из таблицы
Тут уже в действие вступает ХSS
Начнем с примера:
<?php
$name=mysql_real_escape_string($_GET[\'name\']);
mysql_query(\"INSERT INTO `table` (`id`,`name`)VALUES(1,$name)\"
;//Заносим данные в таблицу
$name=mysql_result(mysql_query(\"SELECT `name` FROM `table` WHERE `id`=1\"
,0);//Берем значение из поля name в записи с id=1
echo $name;
?>
Ввели мы например в адресной строке слово Vasya
Ну и хорошо, занесли в базу имя Vasya
Но что, если вместо Vasya пользователь ввёдет такую строку: <script language=\"javascript\">alert(\'Привет! Я есть XSS\');</script>
То вместо ожидаемого нами текста: Vasya на странице, он увидит уже джаваскрипт(маленькое окошко, которое выскочило по средине страницы с текстом: Привет! Я есть XSS)
Это, друзья мои, и есть XSS
Но всё же! Есть этому решение
И это функция
htmlspecialchars() - она экранирует всё теги HTML(можно указать которые не экранировать, подробнее читайте в справке по функциям)
Ею мы будем фильтровать всё данные которые будут выводится пользователю на экран
Теперь если мы сделаем вот так:
<?php
$name=mysql_real_escape_string($_GET[\'name\']);
mysql_query(\"INSERT INTO `table` (`id`,`name`)VALUES(1,$name)\"
;//Заносим данные в таблицу
$name=mysql_result(mysql_query(\"SELECT `name` FROM `table` WHERE `id`=1\"
,0);//Берем значение из поля name в записи с id=1
echo htmlspecialchars($name);
?>
То мы увидим на экране текст: <script language=\"javascript\">alert(\'Привет! Я есть XSS\');</script>
А не работу XSS...
Всё! Да, вот так просто
Возможно гдето есть мои недочеты, в плане изложения материала, но я старался
Не забывайте эти 4 функции and all will be beautiful
Внимательно просматривайте свои скрипты, и не оставляйте этим гадам никаких шансов
Спасибо за внимание, ваш
MrDonald