Table of contents
General Coding Guidelines
The main security risks Tiki developers must avoid are:
- injections (in particular in SQL queries)
- cross-site scripting
- lack of access control
- Cross-Site Request Forgery (CSRF) attacks
- vulnerabilities from bundled libraries
Avoid using $_REQUEST
Only when both $_GET and $_POST variables are expected should $_REQUEST be used. Post variables are not accessible to a number of attacks, so if there is no reason to accept $_GET, don't.
Adding data manipulations (preventing CSRF)
This section needs to be written.
under what conditions a check needs to be made. Basic implementation of ticket and referrer check.
Displaying data (preventing XSS)
The primary defense against XSS is to ensure data from users is always output properly quoted and escaped.
Data output by Smarty templates can be escaped using the Smarty escape modifier. Tiki's escape modifier is based on Smarty's built-in escape modifier. This modifier takes an optional argument to define the context where the data occurs.
More rarely, data is formatted in PHP code. In this case, PHP's htmlspecialchars() built-in function can be used. It is also possible to use the Smarty escape modifier by calling smarty_modifier_escape(); for example:
$javaScriptEscapedTitle = smarty_modifier_escape($title, 'javascript');
This section needs to be completed.
XSS Filtering
Every file that can run directly (most notably the files that begin with tiki-) needs to have a $inputConfiguration declaration before tiki-setup.php is called. Each $_POST and $_GET variable should be filtered here to prevent XSS attacks. It's a tiki policy to filter every variable even if the code does not permit an XSS attack for two reasons:
- Code modification in the future may open security issues.
- It allows auditing of variables in the future, to double check the page is XSS-proof.
Note that 'staticKeyFilters' will not work with array content, they must be placed in 'staticKeyFiltersForArrays'.
It is highly encouraged that each page also unsets all variables not filtered through $inputConfiguration. This is done by setting 'catchAllUnset' to null. This practice helps us audit pages for XSS protection and prevents accidental omission of variables. If it's not possible to unset the remaining variables, a comment should be left as to the reason why so efforts are not duplicated in securing the page.
A list of available filters and what they do may be seen here: lib/core/TikiFilter.php. In general, the best practice is to choose the filter that imposes the most strict conditions that will work in a given situation. The 'xss' and lastly 'none' filters should only ever be used if no other options are available.
You can read more about filtering in tiki here: Filtering Best Practices
Below is a code example that shows how variables may be filtered on a page that uses the variables: send, priority, from & taffyArray:
$inputConfiguration = [[ 'staticKeyFilters' => [ 'send' => 'word', 'priority' => 'int', 'from' => 'striptags', ], 'staticKeyFiltersForArrays' => [ 'taffyArray' => 'digits', ], 'catchAllUnset' => null ]];
Adding a File
Feature & Permission Checks
Every file that can be run directly (most notably the files that begin with tiki-) should begin with limiting access to that file based on the user's permissions and also features enabled in tiki. If it's a feature that is always on and has no special user privileges to access, then these checks are not needed.
The following code is how tiki-calendar_import.php implements these checks:
$access->check_feature('feature_calendar'); $access->check_permission('tiki_p_admin_calendar');
Direct Access Check
Any file that is not simply a library (a file filled with a single class), and is not intended to be called directly should prevent direct access to the file with the following code:
if (basename($_SERVER['SCRIPT_NAME']) === basename(__FILE__)) { die('This script may only be included.'); }
Command Line Interface (CLI) Checks
Any file that is intended to be run from the command line only should restrict access to CLI only with the following code:
if (isset($_SERVER['REQUEST_METHOD'])) { die('Only available through command-line.'); }
Adding a Directory
Prevent Directory Browsing
It's a convention in tiki to prevent directory browsing. The security gains may be negligible in many instances, but perhaps critical in a few. In any new directory simply drop a blank file titled: index.php into it. This prevents directory browsing under most server conditions.
Whitelisting File Types
If your directory is in the root folder, you will need to add a .htaccess file that whitelists file types that may be directly called by a browser. All subfolders take their rules from the parent folder so therefore do not need a new .htaccess. Below is an example of a .htaccess file that prevents access to all files except images, note that these files may still be read and accessed by PHP, through an include statement or otherwise:
<FilesMatch ".*"> <IfModule mod_authz_core.c> Require all denied </IfModule> <IfModule !mod_authz_core.c> order deny,allow deny from all </IfModule> </FilesMatch> <FilesMatch "\.(jpe?g|png|svg|gif)$"> <IfModule mod_authz_core.c> Require all granted </IfModule> <IfModule !mod_authz_core.c> Allow from all </IfModule> </FilesMatch> # -- Prevent Directory Browsing -- # Options -Indexes
Adding a Third-Party Library
Remove unnecessary files
Some standard directories and files are removed in CleanVendors such as demo, docs and test etc, but other default files, especially PHP and some HTML ones, need to be removed specifically there. The clean
function is run after composer update and install so the developer needs to make sure no problematic example files remain in vendors_bundled
and add the code to remove any leftovers if necessary.
Whitelisting files accessed by browsers
Sometimes possibly dangerous files need to be included in a library for it to work, so vendor_bundled/.htaccess
prevents anything apart from images, JavaScript and CSS to be accessed from the browser. Any exceptions to this should be added to this .htaccess file. This is unusual, however.