[Flask] Generic way of input filtering and output encoding to prevent XSS

Ritesh Nadhani riteshn at gmail.com
Tue Oct 3 18:11:52 EDT 2017


It seems when I cut-n-paste into GMAIL it does its own stripping.

The input output is exactly like you showed and its using flask jsonify.

I will look into the libraries. Seems like we will have to go back and
look into each API call to handle it correctly.

On Tue, Oct 3, 2017 at 2:50 PM, Scott Werner <scott.werner.vt at gmail.com> wrote:
> Why is description being converted from "foobar<script>alert(1)</script>" to
> ”}foobar{“"? Are you using flask jsonify when creating your API response?
>
>>>> import json
>>>> form_data =
>>>> json.loads('{"description":"foobar<script>alert(1)</script>"}')
> {'description': 'foobar<script>alert(1)</script>'}
>>>> json.dumps(form_data)
> '{"description": "foobar<script>alert(1)</script>"}'
>
> You should serialize (dumping) and de-serialize (loading) using a library
> like https://marshmallow.readthedocs.io/en/latest/.
> If the user can input html, like a rich editor, and you display it in
> Angular (not escaped), then you should sanitize it with a library like
> https://github.com/mozilla/bleach.
> A quick search shows that you can also sanitize on the client side using
> angular: https://docs.angularjs.org/api/ngSanitize/service/$sanitize.
>
> In summary, never trust the user and always validate on the server.
>
> On Tue, Oct 3, 2017 at 2:57 PM, Ritesh Nadhani <riteshn at gmail.com> wrote:
>>
>> Hello
>>
>> I inherited a Flask + Angular app where all the APIs are basically API
>> calls. As is usual, through some forms allow users to provide names
>> for object and we save it to our DB which can be retreived back. This
>> happens with multiple apis.
>>
>> E.g.
>>
>> HTTP POST:
>> POST /api/v2/flags HTTP/1.1
>> ....
>> Content-Type: application/json;charset=utf-8
>> Content-Length: 109
>> ...
>>
>> {
>>   "description":"foobar<script>alert(1)</script>",
>>   "name":"test99",
>>   "permission":"NO_ACCESS",
>>   "type":"watchlist"
>> }
>>
>> HTTP RESPONSE:
>> HTTP/1.1 200 OK Server: nginx/1.6.2  ..
>> Content-Type: application/json
>> Content-Length: 1195
>>
>> {
>>   "flags":[
>>     {
>>       "description":"”}foobar{“",
>>       "end_time":9999999999000,
>>       "entities":0,
>>       "id":4,
>>       "name":"test99",
>>       "permission":"NO_ACCESS",
>>       "start_time":0,
>>       "type":"watchlist",
>>       "user_id":3
>>     }
>>   ],
>>   "limit":100,
>>   "offset":0,
>>   "status":"Ok",
>>   "total":4
>> }
>>
>> ...
>>
>> we recently had a security inspection and this was deemed to be not
>> properly encoding of output and vulnerable to XSS attack.
>>
>> >>>
>>
>> What is the canonical way to handle this? Since the name is used as
>> reference and other place, ideally I would not like to keep encoded
>> version into the DB. Is there a generic library that can encode the
>> output before sending it back to the client? I suspect in that case UI
>> will have to decode the data in every case to show the correct string
>> to user?
>>
>> I tested against some website e.g. digitalocean and I noticed that if
>> you enter such string in the form, its blocked by cloudflare itself.
>> Since we dont use cloudflare, what is our other options?
>>
>>
>> --
>> Ritesh
>> _______________________________________________
>> Flask mailing list
>> Flask at python.org
>> https://mail.python.org/mailman/listinfo/flask
>
>
>
>
> --
> Scott Werner
> scott.werner.vt at gmail.com



-- 
Ritesh


More information about the Flask mailing list