Skip to content
Snippets Groups Projects
Commit 5eda4a21 authored by Seamus Lee's avatar Seamus Lee Committed by Sean Madsen
Browse files

WIP intiial commit on security related documentation

parent f98184ca
No related branches found
No related tags found
No related merge requests found
# Access Control in CiviCRM
## Introduction
CiviCRM has a system of ACLs which are done in the effort to allow end users to customise which groups of their users are able to see what contacts within the organisation. The Access Control Lists (ACL) also allows Administrators of sites. ACLs work alongside the system of permissions set out by CiviCRM which is intergrated in the Content Management System's Permissions strtucure.
## Context
Access Control is used to control access to CiviCRM data and functionality. This is done through Access Control Lists (ACL's). An ACL consists of:
1. A Role that has permission to do this operation ('Administrator', 'Team Leader'),
2. An Operation (e.g. 'View' or 'Edit'), and
3. A set of Data that the operation can be performed on (e.g. a group of contacts)
Example there maybe a role called "Team Leaders" that can "Edit" all the contacts within the "Active Volunteers Group"
## Within Code
Much of the ACL control process happens within the `CRM/ACL/Api.php` file and `CRM/ACL/BAO/Acl.php` file. These files demonstrates how the ACL is used to add cluases to the WHERE statement of queries that are generated within CiviCRM. Many of these functions will be called from within the relevant CMS system files in `CRM/Utils/System/xxx.php` where xxx is the UF name of your CMS. e.g. Drupal 7 is Drupal, Drupal 8 is Drupal8 etc. These functions are usually checked at run time and are very low level down.
## Extending ACLs
There are a few ACL hooks that allow developers in their extension to extend the implementation of various ACLs for their own purposes.
- `hook_civicrm_aclGroup` This hook aims to alter what entities e.g. CiviCRM Groups, CiviCRM Events etc that an end user is able to see [See hook documentation](/hooks/hook_civicrm_aclGroup/) for more information on the hook.
- `hook_civicrm_aclWhereClause`, The purpose of this hook is as it is mentioned adds on extra SQL statements when the ACL contact cache table is to be filled up. Depending on how frequently your ACL cache is cleared this may become taxining on your database see also [hook documentation](/hooks/hook_civicrm_aclWhereClause/).
- `hook_civicrm_selectWherClause` This hook is very new only introduced within 4.7. THe purpose of this is to allow you to add specific restrictions or remove restrictions when querying specific entities. This is differnt to `hook_civicrm_aclWhereClause` because that only deals with contacts and limiting of contacts and also `hook_civicrm_selectWhereClause` is run every time a select query for that entity is run see also [hook documentation](/hooks/hook_civicrm_selectWhereClause/).
It should be noted that especially with `hook_civicrm_selectWhereClause` there is not a whole lot of CiviCRM Core test coverage on these items so its always very important that end users test their own ACLs when testing any upgrade to CiviCRM.
#Secure Coding
## Introduction
This chapter will look at how developers interact with the the permissions and access control framework that is contained within CiviCRM its self. Also looks at how you can secure CiviCRM through reporting any vulerabilities you come across. This chapter will be primarily focusing on CiviCRM Core over any specific extension situation.
# Permissions Framework in CiviCRM
## Introcution
CiviCRM has a number of permissions that are able to be set through the relevant permissions page of your Content Management System. These are the primary way CiviCRM controls what parts of CiviCRM users are able to see. E.g. Accessing the Scheduled Reminders screen in CiviCRM requires the permission of Administer CiviCRM at least. Permissions are also there to control access to various entities such as contacts. There are generally 2 permissions `Access All Contacts` and `Edit All Contacts` These give the users that are granted those permissions the access to See and possibly edit all the contacts metioned.
## Key Permissions
As mentioned in the introduction there are some crucial permissions to get heads around
- `Administer CiviCRM` - This is a very broad permisison and generally speaking is designed to grant access to any administrative parts of CiviCRM
- `Edit All Contacts`, `View All Contacts` - This grants access to all contacts within the database for editing purposes
- `Access All Customdata` - This grants the user access to view and edit all the custom data in the system.
- `Access n` - These permissions are for each core module e.g. CiviContribute CiviEvent. Where N will be the title of that module. These permissions grant access to those areas of CiviCRM. These permissions will only show up if the modules are enabled.
## Implementing Permissions logic
When in an extension you create a page or form there will be an XML routing file that will be needed to register your path, within the xml document you can put in a key of `access_arguments` This allows developers to specify what should be the default permissions that are needed to access this url. It should be noted if you want to specify an or contition e.g. Administer CiviCRM or Access CiviEvent you need to put it as ```xml<access_arguments>Administer CiviCRM;Access CiviEvent</access_arguments>```. If you want to do an And i.e. the user needs both permissions you should change the ; for a , in that example.
The other form of permissions implementation happens within generally speaking run functions of pages as normally pages have linked to the various forms and the links list is controlled on permissions. The main way this is done is by looking at the function `getIdAndAction` in `CRM\Core\Page\Basic.php` This determines what action e.g. Update, Browse, Delete etc and checks if the user has permission do to that Action.
Another function that does similar work but is more useful is `CRM_Core_Permission::checkActionPermission` This generally gets used in BAO functions when perparing list of links.
When developers are writing code it is useful to use `CRM_Core_Permission::check` to see if the user holds the required permissions.
## API Permissions
Depending on how the API is called it is either called with a "check_permissions" flag turned off or turned on. When it is turned off, It will run the API without checking if the user has the necessary permissions to perform the action needed. If you turn check_permissions on then there will be tests done. By default code in CLI tools e.g. drush or WP-cli or within core code or extension code that is done at run time, the default in CiviCRM APIv3 is that the check_permissions flag is turned off. If you call the CiviCRM API through the rest interface then by default the check_permissions flag will be turned on. The permissions need to make various API calls are defined in `CRM_Core_Permission::getEntityActionPermissions()`
## Extending Permissions
If developers want to add a permission to the list in their CMS, developers can implement `hook_civicrm_permission` This allows developers to specifiy new permissions that would then be avaliable to then select within the content management system permissions. See the [hook documentation](/hooks/hook_civicrm_permission/) for more information and example implementation.
## Altering API Permissions
If a developer wants to alter the permissions that are used in the API permissions check to alter what permissions are needed. Developers can implement the `hook_civicrm_alterAPIPermissions` this will alter permissions. See the [hook documentation](/hooks/hook_civicrm_alterAPIPermissions/) for examples. It should be important to note that developers should be very careful when altering any permissions as they may have unintended consequences.
# Reporting a Security Vulnerability
## Introduction
CiviCRM Core team and the CiviCRM Security Team are responsible for fixing reported security issues within supported CiviCRM versions. Security released will only be made for those versions with active CiviCRM support. Security Advisories will be made avaliable at the same time as the release of the fix version.
## Supported Release Versions
As of August 2017, CiviCRM maintains two supported CiviCRM Versions 4.7.x series and the 4.6.x series. 4.6.x is in Long Term Support with new features and more active development going into the 4.7.x series.
## Release Timing.
CiviCRM maintains two Security release windows, they are the first and third Wednesday of every month US/PDT Timezone. Having a release window doesn't mean that a release will occur but it does allow for site administrators to be concious of when there may be a security update.
## Reporting a Security bug
CiviCRM maitnains an email address `security@civicrm.org` which is at present the primary mechanism for reporting security issues. When you do report an issue please include all possible information that would help the Security Team replicate and help solve the issue. You will be credited with reporting the issue unless you request anonymity and also for any part you take in its resolution.
## Security Policy
CiviCRM Has a publicly avaliable policy which details these points and goes into some further detail around our Security practices. The policy is avaliable on the [CiviCRM Website](https://civicrm.org/security).
# Secure Coding Standards
## Introduction
CiviCRM maintains a number of standard practices which help ensure that CiviCRM is as secure as possible. This chapter will aim to help give developers guidance on the best way to write code for CiviCRM core and Extensions etc in a secure way.
## Escape on Input v Escape on Output.
Escaping on input means that developers ensure that every single input from their Interface(s) are properly escaped before passing them into the database. This has a major issue for an application like CiviCRM because there are too many various interfaces to try and do proper escape on Input. There is also a risk that when you escape on input you can dramatically change the value and strip out some data through the escaping process. Where as escaping on output means you have to cover all your various interfaces, ensure that all of them properly and safely account for the possibility that there maybe unsafe data in your database and sanitise it for safe viewing.
CiviCRM has long been confused and staggered in regards to whether to escape on output or escape on input. CiviCRM are slowly moving towards escaping on output for most purposes however there is still a need for escaping on input when dealing with writing queries against the database.. At present the simplest way to escape on output is to use inbuilt escape functions within our templating engine Smarty.
e.g. ```
<li class="crm-recently-viewed" ><a href="{$item.url}" title="{$item.title|escape:'html'}">
```
This will ensure that the variable title within the item key when generating a list of recently viewed items won't have any Cross Site Scripting as it will be escaped for use within HTML. For more infomration on the types of escaping you can do with Smarty see the [Smarty Documentation](https://www.smarty.net/docsv2/en/language.modifier.escape)
However sometimes to escape on output you need to ensure that because of the complex nature of the variable that the variable is properly escaped when passed to smarty e.g. When building a json encoded blob of data for use in an contribution form it was necessary to escape before passing onto the Smarty Template.
```php
$form->assign('submittedOnBehalfInfo', json_encode(str_replace('"', '\"', $form->_submitValues['onbehalf']), JSON_HEX_APOS));
```
For Angular templates, Developers should consult the Angular [$sanitize documentation](https://docs.angularjs.org/api/ngSanitize/service/$sanitize)
## Handling Request variables
Through the CiviCRM code base you will find that there are a number of times where CiviCRM takes variables passed to it through the URL e.g. ?cid=xxx or ?id=xx. CiviCRM has put in place some inbuilt functions that help to ensure that no dangerous values are able to be passed through
```php
$cid = CRM_Utils_Request::retrieve('cid', 'Positive', $this);
$id = CRM_Utils_Request::retrieve('id', 'Positive', $this, FALSE, NULL, 'GET');
$angPage = CRM_Utils_Request::retrieve('angPage', 'String', $this);
if (!preg_match(':^[a-zA-Z0-9\-_/]+$:', $angPage)) {
CRM_Core_Error::fatal('Malformed return URL');
}
$backUrl = CRM_Utils_System::url('civicrm/a/#/' . $angPage);
```
What you will notice above is that one of the key things there is the usuage of `CRM_Utils_Request::retrieve` This function takes in whatever request variables have been passed to the page or form etc, gets the key requested out of it, then ensures that it meets a specific type of value. The Types permissiable can be found in [CRM_Utils_Type::validate](https://github.com/civicrm/civicrm-core/blob/60050425316acb3726305d1c34908074cde124c7/CRM/Utils/Type.php#L378).
## Passing variables into SQL
Developers should ensure that whenever they pass variables into SQL statements that they do it in the proper standard. More information can be found in the [SQL Coding Standards](/standards/sql/).
## References
- Escape on Input v Escape on output [Stack exchange](https://security.stackexchange.com/questions/95325/input-sanitization-vs-output-sanitization) [Stack Overflow)[https://stackoverflow.com/questions/11253532/html-xss-escape-on-input-vs-output].
......@@ -84,6 +84,11 @@ pages:
# CiviMail: /reference/civimail.md
# CiviReport: /reference/civireport.md
# Payment Processing: /reference/payment.md
- Secure Coding:
- Introduction: secure/index.md
- Acess Control: secure/access.md
- Permissions: secure/permissions.md
- Reporting a Security Vulnerability: secure/reporting.md
- API:
- APIv3 Intro: api/index.md
- APIv3 Usage: api/usage.md
......@@ -225,6 +230,8 @@ pages:
- PHP Standards: standards/php.md
- SQL Standards: standards/sql.md
- Javascript Reference: standards/javascript.md
- Secure Coding: standards/secure.md
# Javascript: standards/js.md
# API: standards/api.md
# Git: standards/git.md
- Documentation:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment