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

Scott Werner scott.werner.vt at gmail.com
Tue Oct 3 17:50:32 EDT 2017


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/flask/attachments/20171003/5ce3f20f/attachment.html>


More information about the Flask mailing list