Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/studio/static/doc/flask-docs/security.html
blob: f118cd273e0075645ed3eb3e6a73c36ac7965f75 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">


<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    
    <title>Security Considerations &mdash; Flask 0.8 documentation</title>
    
    <link rel="stylesheet" href="_static/flasky.css" type="text/css" />
    <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
    
    <script type="text/javascript">
      var DOCUMENTATION_OPTIONS = {
        URL_ROOT:    '',
        VERSION:     '0.8',
        COLLAPSE_INDEX: false,
        FILE_SUFFIX: '.html',
        HAS_SOURCE:  true
      };
    </script>
    <script type="text/javascript" src="_static/jquery.js"></script>
    <script type="text/javascript" src="_static/underscore.js"></script>
    <script type="text/javascript" src="_static/doctools.js"></script>
    <link rel="top" title="Flask 0.8 documentation" href="index.html" />
    <link rel="next" title="Unicode in Flask" href="unicode.html" />
    <link rel="prev" title="HTML/XHTML FAQ" href="htmlfaq.html" />
   
  
  <link rel="apple-touch-icon" href="_static/touch-icon.png" />
  
  <link media="only screen and (max-device-width: 480px)" href="_static/small_flask.css" type= "text/css" rel="stylesheet" />

  </head>
  <body>
    <div class="related">
      <h3>Navigation</h3>
      <ul>
        <li class="right" style="margin-right: 10px">
          <a href="genindex.html" title="General Index"
             accesskey="I">index</a></li>
        <li class="right" >
          <a href="unicode.html" title="Unicode in Flask"
             accesskey="N">next</a> |</li>
        <li class="right" >
          <a href="htmlfaq.html" title="HTML/XHTML FAQ"
             accesskey="P">previous</a> |</li>
        <li><a href="index.html">Flask 0.8 documentation</a> &raquo;</li> 
      </ul>
    </div>  

    <div class="document">
      <div class="documentwrapper">
        <div class="bodywrapper">
          <div class="body">
            
  <div class="section" id="security-considerations">
