I have some articles around the web that talks about XSS attack prevention,but I haven't found any solution:
htmlspecialchars(mb_convert_encoding($value, "UTF-8", "UTF-8"),ENT_QUOTES,'UTF-8')
or
json_encode($value, JSON_HEX_QUOT|JSON_HEX_TAG|JSON_HEX_AMP|JSON_HEX_APOS);
or simply strip_tags
.
At this moment I'pm using these methos everytime I need to retrieve and display some information, execpt for the mesages, because it breaks the format
What I need to do is to prevent XSS attack from this situation:
I have got an upload form that if there are any error it returns the name and alert it;
echo '<script>parent.noty({text: "File Name:'.json_encode($_FILES['filename']['name'][$i]).' Error Code:'.$_FILES['filename']['error'][$i].'",type:"error",timeout:9000});</script>';
User can write messages that can contain html tags, such as the script one, I need to keep it: I use ckeditor to write new messages and I when I retrieve the message I need the main format(
...) to remain and make the script part armless
At this moment when I return the file name I use json_encode
, but I'm not sure
EDIT
From the comments I have got that there aren't many possibilities, so I would like to know why those methods aren't reliable
EDIT
This is how I retrieve the messages:
$query = "SELECT
a.enc_id,
IF(b.department_name IS NOT NULL, b.department_name,'Unknown'),
IF(c.name IS NOT NULL, c.name,IF(a.ticket_status='2','Not Assigned','Unknown'),
a.title,
CASE a.priority WHEN '0' THEN 'Low' WHEN '1' THEN 'Medium' WHEN '2' THEN 'High' WHEN '3' THEN 'Urgent' WHEN '4' THEN 'Critical' ELSE priority END,
a.created_time,
a.last_reply,
CASE a.ticket_status WHEN '0' THEN '<span class=\'label label-success\'>Closed</span>' WHEN '1' THEN '<span class=\'label label-important\'>Open</span>' WHEN '2' THEN '<span class=\'label label-warning\'>To Assign</span>' WHEN '3' THEN '<span class=\'label label-important\'>Reported</span>' ELSE 'Error' END
FROM ".$SupportTicketsTable." a
LEFT JOIN ".$SupportDepaTable." b
ON b.id=a.department_id
LEFT JOIN ".$SupportUserTable." c
ON c.id=a.operator_id
WHERE a.user_id=".$_SESSION['id']."
ORDER BY a.last_reply DESC
LIMIT 350";
$STH = $DBH->prepare($query);
$STH->execute();
$list=array('response'=>'ret','tickets'=>array('user'=>array()));
$STH->setFetchMode(PDO::FETCH_ASSOC);
$a = $STH->fetch();
if(!empty($a)){
do{
$list['tickets']['user'][]=array('id'=>$a['enc_id'],'dname'=>$a['dname'],'opname'=>$a['opname'],'title'=>htmlspecialchars(mb_convert_encoding($a['title'], "UTF-8", "UTF-8"),ENT_QUOTES,'UTF-8'),'priority'=>$a['prio'],'date'=>$a['created_time'],'reply'=>$a['last_reply'],'status'=>$a['stat']);
}while ($a = $STH->fetch());
}
...
echo json_encode($list);
In this particular case, the correct way to escape your content is like so:
echo '...{text: "File Name:"+'.json_encode($_FILES['filename']['name'][$i]).'+" Error code...'
The reason for this is that json_encode
will take any input and make it safe to dump in a JavaScript context. A string will be surrounded by quotes and appropriately escaped to be valid. However, you must close out of existing quotes before concatenating in your value for it to work.
That said, I'm assuming that the function putting this text into your page will use something like document.createTextNode(arguments[0].text);
to create a text node, NOT an HTML context.