Декодирование mysql_real_escape_string() для вывода HTML

Я пытаюсь защитить себя от инъекции sql и использую:

mysql_real_escape_string($string);

При публикации HTML это выглядит примерно так:

<span class="\&quot;className\&quot;">
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p>
</span>

Я не уверен, сколько других вариантов добавляет real_escape_string, поэтому не хочу просто заменять некоторые и пропускать другие... Как мне "декодировать" это обратно в правильно отформатированный HTML, например:

html_entity_decode(stripslashes($string));

person Peter Craig    schedule 04.04.2010    source источник
comment
Если пользователь может управлять $string, то это XSS-уязвимость.   -  person rook    schedule 16.04.2010


Ответы (9)


На странице руководства mysql_real_escape_string() указано, какие символы экранируются:

mysql_real_escape_string() вызывает библиотечную функцию MySQL mysql_real_escape_string, которая добавляет обратную косую черту перед следующими символами: \x00, \n, \r, \, ', " и \x1a.

Вы можете успешно отменить экранирование, заменив эти экранированные символы их неэкранированными формами.

mysql_real_escape_string() не следует использовать для очистки HTML... нет причин использовать его перед выводом данных веб-страницы. Его следует использовать только для данных, которые вы собираетесь поместить в базу данных. Ваш процесс санитарной обработки должен выглядеть примерно так:

Ввод

  1. Принимать пользовательский ввод из формы или HTTP-запроса
  2. Создайте запрос к базе данных, используя mysql_real_escape_string()

Вывод

  1. Получить данные из базы данных
  2. Пропустите любые пользовательские данные через htmlspecialchars() перед печатью

Использование другого драйвера базы данных, такого как MySQLi или PDO позволит вам использовать подготовленные операторы, которые позаботятся об экранировании большинства входных данных за вас. Однако, если вы не можете переключиться или воспользоваться ими, обязательно используйте mysql_real_escape_string()... просто используйте его только перед вставкой данных.

person zombat    schedule 04.04.2010
comment
Я бы рекомендовал подготовленные операторы (например, php.net/manual/en/class.pdostatement .php) более mysql_real_escape_string. И htmlspecialchars не всегда правильный выбор. Иногда белый список является лучшим вариантом. - person Matthew Flaschen; 04.04.2010
comment
Примечание! Если у вас включены 'magic_quotes', даже с PDO вам нужно будет использовать 'stripslashes()' перед помещением строк в базу данных, чтобы избежать двойной косой черты. - person mrserge; 14.08.2015
comment
Но ни в одной современной системе не должно быть включено magic_quotes. Эта функция устарела в течение многих лет. - person Bill Karwin; 04.08.2016

У тебя все перепуталось.

mysql_real_escape_string не нуждается в декодировании.

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

Не говоря уже о том, что любой побег устарел, и вы должны

использовать подготовленные операторы

вместо любой управляющей строки.

Так что никогда не убегайте, никогда не расшифровывайте.
Проблема решена.

person Your Common Sense    schedule 04.04.2010
comment
$query=INSERT INTO table SET html='$html'; не является стандартным SQL, вам лучше использовать INSERT INTO table (html) VALUES('content'); Это работает во всех базах данных, а не только в MySQL. - person Frank Heikens; 04.04.2010
comment
@Frank Heikens Но я работаю с mysql. И я использую множество специфических функций mysql. Скажи мне не использовать PHP, так как он не везде поддерживается. Что за бредовый комментарий! - person Your Common Sense; 04.04.2010
comment
Как указал Гасс, экранирование необходимо для защиты вашей базы данных от SQL-инъекций. - person Pete; 28.07.2018
comment
Спасибо, вы спасли мне жизнь, я использовал подготовленный оператор и mysql_real_escape_string, что привело к двойному экранированию :-) - person LDK; 18.02.2020

mysql_real_escape_string используется для предотвращения SQL-инъекций при сохранении предоставленных пользователем данных в базу данных, но лучшим методом было бы использовать привязку данных с помощью PDO (например). Я всегда рекомендую использовать это вместо того, чтобы возиться с побегом.

