Безопасность PHP (strip_tags, htmlentities)

Я работаю в личном проекте и, помимо использования подготовленных заявлений, я хотел бы использовать каждый вход как угрозу. Для этого я сделал простую функцию.

function clean($input){
if (is_array($input)){
    foreach ($input as $key => $val){
        $output[$key] = clean($val);
    }
}else{
    $output = (string) $input;
    if (get_magic_quotes_gpc()){
        $output = stripslashes($output);
    }
    $output = htmlentities($output, ENT_QUOTES, 'UTF-8');

}
return $output;
}

Это достаточно или я должен использовать следующий код?

        $output = mysqli_real_escape_string($base, $input);
        $output = strip_tags($output);

Извините, это может быть глупый вопрос, но я хотел бы избежать проблем с моим кодом :) Спасибо за вашу помощь.


person Tiago    schedule 19.02.2017    source источник
comment
Использование подготовленных отчетов достаточно безопасно и не требует, чтобы вы каким-либо образом скрывали свои данные. Экранирование необходимо только тогда, когда вы объединяете свои SQL-запросы с входными данными, что не имеет места при использовании подготовленных операторов.   -  person Magnus Eriksson    schedule 19.02.2017
comment
СУБД автоматически очистит параметры, предоставленные в подготовленном операторе, на основе ожидаемого типа данных и кодировки. Если вы вручную экранируете строку, а затем отправляете ее как параметр подготовленного оператора, вы фактически делаете ее менее безопасной.   -  person apokryfos    schedule 19.02.2017
comment
Если у вас есть время, научитесь использовать PDO для обработки взаимодействий с базой данных. php.net/manual/en/book.pdo.php   -  person Anthony Rutledge    schedule 19.02.2017
comment
Экранирование всегда должно быть для определенного контекста — операции, необходимые для того, чтобы сделать что-то безопасным для использования в базе данных, могут сделать его небезопасным для использования в качестве вывода. Так что никогда, никогда не пишите универсальную функцию clean.   -  person IMSoP    schedule 19.02.2017


Ответы (2)


Я приветствую ваши усилия. Вы должны, дружелюбный член сообщества, подумать о разделении своих операций.

1) Иметь одну функцию/подпрограмму/класс/метод для фильтрации входных данных (filter_input_array(), strip_tags(), str_ireplace(), trim() и т. д.). Вы можете захотеть создать функции, которые используют циклы для фильтрации. Такие приемы, как двойное кодирование, одноразовая подмена полосы и другие, могут победить однократное использование таких вещей, как strip_tags().

Вот метод оболочки strip_tags() из моего класса Sanitizer. Обратите внимание, как он сравнивает старое значение с новым значением, чтобы убедиться, что они равны. Если они не равны, он продолжает использовать strip_tags(). Хотя перед выполнением этого метода выполняется предварительная проверка INPUT_POST / $_POST. Другая версия этого с использованием trim() фактически выполняется перед этой.

private function removeHtml(&$value)
{    
    if (is_scalar($value)) {
        do {
            $old = $value;
            $value = strip_tags($value);

            if ($value === $old) {
                break;
            }
        } while(1);
    } else if (is_array($value) && !empty($value)) {
        foreach ($value as $field => &$string) {
            do {
                $old = $string;
                $string = strip_tags($string);

                if ($string === $old) {
                    break;
                }
            } while (1);
        }
    } else {
       throw new Exception('The data being HTML sanitized is neither scalar nor in an array.');
    }

    return;
}

2) Есть еще один для проверки ввода (filter_var_array(), preg_match(), mb_strlen и т. д.)

Затем, когда вашим данным нужно переключить контексты...

A) Для баз данных используйте подготовленные операторы (предпочтительно PDO).

B) Для возврата/передачи ввода пользователя в браузер экранируйте вывод с помощью htmlentities() или htmlspecialchars соответственно.

Что касается магических кавычек, лучше всего просто отключить их в файле php.ini.

Теперь, когда эти различные конструкции имеют свои собственные области ответственности, все, что вам нужно сделать, это управлять потоком логики и данных внутри вашего файла обработчика. Сюда входит предоставление пользователю сообщений об ошибках (при необходимости) и обработка ошибок/исключений.

Нет необходимости сразу использовать htmlentities() или htmlspecialchars, если данные поступают из HTML-формы непосредственно в базу данных. Смысл экранирования данных состоит в том, чтобы предотвратить их интерпретацию как исполняемые инструкции внутри нового контекста. Нет никакой опасности, которую htmlentities() или htmlspecialchars могут устранить при передаче данных в механизм запросов SQL (именно поэтому вы фильтруете и проверяете ввод и используете (PDO) подготовленные операторы).

Однако после того, как данные извлекаются из таблиц базы данных и непосредственно предназначены для браузера, хорошо, теперь используйте htmlentities() или htmlspecialchars. Создайте function, который использует цикл for или foreach для обработки этого сценария.

Вот фрагмент из моего класса Escaper

public function superHtmlSpecialChars($html)
{
     return htmlspecialchars($html, ENT_QUOTES | ENT_HTML5, 'UTF-8', false);
}

public function superHtmlEntities(&$html)
{
    $html = htmlentities($html, ENT_QUOTES | ENT_HTML5, 'UTF-8', false);
}

public function htmlSpecialCharsArray(array &$html)
{       
    foreach ($html as &$value) {
        $value = $this->superHtmlSpecialChars($value);
    }

    unset($value);
}

public function htmlEntitiesArray(array &$html)
{       
    foreach ($html as &$value) {
        $this->superHtmlEntities($value);
    }

    unset($value);
}

Вам придется адаптировать свой код к своим личным вкусам и ситуации.

Обратите внимание: если вы планируете обрабатывать данные перед их отправкой в ​​браузер, сначала выполните обработку, а затем выйдите с помощью удобной функции цикла htmlentities() или htmlspecialchars.

Ты можешь это сделать!

person Anthony Rutledge    schedule 19.02.2017
comment
Это отличный ответ. Я думаю, что первое предложение следует сформулировать более строго: вы должны отделить свои операции, потому что они должны выполняться в разных местах, чтобы выполнять свои задачи. Что касается магических кавычек, последняя версия PHP, поддерживающая их, была 5.3, которые перестали получать официальные исправления безопасности более 2,5 лет назад. - person IMSoP; 19.02.2017
comment
@IMSoP Спасибо. Я помню, как начинал и должен был изучать информационную безопасность. Знание почему вы что-то делаете (фильтрация/проверка/экранирование) имеет большое значение. - person Anthony Rutledge; 20.02.2017
comment
Удивительный ответ. Спасибо! - person Tiago; 22.02.2017

Сценарий использования для обоих strip_tags() and htmlentities or htmlspecialchars().

1.) Если вы хотите удалить любые html-элементы из входных данных формы, которые могут быть уязвимы для XSS-атаки, используйте функцию strip_tags() перед вставкой в ​​​​базу данных. Пример

$data= strip_tags('<b>Hello</b>');

Ваш вывод будет «Привет», и это то, что будет передано на сервер.

2.) Если вы хотите распечатать данные в браузере или на экране, вы можете использовать htmlentities() or htmlspecialchars() ниже приведен сценарий, в котором его можно использовать.

//DB PDO Connect....
$result2 = $db->prepare('select * from users where uid=:uid');
        $result2->execute(array(':uid' =>'1'));

 while ($row = $result2->fetch()) {


$pic=htmlentities($row['profilepic'], ENT_QUOTES, "UTF-8");
}

Затем вы можете распечатать $pic в любом месте и быть свободными от XSS-атаки....

person nackolysis    schedule 19.02.2017