2

I've read here:
https://stackoverflow.com/a/8932454/4301970
that htmlspecialchars() is very effective preventing xss attacks.

I'm receiving formated text from a wysiwyg editor, for example:

<p>
    <em>
        <strong><span style="font-size:36pt;">test</span></strong>
    </em>
</p>

Encoding this on my html:

<!DOCTYPE html>
<html lang=en>
<head>
    <title></title>
</head>
<body>
<?php echo htmlspecialchars('<p><em><strong><span style="font-size:36pt;">test</span></strong></em></p>', ENT_QUOTES); ?>
</body>
</html>

Will output on browser:

<p><em><strong><span style="font-size:36pt;">test</span></strong></em></p>

How can I display the formatted text correctly, while preventing XSS injections?

Community
  • 1
  • 1
random425
  • 679
  • 1
  • 9
  • 20

3 Answers3

2

The htmlspecialchars encodes all characters that have (or could) special meanings in XML, specifically <, >, &, ", and ' (if ENT_QUOTES is set).

So with this setting any malicious code attempts would not be rendered by the browser.

For example

<script>alert('bam');</script>

would be

&lt;script&gt;alert('bam');&lt;/script&gt;
//or with quotes constant
&lt;script&gt;alert(&#039;bam&#039;);&lt;/script&gt;

which JS won't process. So that can be an affective means of stopping XSS injections. However you want users to submit some HTML so you will need to make a kind of whitelist of approved elements. You can do that by replacing the <> with custom text that won't occur in your users inputs. In my below example I've chosen custom_random_hack. Then run everything through the htmlspecialchars which will encode all special characters. Then convert your swapped elements back to their HTML elements.

$string = '<p>
    <em>
        <strong><span style="font-size:36pt;">test</span></strong>
    </em>
</p>';
$allowedtags = array('p', 'em', 'strong');
echo '~<(/?(?:' . implode('|', $allowedtags) . '))>~';
$string = preg_replace('~<(/?(?:' . implode('|', $allowedtags) . '))>~', '#custom_random_hack$1custom_random_hack#', $string);
echo str_replace(array('#custom_random_hack', 'custom_random_hack#'), array('<', '>'), htmlspecialchars($string, ENT_QUOTES));

Demo: https://eval.in/582759

chris85
  • 23,846
  • 7
  • 34
  • 51
1

To prevent xss injections and show correctly, once that strip_tag() isn't fully safe, you should take a look in HTML PURIFIER

I hope this helps!

Community
  • 1
  • 1
Allan Andrade
  • 670
  • 10
  • 26
0

If you want to preserve the indentation:

Wrap your output in a <pre> tag. This tags preserve whitespace charaters

If you want the input to be rendered as HTML:

don't use htmlspecialchars. And yes, this opens up your app to XSS again.

AUsr19532
  • 228
  • 1
  • 11
  • If he want's to render HTML **and** be safe from XSS he'd have to sanitize the input and render the sanitized input as HTML. For example using some pseudo code syntax in the editor such as buelltinboard software does. – AUsr19532 Jun 03 '16 at 13:58