При этом, что касается вашего вопроса о том, как отобразить его впоследствии - после того, как данные сохранены, когда вы их извлекаете, данные являются полными и действительными без какой-либо необходимости «не экранироваться». Если вы не добавили свои собственные экранирующие последовательности, пожалуйста, не делайте этого.

person Guss    schedule 04.04.2010

Не уверен, что происходит с форматированием, как я вижу, но ваша html-форма

<span class="\&quot;className\&quot;">
<p class="\&quot;pClass\&quot;" id="\&quot;pId\&quot;"></p>
</span>

должно быть просто;

<span class="className">
<p class="pClass" id="pId"></p>
</span>

Когда вы получите его обратно, прежде чем поместить его в базу данных, вы избегаете его, используя mysql_real_escape_string(), чтобы убедиться, что вы не подвергаетесь атаке с внедрением sql.

Следовательно, вы избегаете значений, готовых к тому, чтобы текст был следующим.

Когда вы получаете его из базы данных (или отображаете ЛЮБУЮ из них пользователям в виде html), вы снова избегаете его, готового к тому, что это место будет следующим (html) с помощью htmlentities() и т. д., чтобы защитить ваших пользователей от XSS-атак.

Это формирует ЭО-часть мантры FIEO, Filter Input, Escape Output, которую вы должны вытатуировать на внутренней стороне век.

person Cups    schedule 04.04.2010
comment
Вы уверены, что он хочет, чтобы эта форма сбежала? А я в глубоких сомнениях. Если кто-то использует форматирование HTML, он обычно хочет, чтобы оно работало, а не как видимые теги. - person Your Common Sense; 04.04.2010

Мне было интересно, почему у этой процедуры нет сопутствующей процедуры декодера. Вероятно, он интерпретируется MySQL точно так же, как если бы он не был экранирован. Вы получаете неэкранированные результаты, когда выполняете $row=mysql_fetch_array($res, MYSQL_ASSOC)';

person HELPFUL_SHADOW    schedule 22.09.2013

Что ж, я попробовал это по старинке и пока не вижу ничего плохого в своем подходе. Очевидно, что это немного грубо, но оно выполняет свою работу:

function mysql_unreal_escape_string($string) {
    $characters = array('x00', 'n', 'r', '\\', '\'', '"','x1a');
    $o_chars = array("\x00", "\n", "\r", "\\", "'", "\"", "\x1a");
    for ($i = 0; $i < strlen($string); $i++) {
        if (substr($string, $i, 1) == '\\') {
            foreach ($characters as $index => $char) {
                if ($i <= strlen($string) - strlen($char) && substr($string, $i + 1, strlen($char)) == $char) {
                    $string = substr_replace($string, $o_chars[$index], $i, strlen($char) + 1);
                    break;
                }
            }
        }
    }
    return $string;
}

Это должно охватывать большинство случаев.

person Muhwu    schedule 04.08.2016

используйте следующую функцию для удаления косых черт при отображении на HTML-странице:

полоски ();

например. $html=полоски($html); ИЛИ $html=stripslashes($row["fieldname"]);

person Nandkishor Gokhe    schedule 08.11.2017

Даже если это старый вопрос... У меня была та же проблема, что и у Питера Крейга. На самом деле мне приходится иметь дело со старой CMS. Чтобы предотвратить SQL-инъекцию, все значения $_POST и $_GET экранируются sql-экраном. К сожалению, это делается в центральной точке, поэтому все ваши модули получают все данные, экранированные sql! В некоторых случаях вы хотите напрямую отображать эти данные, поэтому сталкиваетесь с проблемой: как отобразить строку с экранированием sql, не получая ее из БД? Ответ: используйте stripcslashes (НЕ Stripslashes!!)

http://php.net/manual/en/function.stripcslashes.php

person Peter    schedule 30.01.2017

Я думаю, что в ряде других ответов пропущена очевидная проблема...

Вы используете mysql_real_escape_string для введенного содержимого (как и следует, если не используете подготовленные операторы).

Ваша проблема связана с выводом.

