Reputation: 65
I am using comment system like this:(i have simplified code for this question)
<?php
$status_ui = '<textarea id="box"></textarea>';
$status_ui .= '<button id="status_button" onclick="postComment(\'box\')">Post</button>';
?>
<html>
<head>
<script type="text/javascript">
function postComment(box){
var data = document.getElementById(box).value;
data = data.replace(/[^a-zA-Z0-9,.?! ;:'"]+/, '');
var hr = new XMLHttpRequest();
hr.open("POST", "comment_system.php", true);
hr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
hr.onreadystatechange = function() {
if(hr.readyState == 4 && hr.status == 200) {
var html_output = "";
current_html = document.getElementById("comment_list").innerHTML;
html_output += '<div class="comment">';
html_output += data;
html_output += '</div>';
document.getElementById("comment_list").innerHTML = html_output + current_html;
}
results_box.innerHTML = html_output;
}
}
hr.send("comment="+data);
</script>
</head>
<body>
<div id="container">
<?php echo $status_ui; ?>
<div id="comment_list"></div>
</div>
</body>
</html>
Users can enter only a-zA-Z0-9,.?! ;:'" and everything works super cool.
In comment_system.php, I am performing all kinds of checks, regex, in order to store my data safely to DB. The question is: how to output the user comment securely to the comment_list div to be XSS proof?
I am using string.replace,and I am aware that it can be bypassed by the bad user.
Upvotes: 0
Views: 142
Reputation: 536429
html_output += '<div class="comment">';
html_output += data;
html_output += '</div>';
This is HTML injection, resulting in a client-side cross-site-scripting (DOM-XSS) vulnerability.
To stop active HTML content being included in the comment div, either:
<
to <
)document.getElementById("comment_list").innerHTML = html_output + current_html;
This is a bad idea. Every time you call this you are serialising the entire contents of the comment list to a new HTML markup string, adding to the string, destroying all the elements in the comment list, and parsing new elements from the markup. This is slow and prone to reserialization errors which also can lead to DOM-XSS (IE has trouble with the backquote character - reading innerHTML
doesn't necessarily give you a string that is safe to re-assign to innerHTML
).
Again, avoid this by creating your content with DOM methods:
var comment = document.createElement('div');
comment.appendChild(document.createTextNode(data));
var list = document.getElementById('comment_list');
list.insertBefore(comment, list.firstChild);
(And similarly for the results box.) Now it doesn't matter what funny characters might have been in the user input, you will always display correctly. Consequently you can allow users to type a less-then sign without mangling their comment.
In comment_system.php, I am performing all kinds of checks, regex, in order to store my data safely to DB.
Input filtering has its place but it is not the answer to SQL injection. You should be using query parameterisation (with mysqli or PDO) to get data into the database and not creating queries with data in them. Then, again, any input is safe and you can allow the user to type an apostrophe without mangling their comment.
Upvotes: 2