blob: d4120d162668eed642ce3eee5cf9d6fa5674148e [file] [log] [blame]
Derek Jones8ede1a22011-10-05 13:34:52 -05001########
2Security
3########
4
5This page describes some "best practices" regarding web security, and
6details CodeIgniter's internal security features.
7
8URI Security
9============
10
11CodeIgniter is fairly restrictive regarding which characters it allows
12in your URI strings in order to help minimize the possibility that
13malicious data can be passed to your application. URIs may only contain
14the following:
15
Andrey Andreev16a704c2012-11-09 17:25:00 +020016- Alpha-numeric text (latin characters only)
Derek Jones8ede1a22011-10-05 13:34:52 -050017- Tilde: ~
vlakoff4ad37082013-03-29 18:14:22 +010018- Percent sign: %
Derek Jones8ede1a22011-10-05 13:34:52 -050019- Period: .
20- Colon: :
21- Underscore: \_
22- Dash: -
vlakoff4ad37082013-03-29 18:14:22 +010023- Space
Derek Jones8ede1a22011-10-05 13:34:52 -050024
25Register_globals
Andrey Andreev1c6522c2015-01-21 23:12:13 +020026================
Derek Jones8ede1a22011-10-05 13:34:52 -050027
Andrey Andreev1c6522c2015-01-21 23:12:13 +020028During system initialization all global variables that are found to exist
29in the ``$_GET``, ``$_POST``, ``$_REQUEST`` and ``$_COOKIE`` are unset.
30
31The unsetting routine is effectively the same as *register_globals = off*.
Derek Jones8ede1a22011-10-05 13:34:52 -050032
Andrey Andreev16a704c2012-11-09 17:25:00 +020033display_errors
34==============
Derek Jones8ede1a22011-10-05 13:34:52 -050035
Andrey Andreev16a704c2012-11-09 17:25:00 +020036In production environments, it is typically desirable to "disable" PHP's
37error reporting by setting the internal *display_errors* flag to a value
Derek Jones8ede1a22011-10-05 13:34:52 -050038of 0. This disables native PHP errors from being rendered as output,
39which may potentially contain sensitive information.
40
purwandi89f6f1a2011-10-07 19:58:22 +070041Setting CodeIgniter's **ENVIRONMENT** constant in index.php to a value of
42**\'production\'** will turn off these errors. In development mode, it is
Derek Jones8ede1a22011-10-05 13:34:52 -050043recommended that a value of 'development' is used. More information
Andrey Andreev16a704c2012-11-09 17:25:00 +020044about differentiating between environments can be found on the
45:doc:`Handling Environments <environments>` page.
Derek Jones8ede1a22011-10-05 13:34:52 -050046
47magic_quotes_runtime
Andrey Andreev16a704c2012-11-09 17:25:00 +020048====================
Derek Jones8ede1a22011-10-05 13:34:52 -050049
Andrey Andreev16a704c2012-11-09 17:25:00 +020050The *magic_quotes_runtime* directive is turned off during system
Derek Jones8ede1a22011-10-05 13:34:52 -050051initialization so that you don't have to remove slashes when retrieving
52data from your database.
53
54**************
55Best Practices
56**************
57
58Before accepting any data into your application, whether it be POST data
59from a form submission, COOKIE data, URI data, XML-RPC data, or even
60data from the SERVER array, you are encouraged to practice this three
61step approach:
62
Derek Jones8ede1a22011-10-05 13:34:52 -050063#. Validate the data to ensure it conforms to the correct type, length,
Aaron Melocikdd6222b2015-06-18 08:40:43 -070064 size, etc.
Andrey Andreev1c6522c2015-01-21 23:12:13 +020065#. Filter the data as if it were tainted.
66#. Escape the data before submitting it into your database or outputting
67 it to a browser.
Derek Jones8ede1a22011-10-05 13:34:52 -050068
Andrey Andreev1c6522c2015-01-21 23:12:13 +020069CodeIgniter provides the following functions and tips to assist you
70in this process:
Derek Jones8ede1a22011-10-05 13:34:52 -050071
72XSS Filtering
73=============
74
75CodeIgniter comes with a Cross Site Scripting filter. This filter
Andrey Andreev16a704c2012-11-09 17:25:00 +020076looks for commonly used techniques to embed malicious JavaScript into
Derek Jones8ede1a22011-10-05 13:34:52 -050077your data, or other types of code that attempt to hijack cookies or
78do other malicious things. The XSS Filter is described
79:doc:`here <../libraries/security>`.
80
Andrey Andreev1c6522c2015-01-21 23:12:13 +020081.. note:: XSS filtering should *only be performed on output*. Filtering
82 input data may modify the data in undesirable ways, including
83 stripping special characters from passwords, which reduces
84 security instead of improving it.
85
86CSRF protection
87===============
88
89CSRF stands for Cross-Site Request Forgery, which is the process of an
90attacker tricking their victim into unknowingly submitting a request.
91
92CodeIgniter provides CSRF protection out of the box, which will get
93automatically triggered for every non-GET HTTP request, but also needs
94you to create your submit forms in a certain way. This is explained in
95the :doc:`Security Library <../libraries/security>` documentation.
96
97Password handling
Derek Jones8ede1a22011-10-05 13:34:52 -050098=================
99
Andrey Andreev1c6522c2015-01-21 23:12:13 +0200100It is *critical* that you handle passwords in your application properly.
101
102Unfortunately, many developers don't know how to do that, and the web is
103full of outdated or otherwise wrongful advices, which doesn't help.
104
105We would like to give you a list of combined do's and don'ts to help you
106with that. Please read below.
107
108- DO NOT store passwords in plain-text format.
109
110 Always **hash** your passwords.
111
112- DO NOT use Base64 or similar encoding for storing passwords.
113
114 This is as good as storing them in plain-text. Really. Do **hashing**,
115 not *encoding*.
116
117 Encoding, and encryption too, are two-way processes. Passwords are
118 secrets that must only be known to their owner, and thus must work
119 only in one direction. Hashing does that - there's *no* un-hashing or
120 de-hashing, but there is decoding and decryption.
121
122- DO NOT use weak or broken hashing algorithms like MD5 or SHA1.
123
124 These algorithms are old, proven to be flawed, and not designed for
125 password hashing in the first place.
126
127 Also, DON'T invent your own algorithms.
128
129 Only use strong password hashing algorithms like BCrypt, which is used
130 in PHP's own `Password Hashing <http://php.net/password>`_ functions.
131
132 Please use them, even if you're not running PHP 5.5+, CodeIgniter
133 provides them for you as long as you're running at least PHP version
134 5.3.7 (and if you don't meet that requirement - please, upgrade).
135
Andrey Andreevf1ca8652015-02-24 20:25:16 +0200136 If you're one of the really unlucky people who can't even upgrade to a
137 more recent PHP version, use `hash_pbkdf() <http://php.net/hash_pbkdf2>`,
138 which we also provide in our compatibility layer.
139
Andrey Andreev1c6522c2015-01-21 23:12:13 +0200140- DO NOT ever display or send a password in plain-text format!
141
142 Even to the password's owner, if you need a "Forgotten password"
143 feature, just randomly generate a new, one-time (this is also important)
144 password and send that instead.
145
Andrey Andreeva8c499d2015-03-31 15:01:36 +0300146- DO NOT put unnecessary limits on your users' passwords.
Andrey Andreev1c6522c2015-01-21 23:12:13 +0200147
Andrey Andreeva8c499d2015-03-31 15:01:36 +0300148 If you're using a hashing algorithm other than BCrypt (which has a limit
149 of 72 characters), you should set a relatively high limit on password
150 lengths in order to mitigate DoS attacks - say, 1024 characters.
151
152 Other than that however, there's no point in forcing a rule that a
153 password can only be up to a number of characters, or that it can't
154 contain a certain set of special characters.
Andrey Andreev1c6522c2015-01-21 23:12:13 +0200155
156 Not only does this **reduce** security instead of improving it, but
157 there's literally no reason to do it. No technical limitations and
158 no (practical) storage constraints apply once you've hashed them, none!
159
160Validate input data
161===================
162
Andrey Andreev16a704c2012-11-09 17:25:00 +0200163CodeIgniter has a :doc:`Form Validation Library
164<../libraries/form_validation>` that assists you in
Derek Jones8ede1a22011-10-05 13:34:52 -0500165validating, filtering, and prepping your data.
166
Andrey Andreev1c6522c2015-01-21 23:12:13 +0200167Even if that doesn't work for your use case however, be sure to always
168validate and sanitize all input data. For example, if you expect a numeric
169string for an input variable, you can check for that with ``is_numeric()``
170or ``ctype_digit()``. Always try to narrow down your checks to a certain
171pattern.
172
173Have it in mind that this includes not only ``$_POST`` and ``$_GET``
174variables, but also cookies, the user-agent string and basically
175*all data that is not created directly by your own code*.
176
177
Derek Jones8ede1a22011-10-05 13:34:52 -0500178Escape all data before database insertion
179=========================================
180
181Never insert information into your database without escaping it.
Andrey Andreev16a704c2012-11-09 17:25:00 +0200182Please see the section that discusses :doc:`database queries
183<../database/queries>` for more information.
Derek Jones8ede1a22011-10-05 13:34:52 -0500184
Andrey Andreev16a704c2012-11-09 17:25:00 +0200185Hide your files
186===============
Derek Jones8ede1a22011-10-05 13:34:52 -0500187
Andrey Andreev16a704c2012-11-09 17:25:00 +0200188Another good security practice is to only leave your *index.php*
189and "assets" (e.g. .js, css and image files) under your server's
190*webroot* directory (most commonly named "htdocs/"). These are
191the only files that you would need to be accessible from the web.
192
193Allowing your visitors to see anything else would potentially
194allow them to access sensitive data, execute scripts, etc.
195
196If you're not allowed to do that, you can try using a .htaccess
197file to restrict access to those resources.
198
199CodeIgniter will have an index.html file in all of its
200directories in an attempt to hide some of this data, but have
201it in mind that this is not enough to prevent a serious
Aaron Melocikdd6222b2015-06-18 08:40:43 -0700202attacker.