In a project I have to do for school it is required to prevent XSS (Cross-Site Scripting) attacks at my website, so tags such as <script type="text/javascript">alert("hello");</script> (which I can insert in every input tag in my website) shouldn't work (I should not see the alert window in this case). At school I was advised to use the php function htmlspecialchars, but the browser still shows me the alert window, when I insert this tag in a comment in my website. I can't understand what I'm doing wrong.
(NOTE: I've also inserted the js code, but I think that the problem is in php, all the code works correctly)
$("#new-comment").on('click',function(){
var $newReview = $("<input class='new-input' type='text' id='insert' name='insert' placeholder='write here...'>");
$("#reviews").append($newReview);
$newReview.on('keypress',function(e){
if(e.which == 13){
var comm = $(this);
var datatime = new Date($.now());
correctHour = printMysqlFormat(datatime);
$.ajax({
url:'reviews/reviews_query.php',
data: {put:true, title: $("#right_title").text(), script: comm.val(), time: correctHour},
datatype:'json',
success: function(json){
var output = jQuery.parseJSON(json);
var newName = "<span class='rev_name'>"+ output + "</span>";
var newComment = "<span class='rev_comment'>"+ comm.val() + "<div class='rev_time'>" + correctHour + "</div></span>";
$("#reviews > ul").html($("#reviews > ul").html()+"<li style='margin-bottom:20px'>" + newName + " " + newComment + "</li>");
},
error: function(e){
console.log(e.message);
}
});
$newReview.remove();
}
});
});
if(isset($_GET["show"]) && isset($_GET["title"])){ //to show all comments
$db = new PDO("mysql:host=localhost;dbname=music", "username", "password");
$titolo = $_GET["title"];
$ti = $db->quote($titolo);
$rows = $db->query("SELECT * FROM reviews WHERE titolo=$ti ORDER BY ora ASC");
if($rows->rowCount() == 0){
echo 0;
}else{
$res = $rows->fetchALL(PDO::FETCH_ASSOC);
echo json_encode($res);
}
}
if(isset($_GET["put"]) && isset($_GET["title"]) && isset($_GET["script"]) && isset($_GET["time"])){ //to write a new comment
$db = new PDO("mysql:host=localhost;dbname=music", "username", "password");
$username = $_SESSION["name"];
$us = $db->quote($username);
$titolo = $_GET["title"];
$ti = $db->quote($titolo);
$commento = $_GET["script"];
$commento = htmlspecialchars($commento);
$comm = $db->quote($commento);
$timestamp = $_GET["time"];
$tim = $db->quote($timestamp);
$rows = $db->query("INSERT into reviews VALUES ($us, $ti, $comm, $tim)");
$res = $_SESSION["name"];
echo json_encode($res);
}
EDIT: I've tried with this code but nothing changes:
if(isset($_GET["show"]) && isset($_GET["title"])){
$db = new PDO("mysql:host=localhost;dbname=music", "username", "password");
$titolo = $_GET["title"];
$ti = $db->quote($titolo);
$rows = $db->query("SELECT * FROM reviews WHERE titolo=$ti ORDER BY ora ASC");
if($rows->rowCount() == 0){
echo 0;
}else{
$res = $rows->fetchALL(PDO::FETCH_ASSOC);
$res['comment_clean'] = htmlspecialchars($res['commento'], ENT_QUOTES, 'UTF-8'); //commento is an attribute of my table, where I save the comment
echo json_encode($res);
}
}
newComment = "<span class='rev_comment'>"+ comm.val(), and then putting that into your page. So in this code you're just taking the raw comment value from the input directly. You're not using the encoded version which was saved into the database.htmlspecialcharsto the data that gets inserted into the database, is fundamentally wrong to begin with. This should happen when the data is read back from the database, the moment it gets put into the HTML context. But you have not even shown us that part yet, currently the only thing you are giving back from the server to the client is the user name from the session, all other values are still client-side ones to begin with.