Текущая проблема заключается в том, что вы вызываете html_entity_decode. Всего лишь полоска слэша — это все, что вам нужно, чтобы восстановить исходный текст. html_entity_decode - это то, что портит ваши кавычки и т. д., поскольку оно их меняет. На самом деле вы хотите вывести html, а не просто текст (в этом случае вы должны использовать html_entities и т. д.). Вы декодируете то, что хотите закодировать.

Если вы хотите, чтобы отображалась только текстовая версия, вы можете использовать сущности. Если вы беспокоитесь о неверных тегах, используйте стриптеги и разрешайте только те теги, которые вам нужны (например, b, i и т. д.).

Наконец, не забудьте кодировать и декодировать в правильном порядке. если вы запустили mysql_real_escape_String(htmlentities($str)), то вам нужно запустить html_entity_decode(stripslashes($str)). Порядок операций имеет значение.

ОБНОВЛЕНИЕ: я не знал, что html_entity_decode также удаляет косые черты. Это не было четко задокументировано на той странице, и я просто не уловил этого. Я все равно буду запускать его автоматически, так как большинство html, которые я представляю, я хочу оставить как объекты, и даже когда я этого не делаю, я предпочитаю принимать это решение вне моего класса db, в каждом конкретном случае. Таким образом, я знаю, что косые черты исчезли.

Похоже, что исходный постер использует htmlentities (или его программу ввода, например, tinymce, которая делает это за него), и он хочет вернуть ее к содержимому. Таким образом, html_entity_decode($Str) должно быть всем, что требуется.

person Cryophallion    schedule 04.04.2010
comment
Вы неправы. ему не нужно обнажать косые черты. Ne нужно добавить его правильно. Лечите болезнь, а не симптом. - person Your Common Sense; 04.04.2010
comment
Ему ДЕЙСТВИТЕЛЬНО нужно удалить косые черты, так как он сначала запустил escape-строку. Он закодировал его, теперь ему нужно его раскодировать, чтобы избавиться от косых черт в выводе. Следовательно, \ появляется перед . - person Cryophallion; 04.04.2010
comment
Вы понятия не имеете, как эта штука работает. Так что лучше запретите себе отвечать, пока не научитесь. Нет необходимости в зачистке. Попробуй сам. - person Your Common Sense; 04.04.2010
comment
Наконец, не забудьте кодировать и декодировать в правильном порядке. если вы запустили mysql_real_escape_String(htmlentities($str)), никаких действий по декодированию не требуется. Иди разберись. если вам не нужны сущности - просто не кодируйте их. Если делали - зачем расшифровывать? - person Your Common Sense; 04.04.2010
comment
Мой класс базы данных запускает real_escape_string перед каждой вставкой. Чтобы избавиться от косых черт перед кавычками, мне нужно запустить полосовые косые черты, иначе косые черты экранируются. Я абсолютно точно знаю, как это работает — я постоянно пишу этот материал. Пытается вернуть свой html, там косые черты. Как, кроме стрипов, вы планируете это сделать, не усложняя? Однако сначала ему нужно убедиться, что сущности вернулись! Проблема в том, что он сначала запускает стрип, он должен сначала запускать декодирование. - person Cryophallion; 04.04.2010
comment
I have to run stripslashes, or the slashes are escaped. I absolutely know how it works ахахахахаха! какой забавный комментарий :) Иди отключи волшебные кавычки и почитай что-нибудь об этом вручную. Ваш вопрос был задан недавно stackoverflow.com/questions/2573150/ - person Your Common Sense; 04.04.2010
comment
Этот вопрос вообще не имеет отношения к этому (речь идет не о том, занимают ли косые черты символы в mysql). A. Я не использую волшебные кавычки B. Я исправлен в необходимости использовать полоски косой черты в html_entity_decode. Это не четко задокументировано на странице руководства, и это приятно знать. ОДНАКО, это не обязательно плохо, чтобы привыкнуть делать (запускать полосы косой черты перед чем-либо еще), если вы хотите, чтобы объекты были преобразованы или нет. - person Cryophallion; 04.04.2010