I am getting some data in JSON format via jQuery and then I need to display it to users, however it is vulnerable to XSS attack. What are my options here, should I strip chars before I put the data in database? Framework that I am using (Kohana) has a nifty function HTML::Chars();, but since I am displaying data with javascript I can’t use it there.
One option seems to be is to walk through every array element that is being json encoded and apply HTML::Chars(); to it. Is it the only option, and if so than what would be optimal way of doing this?
Example:
- User enters some data:
title, body - Data is stored into database
- Then some other user enters site, data array is taken from database
and exported to json format - My jQuery script is taking the json and appending new element to
body of my page.
Code:
$(document).ready(function(){
$.ajax({
url: '/timeline/latest/1',
dataType: 'json',
success: function(data){
$.each(data, function(key, val) {
switch (val.type){
case 'post': // I have only made post so far
addPost(val);
break;
}
});
}
});
})
function addPost(val){
$('.content .timeline').prepend(val.title + '<br />' + val.body); // xss vulnerable
}
Getting data from database
<?php
class Controller_Timeline extends Controller{
public function Action_Latest(){
$parentID = $this->request->param('id');
$modelTimeline = new Model_Timeline();
// Here I get latest entries, big array
$latest = $modelTimeline->Latest($parentID);
// Response it and encode with JSON
$this->response->body(json_encode($latest));
}
}
My solution so far is this, before I echo out the $latest I walk through array and apply the anti-xss function, I don’t know how optimal it is however:
array_walk($latest, function(&$latest){
foreach ($latest as &$key){
$key = HTML::chars($key);
}
});
I suggest you do it like Drupal.
Drupal doesn’t filter any input. It stores the text in the database with XSS vulnerabilities if this HTML code were to be displayed without being filtered.
Instead, it filters on the output. You should definitely do that on the server side.
You should inspire yourself from the
filter_xss()function Drupal uses.Make sure it’s applied for each of your entry. Do it globally if you can of course, like the following: