25th April 2006
Amended 1st January 2023
Compliance with various security requirements is essential if an application is to be taken seriously by prospective clients. Having no security at all can lead to delicate information falling into the wrong hands, or allowing delicate information to be modified or destroyed by unauthorised personnel. On the other hand, too much security can prevent an authorised person from completing a legitimate task. Clearly some sort of balance is necessary, and each decision, whether to employ or not employ a particular security mechanism, may benefit from explanation and justification.
The purpose of this document is to identify what security features either do or do not exist within RADICORE, and to give explanations where necessary. It should be noted that RADICORE is a web application that uses the stateless HTTP protocol, which means that certain options which are available to traditional desktop applications are inapplicable.
The RADICORE system forces every user to navigate through a login screen which requires the input of a user_id (or an email address) and a password. These will be validated against the contents of the USER database table, and only if there is a match will the user be allowed to proceed. If either of these inputs is wrong a simple "security violation" message will be issued which does not identify which of the inputs was wrong.
Several different methods are available to authenticate a user's password. These are:
A user's login rights can also be restricted to a particular date range by means of a START_DATE and END_DATE on the user's profile. If the user attempts to login outside of this period then a suitable error message will be issued.
There is also provision for a user's login rights to be temporarily disabled by an administrator by setting an IS_DISABLED flag on the user's profile. All rights can be restored simply by unsetting this flag.
RADICORE provides the following methods for logging out:
Note 1: It is not possible to return the client to the logon screen until the client issues a request as the web server cannot initiate any activity on the client, it can only send a response in reply to a request from the client.
Note 2: It is not possible to force the client to send a "logout" request to the server. The client may terminate the web browser at any time without sending any notification to the server.
Note 3: It is not possible to prompt the user to save any pending changes as the web application is totally unaware of any activity on the client until the client issues a request.
It may be a requirement in some systems to ensure that the same user is not logged in from multiple locations, and for a second login to automatically cancel an earlier session, but that is not implemented in RADICORE. Special facilities have been built into RADICORE to allow a user to open multiple sessions on the same client as this is a legitimate method of working. It is only possible to limit these multiple sessions to the same device provided that the device has a static IP address. See Restrict access to authorised devices for details.
It may be a requirement in some systems to ensure that the system does not crash because of too many users, but that is not practical in a web application:
It may be a requirement in some systems to record the start time, end time and duration of each user session, but as a session can end without the server receiving a "logout" request this is not completely practicable. However, all login attempts, whether successful or unsuccessful, are logged, and all logout requests, when received, are also logged.
In those cases where a user has already passed through a logon process on their PC it may be inconvenient to have to pass through an additional logon screen in order to gain access to the RADICORE application. This SSO option will bypass the need for the user to enter their credentials again by reusing those which were supplied when logging in to some other software.
This option is currently available under the following conditions:
This will enable a link to the application to appear among those displayed on the https://myapplications.microsoft.com/ page. By activating this link the RADICORE logon screen will automatically use the same credentials without asking for them again.
Although RADICORE forces each user to have a unique identity, it does not force each user to have a unique password. This is because each user password is encrypted with a different key, which means that it would not be possible to perform a lookup on a particular password without first decrypting all the existing passwords. Besides, what benefit comes from having unique passwords? A password on its own is nothing, it is only the combination of user_id and password that has any significance, and not every password is valid with every user_id.
When changing their passwords, users must retype them in order to confirm them in order to avoid spelling mistakes or typing errors which would render their passwords as ineffective. Any mismatches must be cleared before a password change can be put into effect.
The system must allow passwords to contain both letters and numbers, and to distinguish between upper case and lower case.
RADICORE allows the system administrator to define a valid format for new passwords by means of the following specifications:
These alphanumeric characters can appear in any order as it is only their number which is checked.
These formatting rules are enforced only when passwords are being changed, not when being entered in the login screen.
It must be possible for a system administrator to define a minimum length for new passwords. This can be anywhere between 4 characters and the maximum size (which can be set to a value between 16 and 40 characters). This rule is enforced only when passwords are being changed, not when being entered in the login screen. Any password which has already been stored in the database is deemed to be valid as it must have passed the validation rules which were in effect when it was created.
To help protect against denial of service attacks the system must have some sort of lock-out mechanism after a predefined number of failed login attempts. RADICORE has the following features:
RADICORE provides the option of storing passwords either internally or externally according to the Authentication method.
This process could also be used to encrypt sensitive data in the database as the decryption process would only be available to authorised users.
Both of these methods require a key (or salt) to aid in the encryption process, and the method used to construct this key can be varied using the Key Format variable. Passwords are also subject to Passwords Format Rules and Password Length.
When checking the password on the LOGON screen the system must encrypt the input password instead of decrypting the actual password so that a plain-text version of the password is never passed over the network.
Having a reversible (two-way) encryption process means that the settings (algorithm or key) can be changed at any time without losing the current password values as known by the users. Simply decrypt all passwords, change the settings, then encrypt all the passwords again using the new settings.
When any of these options are chosen the user_password held in the database is ignored.
The system must ensure that the password that a user types into the login screen is encrypted before being transmitted over the network. This will ensure that an eavesdropper does not have access to a plain text version of any password.
RADICORE achieves this by ensuring that each screen which requires the user to enter a password is transmitted using SSL (Secure Socket Layer) or the more modern TLS (Transport Layer Security) via the HTTPS protocol. This can be verified by seeing the characters HTTPS://
at the start of the URL, not the unsecure HTTP://
If a user forgets his/her password then there should be a method of retrieving it without requiring the intervention of an administrator.
RADICORE achieves this by supplying a "recover password" link on the login screen which will activate a form into which the user can enter his/her e-mail address. This address is used to locate the user's details in the MENU database, then the password is e-mailed to this address. The user can retrieve this message from his/her e-mail inbox and use the details to gain access to the system.
The system must allow the user to change his/her password at any time.
RADICORE achieves this in the following ways:
The system must allow the system administrator to define an interval after which the password must be changed.
RADICORE achieves this in the following ways:
It may be a requirement in some systems to remember a selected number of previous passwords for each user so that a new password for the same user is not on this list, but this facility is not available in RADICORE. Currently the only check is that the proposed password is not the same as the existing password.
It may be a requirement in some systems to check proposed passwords against a list of reserved words so that common words, or words which may be easy to guess, are not used.
RADICORE does not do this as the Formatting Rules give the system administrator the ability to define patterns which automatically eliminate common words.
User accounts can only be de-activated by a system administrator.
In RADICORE the ability to de-activate or modify user accounts is by default given only to system administrators. There are two ways in which an account can be de-activated:
Whichever method is chosen will, of course, be recorded in the system's audit log, as will any failed logon attempts.
The system has to ensure that it will be possible for customers to decide whether they want to enable/disable the auto-complete feature for user names and passwords.
This is an optional feature of the web browser and cannot be modified by the application software which runs on the server.
RADICORE does not have an auto-logon facility, therefore everyone must go though the login screen.
A system may have hundreds of users and hundreds of functions, but not all users may be allowed to access all functions. The system must therefore have some method by which a user's access to functions can be defined and limited, and all access attempts must be verified against this list.
RADICORE achieves this by having all information regarding functions, users and access control maintained in a central database. The functions to maintain the contents of this database are, by default, only accessible by a system administrator. The structure of this database is as follows:
RADICORE also employs a dynamic menu system in which all menu pages are maintained within the database. When a user selects a menu the details are retrieved from the database and compared against the ROLE-TASK table so that any functions which are not accessible by the user are automatically filtered out before the menu options are displayed.
This method therefore has two levels of functionality:
The system should also handle access control at the field level. Normally all fields are available, but there should be a facility to make certain fields either read-only or hidden for USERs of certain ROLEs.
RADICORE achieves this by allowing an administrator to define the following on the central database:
Note: This facility is not provided by any mechanism within the database as everyone shares the same database login, without which the pooling of persistent connections would not be possible. It is instead provided completely within the application. This is made easier by the fact that each HTML page is built completely from scratch each time rather than being taken from some pre-compiled definition. When building the page easy it is therefore a straightforward process to make any HTML control read-only instead of writable, or not to include it in the output at all.
It possible for the same database table(s) to hold data for several different customer accounts, but where users within an account can only access records (rows) which belong to that account. Account access can be turned on for any database table simply by adding a column called rdcaccount_id
. The features of the RADICORE implementation are:
rdcaccount_id
column has the value '1', or the table does not contain the rdcaccount_id
column).rdcaccount_id
column are shared, not private, therefore can be viewed and modified by users within any account.rdcaccount_id
column may have a mixture of shared and private data:
rdcaccount_id
column.rdcaccount_id
column.rdcaccount_id
can only access shared data.rdcaccount_id
can only access data which belongs to that account, plus any shared data.This topic is discussed in greater detail in Implementing Virtual Private Databases.
The system must have control mechanisms that prevent the accessing of functions outside the predefined access path, based on the access rights given to users. Unauthorised users must not be able to access, change or otherwise corrupt the data within the system.
RADICORE deals with this in the following ways:
The system must have provision for granting automatic access to every function within the system without having to rebuild the access control list. This facility is required for system administrators, not everyday users.
RADICORE achieves this by having a GLOBAL_ACCESS switch on the ROLE record. If this switch is turned ON then all users with this role have global access. If this switch is turned OFF then access to each function is disabled until it is specifically enabled.
It may be required to restrict system access to authorised client devices. The following options may be required:
With web applications each client device is recognised by its IP address. RADICORE implements this feature by maintaining a list of valid IP addresses for each user and each task. By default these lists are empty and this feature is turned off, but it may be turned on at any time by creating a non-empty list. Any number of IP address entries can be specified for each user and each task.
User access is checked when passing through the logon screen. Task access is checked whenever a task is requested, either through a menu button or a navigation button.
NOTE: This feature is only applicable to those devices which have static (fixed) addresses. In situations where IP addresses are assigned dynamically, such as through a DCHP server, or where they are shared or masked, such as through a proxy server, this feature will not work as expected.
It may be required to restrict system access to authorised time periods, either for individual users or all users within specified roles. It may be a requirement, for example, that a user can only access the system during normal office hours (such as 9am to 5pm, Monday to Friday), so access outside of these hours can be blocked.
Time limited access is checked at the start of each task. If there are time periods in force, and the current time is not within any of those periods, then the user will be logged off. The user will be given a warning when within 5 minutes of the period end.
Data recorded in the Audit database may never be deleted or overwritten by anybody.
The RADICORE framework has facilities to write entries to the Audit database, and to view Audit records using a standard set of online screens, but there are no facilities which allow the user to modify or delete any entries.
This security requirement may be further enhanced by making use of MySQL's ARCHIVE storage engine which has two significant features:
The system must have the capability of logging changes to all database tables, and there should also be a standard set of screens to search through and view the contents of the audit data.
The RADICORE framework comes with a ready-made AUDIT database, functions to write to the database and functions to search through and view the contents of the database. All the system administrator has to do to enable the logging of changes to any database table is to visit the Update Table screen in the Data Dictionary and turn on the "Audit Logging" switch, then export the details so that they can be used by the application.
When audit logging has been turned on for any database table this will by default include every column in that table. The logging of a particular column can be turned off by visiting the Update Column screen in the Data Dictionary and switching the "No Audit" flag to YES, then export the details so that they can be used by the application.
The following details are written to the AUDIT database and are viewable using the online screen enquiry:
Th AUDIT database used within RADICORE has a fixed structure which can deal with any number of application tables. This has the following advantages:
The system has to ensure that if there is an error during a user session that details of the error are automatically captured and made available to the system administrator. This removes the responsibility from the user who may not be aware of the procedure for reporting such incidents, or may not provide enough information.
In the RADICORE framework this is achieved by passing all errors through a standard error handler which performs the following:
errorlog.html
which can be viewed through any browser.RADICORE is a web application, which means it runs on a web server which can be accessed, via the HTTP protocol, through a web browser over the public internet, a private intranet or a semi-private extranet. Where it is deployed on an intranet or extranet only those users who have access to that network are able to access the application. If it is deployed on the internet then it is accessible to anyone with an internet connection. Anyone who can access the system could potentially attack the system in order to compromise its data. This section identifies how such attacks are addressed.
Session Fixation is an attack that permits an attacker to hijack a valid user session. The session ID which is assigned to each user's session is vulnerable to attack if the same id is used across multiple sessions. This weakness is avoided in RADICORE as it always creates a new session ID for each logon. Also, the session ID is never included in any URLs, nor as a hidden field in any forms. It is only ever held in a session cookie.
The ability to guess a session identity is lessened by the fact that as from PHP version 7.1.0 the session ID length can be set as high as 256 characters.
If the ALL option is turned on then RADICORE will automatically activate HTTP Strict Transport Security (HSTS) when processing the login screen in order to prevent the HTTPS protocol from being downgraded to plain HTTP.
A CSRF attack is one which forces an end user to execute unwanted actions on a web application in which they're currently authenticated. This is done by creating a malicious link, such as a hyperlink in an email, and getting the unsuspecting user to click on this link. There are numerous steps taken in the RADICORE framework to combat such attacks, and these are detailed separately in How Radicore prevents CSRF attacks.
An SQL injection attack consists of insertion or "injection" of an SQL query via the input data from the client to the application. The application thinks that it is executing a valid query when in fact that query has been corrupted. For example, the application takes input from a screen and inserts some of that input into a query such as as:
SELECT id, firstname, lastname FROM authors WHERE firstname = '{$GET['firstname']}' AND lastname = '{$GET['lastname']}';
If the user enters 'Fred' as firstname and 'Bloggs' as lastname this will execute the following query:
SELECT id, firstname, lastname FROM authors WHERE firstname = 'Fred' AND lastname = 'Bloggs';
The above query produces the result expected by the developer. Now suppose that a malicious user enters the value Bloggs';delete from authors;--
into the lastname field. This will result in the application executing the following:
SELECT id, firstname, lastname FROM authors WHERE firstname = 'Fred' AND lastname = 'Bloggs';delete from authors;-- ';
The use of ';
(single quote, semi-colon) is treated as a terminator for the expected query and whatever follows is another query. In the above example this will cause the entire contents of the authors table to be deleted. As well as causing damage a corrupt query can also let an attacker gain access to an application. Image a login screen which asks for a user id and a password. In order to validate these two values the application will execute the following query:
SELECT * FROM user WHERE id = '???' AND password = '???';
By corrupting the password the attacker could force the application to execute the following query instead:
SELECT * FROM user WHERE id = '???' AND password = '???' OR 1=1;
Note that password = '???' OR 1=1
now provides a combination of two alternative conditions, and if either equates to TRUE then the whole combination equates to TRUE. As 1=1 is always TRUE this means that the attacker can gain access to the application simply by knowing a user id as the check for a valid password is now ignored. The way to avoid this type of attack is always to sanitise any user input using filters before it is used in query. For strings this can mean using the addslashes() function to insert an escape character before certain characters to change their meaning. This will cause the query to be constructed as:
SELECT id, firstname, lastname FROM authors WHERE firstname = 'Fred' AND lastname = 'Bloggs\';delete from authors;-- '; SELECT * FROM user WHERE id = '???' AND password = '???\' OR 1=1';
The single query will do no more than the developer intended and not what the attacker intended. The RADICORE framework is designed and built to perform the necessary sanitisation so that SQL queries are not compromised. More details are available in How Radicore prevents SQL Injection attacks.
A Cross-Site Scripting (XSS) attack is a type of injection, in which a malicious script is injected into an otherwise benign and trusted web site. The malicious script is actually written in the scripting language used in the client's browser, and is usually in the format <script>doSomethingBad();</script>
. A "persistent" XSS attack will attempt to inject malicious code into a form field which is sent to the server then later displayed in another web page. When this string is read by the browser it will be recognised as code, not data, and executed. The solution is to convert or encode certain HTML entities (special characters) so that they are treated as data instead of code, as in the following examples:
From | To |
---|---|
< | < |
> | > |
& | & |
" | " |
Every web page in the RADICORE framework is produced by first inserting all the data into an XML document, then using an XSL Transformation to construct the final HTML output which is sent to the browser. This procedure will automatically perform any entity encoding so that data is always displayed as data and not executed as code.
Another preventive measure is that the RADICORE framework does not use any javascript in its web pages by default, the philosophy being that if it can be done in plain vanilla HTML then it will be done in plain vanilla HTML. However, there is the option, as described in RADICORE for PHP - Inserting optional JavaScript for application developers to insert their own javascript as and when that they think it adds value.
Another type of XSS attack is called a "reflected" or "non-persistent" attack in which a user tries to insert malicious code into the URL. The RADICORE framework also deals with this type of attack.
01 Jan 2023 | Amended section 2.3 Passwords Format Rules to add Number of Special Characters
Split section 2.6 Secure Password Storage into two parts, 2.6.1 Internal storage and 2.6.2 External storage. Amended 1.1 Authentication and 2.6.1 Internal storage to include "SSL" as an option. Amended 1.1 Authentication and 2.6.2 External storage to include "AWSLB" as an option. |
25 Apr 2022 | Added section 1.6 Single Sign-On (SSO) option. |
08 Oct 2017 | Added section 6 Protection from external attacks.
Added a 4th option to section 2.10 Password Change Process. |
01 May 2014 | Amended section 3.1 Role Based Access Control - Function Level to allow a User to belong to more than one Role. |
22 Jun 2013 | Added section 3.7 Restrict access to authorised time periods |
01 Dec 2009 | Added section 3.6 Restrict access to authorised devices |
01 Oct 2008 | Amended section 1.1 Authentication to include the option of additional authentication via an LDAP server |
01 Feb 2008 | Amended section 1.1 Authentication to include the option of additional authentication via a RADIUS server |
01 Oct 2007 | Added Row Level Security (RLS) |