偶然看到这么一篇文章,觉得不管是什么安全措施,都要在正确的场景下正确的使用,人的意识才是最大的问题~~
注意里面关于xss的那部分
I have learned that Django provides built-in protection against the three main types of web app attacks (SQL injection, XSS and CSRF), which is really awesome.
Yet I have spoken to a few Django developers and they have essentially told me not to rely on these too heavily, if at all.
They told me to treat all data as "unsafe" and handle it appropriately.
I have two questions to ask everyone about this:
- Can Django's built-in security features be relied upon?
- What do my friends mean by "handle it (unsafe data) appropriately"? I know its about escaping and/or removing unsafe phrases and/or characters, but my biggest fear is that if I try to do that myself I will end up producing a "filter" that is worse off than Django's built in stuff. Does anyone have any guides for building on top of Django and not overriding it, in this regard?
SQL injection. If you use Django's object-relational mapper (ORM) layer, you are basically protected from SQL injection.
The only caveat is that you need to avoid manually forming SQL queries using string concatenation. For instance, do not use raw SQL queries (e.g.,
raw()
). Similarly, do not use theextra()
method/modifier to inject raw SQL. Do not execute custom SQL directly; if you bypass Django's ORM layer, you bypass its protections against SQL injection.CSRF. Django's built-in CSRF protection is good. Make sure you enable it and use it everywhere. Django provides ways to disable it locally or globally; obviously, don't do that.
It is important that you make sure that GET requests do not have any side effects. For requests which can have a side-effect, make sure you use a POST request (and do not accept a GET request for those). This is standard web design, but some developers screw it up; Django's built-in CSRF prevention assumes you get this right.
There are some caveats if you have subdomains (e.g., your web app is hosted on
www.example.com
and there is a subdomainalice.example.com
that hosts user-controlled content); the built-in CSRF protection might not be sufficient in that case. That's a tricky case for a number of reasons. Most web applications won't have to worry about these caveats.XSS. If you use Django's template system and make sure that auto-escaping is enabled, you're 95% of the way there. Django provides an auto-escaping mechanism for stopping XSS: it'll automatically escape data that's dynamically inserted into the template, if it hasn't already been escaping (see e.g.,
mark_safe
,safe
, etc.). This mechanism is good stuff, but it is not quite enough on its own. It takes you much of the way to stopping XSS, but you still have to be aware of some issues.In particular, Django's auto-escaping will escape data sufficiently for most HTML contexts, but in some special cases you must manually do additional escaping:
-
Make sure you quote all attributes where dynamic data is inserted. Good:
<img alt="{{foo}}" ...>
. Bad:<img alt={{foo}} ...>
. Django's auto-escaping isn't sufficient for unquoted attribute values. -
For data inserted into CSS (
style
tags and attributes) or Javascript (script
blocks, event handlers, andonclick
/etc. attributes), you must manually escape the data using escaping rules that are appropriate for CSS or Javascript. -
For data inserted into an attribute where a URL is expected (e.g.,
a href
,img src
), you must manually validate the URL to make sure it is safe. You need to check the protocol against a whitelist of allowed protocols (e.g.,http:
,https:
,mailto:
,ftp:
, etc. -- but definitely notjavascript:
). -
For data inserted inside a comment, you have to do something extra to escape
-
s. Actually, better yet, just don't insert dynamic data inside a HTML comment; that's an obscure corner of HTML that's just asking for subtle problems. (Similarly, don't insert dynamic data into attributes where it is crazy for user input to appear (e.g.,foo class=...
).) -
You still must avoid client-side XSS (also known as DOM-based XSS) separately; Django doesn't help you with this. YOu could read Adam Barth's advice on avoiding XSS for some guidelines that will help you avoid client-side XSS.
-
If you use
mark_safe
to manually tell that Django that some data has already been escaped and is safe, you'd better know what you're doing, and it really better be safe. It's easy to make mistakes here if you don't know what you are doing. For example, if you generate HTML programmatically, store it into the database, and later send it back to the client (unescaped, obviously), it's very easy to make mistakes; you're on your own, and the auto-escaping won't help you.
The reason why you have to do something extra for these cases is that Django's auto-escaping functionality uses an escaping function that is supposed to be one-size-fits-all, but in practice, one size doesn't always fit in every case; in some cases, you need to do something extra on your own.
For more information about what escaping rules to use in these special contexts, see the OWASP XSS cheatsheet.
Other stuff. There are some other things you didn't mention:
-
I recommend using SSL sitewide, if possible, and in that case enabling HSTS and marking all cookies with the 'secure' flag. Search this site for details on the tradeoffs of doing so. If you want to do so, Django provides support for this, and there are some resources on this site as well: Trying to make a Django-based site use HTTPS-only, not sure if it's secure?
-
I recommend enabling Django's clickjacking protection.
-
You could check out django-secure for some utilities to help you avoid forgetting some basic security steps, particularly if you are using SSL.
-
All of this good stuff is not a panacea. It doesn't mean you can ignore security from here on. It'll help you avoid some of the most common mistakes, but you still bear the ultimate responsibility for building a secure web application.
For more information. See Django's documentation on security, including the chapter on security in the Django book.
-
http://security.stackexchange.com/questions/27805/is-djangos-built-in-security-enough