I am trying to filter the user's input from malicious code to prevent XSS attack. When the user submits the input, the input goes trough the following checks... The input is contained in the $post variable.
$post = htmlspecialchars($post);
$id = $_SESSION['loggedIn'];
$sql = "UPDATE playerstats SET message='$post' WHERE id = $id";
$db->query($sql);
header("location: ?page=message");
Yeah i know i am not using prepared statements, but i made that code just for testing purposes. Okay, it works. In the database i see
<script>top.location.href = "?page=message";</script>
So in that message page i see the post that was just inserted. But i don't see the effect of htmlspecialchars? It affected the post when it got submitted to the database, but when i display it in the message page.. i see again
<script>top.location.href = "?page=message";</script>
Any idea why this is happening? Is the htmlspecialchars command only meant to be for output?
The point of htmlspecialchars is to remove any HTML special characters and replace them with Ampersand-Codes which will show the character but not get interpreted as HTML. This is highly effective against XSS Attacks (but not SQL Injection).
That means if you put the string <script>malicousCode</script> through htmlspecialchars and echo it into the page, the user will see the actual string. If you do not put it through htmlspecialchars the browser would think that it's a <script> tag and execute malicousCode.
This in itself does not prevent SQL Injection! It is only used to sanitize strings which you want to show to the user.
To prevent SQL Injection use prepared statements (I discourage you from using any other forms of escaping like mysqli_real_escape_string because using prepared statements makes it completely impossible)
htmlspecialchars encodes html characters, for example <tag> will be replaced with <tag>. When you load that string back from database and display it, the browser will still display <tag> as <tag>, but it won't be treated as html instruction by the browser. So in the page source, you will still see the encoded <tag>.
If you want to use the string on the page so it gets interpreted as normal html command, you have to use htmlspecialchars_decode (Docs) to convert it back after you loaded the content back from the database.
loaded_from_db = htmlspecialchars_decode(value);
If you want to escape your input because of security considerations to protect you from sql injections, you could use mysqli_real_escape_string instead.
But using prepared statements would be the best choice, because you define exactly what you expect as parameters for your statements and the values provided cannot mess it up. It's also the recommended approach even if it's just for testing purpose and it's not that hard to implement.
so your example with mysqli and prepared statements would be:
$stmt = $mysqli->prepare("UPDATE playerstats SET message=? WHERE id = ?");
$stmt->bind_param("si", $post, $id)
$stmt->execute()
note that I didn't include any error handling.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With