Escape JSON vars without escaping JSON control characters

298 views
Skip to first unread message

spiffytech

unread,
Dec 14, 2010, 1:28:50 AM12/14/10
to web2py-users
I'm fetching data from my database, converting it to JSON with
simplejson.dumps(), then passing it to my view to include in my
Javascript. I need to escape the JSON vars to prevent XSS attacks
without escaping all of the brackets, braces, and quotes that make
JSON work.

How can I do this? What I've attempted so far results in either the
entire JSON string being escaped, or none of it. I've hacked together
a loop that generates and prints the JSON one variable, but that's
pretty fragile and kludgy solution. Surely there's a better way?

DenesL

unread,
Dec 14, 2010, 11:34:35 AM12/14/10
to web2py-users

Maybe one of the examples in __init__.py under gluon/contrib/
simplejson can help.
Otherwise post a sample of your data and how you need it.

spiffytech

unread,
Dec 15, 2010, 12:09:55 PM12/15/10
to web2py-users
Here's my sample data, generated in my controller with
"db(...).select().as_list()":

====
events = [{'address': 'Poe Hall, Raleigh, NC 27607, USA',
'description': 'Description',
'food_desc': 'Food at the event',
'id': 15,
'latitude': '35.7855918',
'location': 'Room 9999',
'longitude': '-78.6663783',
'timestamp': '2010-12-17 11:44:58',
'title': 'Event title',
'university': 'North Carolina State University'},
{'address': 'Poe Hall, Raleigh, NC 27607, USA',
'description': "<script>alert('stuff');</script>",
'food_desc': 'Vulnerability stew',
'id': 16,
'latitude': '35.7855918',
'location': 'Room 9999',
'longitude': '-78.6663783',
'timestamp': '2010-12-17 11:44:58',
'title': 'XSS event',
'university': 'North Carolina State University'}]
====

I run this through "simplejson.dumps(data)", which produces this:

====
json_events = '[{"description": "Description", "title": "Event title",
"timestamp": "2010-12-17 11:44:58", "university": "North Carolina
State University", "longitude": "-78.6663783", "food_desc": "Food at
the event", "location": "Room 9999", "address": "Poe Hall, Raleigh, NC
27607, USA", "latitude": "35.7855918", "id": 15}, {"description":
"<script>alert(\'stuff\');</script>", "title": "XSS event",
"timestamp": "2010-12-17 11:44:58", "university": "North Carolina
State University", "longitude": "-78.6663783", "food_desc":
"Vulnerability stew", "location": "Room 9999", "address": "Poe Hall,
Raleigh, NC 27607, USA", "latitude": "35.7855918", "id": 16}]'
====

I pass that string into my view, where I want to use it like this:

====
...
<script type="text/javascript">
var events = {{=json_events}};
for(event in events) {
<do stuff with event["title"]>
<do stuff with event["description"]
...
}
</script>
...
====

However, this doesn't work because "{{=json_events}}" escapes the
quotes in the JSON string (producing "var events =
[{&quot;description&quot;&#58; &quot;Description&quot;, ..."), so I
get a Javascript error saying "I don't know how to make sense of
'&quot;', I need real quotes!".

I tried "{{response.write(json_events, escape=True}}" and
"{{=XML(json_events, sanitize=True}}", but those produce the same
Javascript error as the ordinary "{{=json_events}}".

So I tried "{{response.write(json_events, escape=False}}" and
"{{=XML(json_events, sanitize=False}}", but they leave the site
vulnerable to the Javascript embedded in the second event's
description.

So what I need is a way to escape/sanitize the data coming from the
database without escaping/sanitizing the quotation marks that allow me
to embed JSON in my view.

I have a temporary solution (using a loop with web2py view code to
print JSON into the view, element by element) but it's kludgy and a
pain to maintain. Is there a better solution to this dilemma?

DenesL

unread,
Dec 17, 2010, 4:02:47 PM12/17/10
to web2py-users

Try with $.getJSON() as in

<script>
$.getJSON('/your_app/your_ctl/your_action_returning_json',
function(events) {
for(event in events) {
...
};
});
</script>
Reply all
Reply to author
Forward
0 new messages