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

Форум MySQL

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

 

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

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

тема: Проверка на безопасность данных
 
 автор: tima2010   (19.12.2011 в 14:52)   письмо автору
 
 

Привет! Терзает вопрос по счет безопасности, как вы считаете достаточно ли такого кода чтобы он был безопасен при записи в MySql и построении запроса?


<?php

$email 
stripslashes($_POST['email']);
$email htmlspecialchars($email);
if (
$email == '') { 
    
$error .= 'E-Mail не может быть пустым<br>'
}
elseif (!
preg_match("/^[-0-9a-z_\.]+@[-0-9a-z_^\.]+\.[-0-9a-z_]{2,6}$/i"$email)) { 
    
$error .= 'Некорректно указан E-Mail.<br>'
}

$name stripslashes($_POST['name']);
$name htmlspecialchars($name);
if (
$name == '') {
    
$error .= 'Имя не может быть пустым<br>';
}
elseif (
preg_match ("/[^а-яA-Яa-zA-Z0-9\s]/"$name)) {
    
$error .= "Недопустимые символы в имени<br>";
}

$text htmlspecialchars($_POST['text']);

if (!
$error) {
    
$query "INSERT INTO mytable (email, name, text) VALUES ('$email', '$name', '$text')");
}
?>

  Ответить  
 
 автор: cheops   (19.12.2011 в 15:01)   письмо автору
 
   для: tima2010   (19.12.2011 в 14:52)
 

Вообще говоря нет, не безопасно. Если не сложно объясните, для чего предназначено это регулярное выражение?
elseif (preg_match ("/[^а-яA-Яa-zA-Z0-9\s]/", $name)) { 
    $error .= "Недопустимые символы в имени<br>"; 
}

PS Основная притензия в том, что у вас отсутствует экранирование... Манипулируя $_POST['name'] и кавычками я могу в $text вставить что угодно, вплоть до паролей к системе администрирования сайта, если нащупаю (или буду знать заранее), где они у вас хранятся. Можно будет вывести туда стркутуру таблиц, посмотреть какие в них поля, нет ли где-то что-то напоминающего поля для хранения пароля... в общем код считайте взломан.

  Ответить  
 
 автор: tima2010   (19.12.2011 в 15:08)   письмо автору
 
   для: cheops   (19.12.2011 в 15:01)
 

РВ для имени пользователя, имя может состоять только из русских букв английских букв пробела и цифр (вроде как работает корректно)

stripslashes - поставил в связи с тем, что данные почему то записываются с экранированными кавычками... На сколько я знаю они используются только для запроса если активно get_magic_quotes_gpc то кавычки экранируются но отбрасываются при записи в базу... а у меня почему то нет :(

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

  Ответить  
 
 автор: cheops   (19.12.2011 в 15:10)   письмо автору
 
   для: tima2010   (19.12.2011 в 15:08)
 

А у вас во-первых проверка допускает все, лишь бы первым не было указан пробел или буква алфавита, нет символа окончания строки $, нет отрицания как в email. Т.е. участок следует переписывать так
$name = stripslashes($_POST['name']); 
$name = htmlspecialchars($name); 
if ($name == '') { 
    $error .= 'Имя не может быть пустым<br>'; 

elseif (!preg_match ("/[^а-яA-Яa-zA-Z0-9\s]+$/", $name)) { 
    $error .= "Недопустимые символы в имени<br>"; 
}

  Ответить  
 
 автор: tima2010   (19.12.2011 в 15:18)   письмо автору
 
   для: cheops   (19.12.2011 в 15:10)
 

Простите запутался,
если ставить !preg_match то ошибка будет при существовании этих символов...
если я ставлю без условия ! то тогда наоборот проверка работает нормально...

  Ответить  
 
 автор: cheops   (19.12.2011 в 16:19)   письмо автору
 
   для: tima2010   (19.12.2011 в 15:18)
 

Наоборот, если все эти символы существуют от начала строки до конца и никаких других нет - это то, что нам нужно, двигаемся вперед. А вот если регулярное выражение возвращает false - значит среди них затесался какой-то символ им не удовлетворяющий, нужно превратить false в true при помощи отрицания, чтобы сообщить об ошибке.

  Ответить  
 
 автор: tima2010   (19.12.2011 в 16:24)   письмо автору
 
   для: cheops   (19.12.2011 в 16:19)
 

Спасибо! А по счет кавычек, так буде лучше и безопаснее?

<?php
if(get_magic_quotes_gpc()==1)
{
$text=stripslashes(trim($_POST["text"]));
}
else
{
$text=trim($_POST["text"]);
}

$text=mysql_real_escape_string($text);
?>

  Ответить  
 
 автор: cheops   (19.12.2011 в 17:26)   письмо автору
 
   для: tima2010   (19.12.2011 в 16:24)
 

Вы знаете, лучше не использовать ==1, просто пишите get_magic_quotes_gpc() - так универсальнее будет. Нет, все что у вас написано, все правильно, это чисто стилистическая правка - короче и более универсально, в том числе и для будущих изменений в языке.

  Ответить  
 
 автор: tima2010   (19.12.2011 в 16:54)   письмо автору
 
   для: cheops   (19.12.2011 в 16:19)
 

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


<?php
function security_Check($str=''$number=''$type='') {

    if(
get_magic_quotes_gpc() == '1') {
        
$str stripslashes(trim($str));
    } else    {
        
$str trim($str);
    }
    
$str mysql_real_escape_string($str);
    
$stt htmlspecialchars($stt);

    if(isset(
$number)) {
        
$strlen strlen($str);
        if (
$strlen $number) {
            
$error .= "Слишком много букв.";
        }
    }
    
    if(!isset(
$str)) {
        
$error .= "Поле не должно быть пустым<br>";
    }
    
    if(
$type == 'text') {
        if(!
preg_match ("/[^а-яA-Яa-zA-Z0-9\s-]+$/"$str) {
            
$error .= "Использовать можно только: Русские буквы, Английские буквы, Цифры, Пробел и Тере.<br>";
        }
    }
    
    if(
$type == 'email') {
        if(!
preg_match ("/^[-0-9a-z_\.]+@[-0-9a-z_^\.]+\.[-0-9a-z_]{2,6}$/i"$str) {
            
$error .= "Неверный E-Mail<br>";
        }
    }
    
    if(
$type == 'number') {
        if(!
preg_match ("/[^0-9-+\s()]+$/"$str) {
            
$error .= "Использовать можно только: Цифры, Пробел, Тере и Скобки.<br>";
        }
    }
    return 
$error;
}
?>

  Ответить  
 
 автор: cheops   (19.12.2011 в 17:30)   письмо автору
 
   для: tima2010   (19.12.2011 в 16:54)
 

Все хорошо.

PS Единственное, что я бы не стал использовать htmlspecialchars() до вставки в базу данных, только при выводе на страницу. Если будете использовать эту функцию до вставки - рано или поздно пожалеете об этом решении. Ну и скажем так, ваш код не будет считать профессиональным. Любой профессионал читая его, будет морщиться и думать примерно так: ну вот человек не был уверен в своих силах в области безопасности и перестраховывался, а мне теперь что с его кодом делать (теперь придется иметь в виду целый дополнительный класс ошибок)?

  Ответить  
 
 автор: Slo_Nik   (20.12.2011 в 12:30)   письмо автору
 
   для: cheops   (19.12.2011 в 17:30)
 

а какой бы вариант решения задачи Вы предложили бы?

  Ответить  
 
 автор: cheops   (20.12.2011 в 14:03)   письмо автору
 
   для: Slo_Nik   (20.12.2011 в 12:30)
 

Близкий к тому, что предложен выше (если требования действительно такие жесткие и есть необходимость использовать регулярные выражения), за минусом функции htmlspecialchars(), которую бы использовал при выводе информации из базы данных. В противном случае при редактировании данных можно получить множество проблем (причем практически неразрешимых).
Такую избыточную конструкцию
    if(get_magic_quotes_gpc() == '1') { 
        $str = stripslashes(trim($str)); 
    } else    { 
        $str = trim($str); 
    } 
    $str = mysql_real_escape_string($str);
обычно не используют, когда режутся слеши и тут же вставляются. В этом теряется преимущество позднего экранирования. Когда слеши режут, то экранирование производят уже не посредственно около SQL-запроса (всех данных без разбора откуда они поступили). Если экранирование переносится к получению внешних данных, то применяют конструкцию вида
if(!get_magic_quotes_gpc()) { 
    $str = mysql_real_escape_string($str);
}

  Ответить  
 
 автор: tima2010   (19.12.2011 в 21:06)   письмо автору
 
   для: cheops   (19.12.2011 в 16:19)
 

cheops:
Наоборот, если все эти символы существуют от начала строки до конца и никаких других нет - 
это то, что нам нужно, двигаемся вперед. А вот если регулярное выражение возвращает false - 
значит среди них затесался какой-то символ им не удовлетворяющий, нужно превратить false в 
true при помощи отрицания, чтобы сообщить об ошибке.


По счет РВ, я все понимаю, но с какого то перепугу происходит следующие...

При таком условии возвращает OK

<?php
$test 
"аАaZ0- Ё@"// присутствует недопустимый символ @
if(!preg_match ("/[^а-яA-Яa-zA-Z0-9\s-]+$/"$test)) { // с !
    
echo "Не соответствует шаблону.";
} else {
    echo 
"ok";
}
?>


При таком условии возвращает Не соответствует шаблону...


<?php
$test 
"аАaZ0- Ё@"// присутствует недопустимый символ @
if(preg_match ("/[^а-яA-Яa-zA-Z0-9\s-]+$/"$test)) { // без !
    
echo "Не соответствует шаблону.";
} else {
    echo 
"ok";
}
?>


Но опираясь на Ваши слова выше должно же быть наоборот? Почему так?

  Ответить  
 
 автор: cheops   (19.12.2011 в 21:12)   письмо автору
 
   для: tima2010   (19.12.2011 в 21:06)
 

>При таком условии возвращает OK
Да, я ошибся положением символа ^ (отладить не было возможности), вместо
[^а-яA-Яa-zA-Z0-9\s-]+$

нужно писать
^[а-яA-Яa-zA-Z0-9\s-]+$

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

Большое спасибо! обезопасился :)

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

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