<h1>Security Considerations<a class="headerlink" href="#security-considerations" title="Permalink to this headline">¶</a></h1>
<p>Web applications usually face all kinds of security problems and it&#8217;s very
hard to get everything right.  Flask tries to solve a few of these things
for you, but there are a couple more you have to take care of yourself.</p>
<div class="section" id="cross-site-scripting-xss">
<span id="xss"></span><h2>Cross-Site Scripting (XSS)<a class="headerlink" href="#cross-site-scripting-xss" title="Permalink to this headline">¶</a></h2>
<p>Cross site scripting is the concept of injecting arbitrary HTML (and with
it JavaScript) into the context of a website.  To remedy this, developers
have to properly escape text so that it cannot include arbitrary HTML
tags.  For more information on that have a look at the Wikipedia article
on <a class="reference external" href="http://en.wikipedia.org/wiki/Cross-site_scripting">Cross-Site Scripting</a>.</p>
<p>Flask configures Jinja2 to automatically escape all values unless
explicitly told otherwise.  This should rule out all XSS problems caused
in templates, but there are still other places where you have to be
careful:</p>
<ul class="simple">
<li>generating HTML without the help of Jinja2</li>
<li>calling <a class="reference internal" href="api.html#flask.Markup" title="flask.Markup"><tt class="xref py py-class docutils literal"><span class="pre">Markup</span></tt></a> on data submitted by users</li>
<li>sending out HTML from uploaded files, never do that, use the
<cite>Content-Disposition: attachment</cite> header to prevent that problem.</li>
<li>sending out textfiles from uploaded files.  Some browsers are using
content-type guessing based on the first few bytes so users could
trick a browser to execute HTML.</li>
</ul>
<p>Another thing that is very important are unquoted attributes.  While
Jinja2 can protect you from XSS issues by escaping HTML, there is one
thing it cannot protect you from: XSS by attribute injection.  To counter
this possible attack vector, be sure to always quote your attributes with
either double or single quotes when using Jinja expressions in them:</p>
<div class="highlight-html+jinja"><div class="highlight"><pre><span class="nt">&lt;a</span> <span class="na">href=</span><span class="s">&quot;</span><span class="cp">{{</span> <span class="nv">href</span> <span class="cp">}}</span><span class="s">&quot;</span><span class="nt">&gt;</span>the text<span class="nt">&lt;/a&gt;</span>
</pre></div>
</div>
<p>Why is this necessary?  Because if you would not be doing that, an
attacker could easily inject custom JavaScript handlers.  For example an
attacker could inject this piece of HTML+JavaScript:</p>
<div class="highlight-html"><div class="highlight"><pre>onmouseover=alert(document.cookie)
</pre></div>
</div>
<p>When the user would then move with the mouse over the link, the cookie
would be presented to the user in an alert window.  But instead of showing
the cookie to the user, a good attacker might also execute any other
JavaScript code.  In combination with CSS injections the attacker might
even make the element fill out the entire page so that the user would
just have to have the mouse anywhere on the page to trigger the attack.</p>
</div>
<div class="section" id="cross-site-request-forgery-csrf">
<h2>Cross-Site Request Forgery (CSRF)<a class="headerlink" href="#cross-site-request-forgery-csrf" title="Permalink to this headline">¶</a></h2>
<p>Another big problem is CSRF.  This is a very complex topic and I won&#8217;t
outline it here in detail just mention what it is and how to theoretically
prevent it.</p>
<p>If your authentication information is stored in cookies, you have implicit
state management.  The state of &#8220;being logged in&#8221; is controlled by a
cookie, and that cookie is sent with each request to a page.
Unfortunately that includes requests triggered by 3rd party sites.  If you
don&#8217;t keep that in mind, some people might be able to trick your
application&#8217;s users with social engineering to do stupid things without
them knowing.</p>
<p>Say you have a specific URL that, when you sent <cite>POST</cite> requests to will
delete a user&#8217;s profile (say <cite>http://example.com/user/delete</cite>).  If an
attacker now creates a page that sends a post request to that page with
some JavaScript they just has to trick some users to load that page and
their profiles will end up being deleted.</p>
<p>Imagine you were to run Facebook with millions of concurrent users and
someone would send out links to images of little kittens.  When users
would go to that page, their profiles would get deleted while they are
looking at images of fluffy cats.</p>
<p>How can you prevent that?  Basically for each request that modifies
content on the server you would have to either use a one-time token and
store that in the cookie <strong>and</strong> also transmit it with the form data.
After receiving the data on the server again, you would then have to
compare the two tokens and ensure they are equal.</p>
<p>Why does Flask not do that for you?  The ideal place for this to happen is
the form validation framework, which does not exist in Flask.</p>
</div>
<div class="section" id="json-security">
<span id="id1"></span><h2>JSON Security<a class="headerlink" href="#json-security" title="Permalink to this headline">¶</a></h2>
<div class="admonition-ecmascript-5-changes admonition ">
<p class="first admonition-title">ECMAScript 5 Changes</p>
<p class="last">Starting with ECMAScript 5 the behavior of literals changed.  Now they
are not constructed with the constructor of <tt class="docutils literal"><span class="pre">Array</span></tt> and others, but
with the builtin constructor of <tt class="docutils literal"><span class="pre">Array</span></tt> which closes this particular
attack vector.</p>
</div>
<p>JSON itself is a high-level serialization format, so there is barely
anything that could cause security problems, right?  You can&#8217;t declare
recursive structures that could cause problems and the only thing that
could possibly break are very large responses that can cause some kind of
denial of service at the receiver&#8217;s side.</p>
<p>However there is a catch.  Due to how browsers work the CSRF issue comes
up with JSON unfortunately.  Fortunately there is also a weird part of the
JavaScript specification that can be used to solve that problem easily and
Flask is kinda doing that for you by preventing you from doing dangerous
stuff.  Unfortunately that protection is only there for
<a class="reference internal" href="api.html#flask.jsonify" title="flask.jsonify"><tt class="xref py py-func docutils literal"><span class="pre">jsonify()</span></tt></a> so you are still at risk when using other ways to
generate JSON.</p>
<p>So what is the issue and how to avoid it?  The problem are arrays at
top-level in JSON.  Imagine you send the following data out in a JSON
request.  Say that&#8217;s exporting the names and email addresses of all your
friends for a part of the user interface that is written in JavaScript.
Not very uncommon:</p>
<div class="highlight-javascript"><div class="highlight"><pre><span class="p">[</span>
    <span class="p">{</span><span class="s2">&quot;username&quot;</span><span class="o">:</span> <span class="s2">&quot;admin&quot;</span><span class="p">,</span>
     <span class="s2">&quot;email&quot;</span><span class="o">:</span> <span class="s2">&quot;admin@localhost&quot;</span><span class="p">}</span>
<span class="p">]</span>
</pre></div>
</div>
<p>And it is doing that of course only as long as you are logged in and only
for you.  And it is doing that for all <cite>GET</cite> requests to a certain URL,
say the URL for that request is
<tt class="docutils literal"><span class="pre">http://example.com/api/get_friends.json</span></tt>.</p>
<p>So now what happens if a clever hacker is embedding this to his website
and social engineers a victim to visiting his site:</p>
<div class="highlight-html"><div class="highlight"><pre><span class="nt">&lt;script </span><span class="na">type=</span><span class="s">text/javascript</span><span class="nt">&gt;</span>
<span class="kd">var</span> <span class="nx">captured</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">var</span> <span class="nx">oldArray</span> <span class="o">=</span> <span class="nb">Array</span><span class="p">;</span>
<span class="kd">function</span> <span class="nb">Array</span><span class="p">()</span> <span class="p">{</span>
  <span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">this</span><span class="p">,</span> <span class="nx">id</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">capture</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
    <span class="nx">obj</span><span class="p">.</span><span class="nx">__defineSetter__</span><span class="p">(</span><span class="nx">id</span><span class="o">++</span><span class="p">,</span> <span class="nx">capture</span><span class="p">);</span>
    <span class="k">if</span> <span class="p">(</span><span class="nx">value</span><span class="p">)</span>
      <span class="nx">captured</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">value</span><span class="p">);</span>
  <span class="p">};</span>
  <span class="nx">capture</span><span class="p">();</span>
<span class="p">}</span>
<span class="nt">&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">type=</span><span class="s">text/javascript</span>
  <span class="na">src=</span><span class="s">http://example.com/api/get_friends.json</span><span class="nt">&gt;&lt;/script&gt;</span>
<span class="nt">&lt;script </span><span class="na">type=</span><span class="s">text/javascript</span><span class="nt">&gt;</span>
<span class="nb">Array</span> <span class="o">=</span> <span class="nx">oldArray</span><span class="p">;</span>
<span class="c1">// now we have all the data in the captured array.</span>
<span class="nt">&lt;/script&gt;</span>
</pre></div>
</div>
<p>If you know a bit of JavaScript internals you might know that it&#8217;s
possible to patch constructors and register callbacks for setters.  An
attacker can use this (like above) to get all the data you exported in
your JSON file.  The browser will totally ignore the <tt class="docutils literal"><span class="pre">application/json</span></tt>
mimetype if <tt class="docutils literal"><span class="pre">text/javascript</span></tt> is defined as content type in the script
tag and evaluate that as JavaScript.  Because top-level array elements are
allowed (albeit useless) and we hooked in our own constructor, after that
page loaded the data from the JSON response is in the <cite>captured</cite> array.</p>
<p>Because it is a syntax error in JavaScript to have an object literal
(<tt class="docutils literal"><span class="pre">{...}</span></tt>) toplevel an attacker could not just do a request to an
external URL with the script tag to load up the data.  So what Flask does
is to only allow objects as toplevel elements when using
<a class="reference internal" href="api.html#flask.jsonify" title="flask.jsonify"><tt class="xref py py-func docutils literal"><span class="pre">jsonify()</span></tt></a>.  Make sure to do the same when using an ordinary
JSON generate function.</p>
</div>
</div>


          </div>
        </div>
      </div>
      <div class="sphinxsidebar">
        <div class="sphinxsidebarwrapper"><p class="logo"><a href="index.html">
  <img class="logo" src="_static/flask.png" alt="Logo"/>
</a></p>
  <h3><a href="index.html">Table Of Contents</a></h3>
  <ul>
<li><a class="reference internal" href="#">Security Considerations</a><ul>
<li><a class="reference internal" href="#cross-site-scripting-xss">Cross-Site Scripting (XSS)</a></li>
<li><a class="reference internal" href="#cross-site-request-forgery-csrf">Cross-Site Request Forgery (CSRF)</a></li>
<li><a class="reference internal" href="#json-security">JSON Security</a></li>
</ul>
</li>
</ul>
<h3>Related Topics</h3>
<ul>
  <li><a href="index.html">Documentation overview</a><ul>
      <li>Previous: <a href="htmlfaq.html" title="previous chapter">HTML/XHTML FAQ</a></li>
      <li>Next: <a href="unicode.html" title="next chapter">Unicode in Flask</a></li>
  </ul></li>
</ul>
  <h3>This Page</h3>
  <ul class="this-page-menu">
    <li><a href="_sources/security.txt"
           rel="nofollow">Show Source</a></li>
  </ul>
<div id="searchbox" style="display: none">
  <h3>Quick search</h3>
    <form class="search" action="search.html" method="get">
      <input type="text" name="q" />
      <input type="submit" value="Go" />
      <input type="hidden" name="check_keywords" value="yes" />
      <input type="hidden" name="area" value="default" />
    </form>
    <p class="searchtip" style="font-size: 90%">
    Enter search terms or a module, class or function name.
    </p>
</div>
<script type="text/javascript">$('#searchbox').show(0);</script>
        </div>
      </div>
      <div class="clearer"></div>
    </div>
    <div class="footer">
      &copy; Copyright 2010, Armin Ronacher.
      Created using <a href="http://sphinx.pocoo.org/">Sphinx</a>.
    </div>
  </body>
</html>