Добрый вечер, друзья
Решил написать новичкамв этом плане о том, как защитить себя, поправочка, свои скрипты от 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
Статья будет не очень понятна новичкам,много лишнего.Зачем делать проверки,если можно сразу фильтровать?
пусть изучают функции, полезно им
Лучше всё фильтровать при записи чем при выводе.
как ты отфильтруешь хтмл чтобы он не выводился при следующем его выводе через эчо?
Но урок же не про функции,тем более preg_match это не функция.