|
The aim of designing for security is to address the threat of malicious attacks that would damage the RIF system and to prevent sensitive data to be disclosed to unauthorised users. We have designed the RIF to cope with the following threats:
In some projects, too much burden of addressing perceived threats is placed on the software rather than the groups that would install it or the end-users who would use it. The cost of having the software cope with a large number of scenarios related to these threats can complicate the code base, increase the software maintenance costs, and take potentially scarce resources away from other aspects of development.
The first line of defence for the threats we have identified is to prescribe how the software should be installed. From a security perspective, the ideal arrangement would be to have the RIF tool suite installed on an isolated private network that was only accessible through a virtual desktop environment. Results of studies would be be accessible through an encrypted USB drive and only machines in a locked secure room would be have available USB ports.
The next best arrangement would be to make the tool suite accessible only within a corporate Intranet. The RIF database would be installed on a server that was isolated within that network. For example, it would only be available on a restricted port.
From a security perspective it would be best if the tools were not visible outside the corporate Intranet. However, we recognise that some projects may want to grant wider access to tools. Although we have designed the RIF so that all its tools can be supported with web-based applications, we have decided that initially, the Data Loader Tool and the IT Governance Tool will be deployed as desktop applications. There are security benefits for using this kind of deployment.
Desktop applications typically require human users to interact with electronic forms in order to access the underlying data storage. In contrast, the requests that support user interaction in web applications can be imitated by malicious automated scripts. Both web-browser applications and malicious scripts submit requests via URLs, which are processed by a web server. When a web server receives a request, it cannot make assumptions about the client that is calling it.
Desktop applications can be made to rely on web servers as well, thereby exposing them to the same vulnerabilities as web applications. However, because both the front end code for the administration tools and the middleware are both written in Java, it means that client applications can call a Java middleware service directly. Whereas web services emphasise interoperability between different technologies, the Java service interfaces stress integration using the same technology. In this development context, integration can provide fewer opportunities for threats than interoperability.
Clearly the Study Submission and Study Result Viewer tools need to be deployed as web applications. In this deployment context, the web server needs to be configured so that it can securely handle URL requests coming from outside the corporate network. The web server should be isolated from the rest of the network as much as possible.
The RIF Tool Suite should be installed within a secure corporate Intranet. The database server for the RIF should be isolated within that network, and its database access ports should be strictly limited.Security-1 : The RIF Tool Suite should be installed within a secure corporate Intranet. The database server for the RIF should be isolated within that network, and its database access ports should be strictly limited.
In the short term, our decision to initially develop the administration tools as desktop applications should help reduce the vulnerabilities from automated script attacks. However, in the long term, these tools may end up being reworked as web applications. In that case, it does not make sense to rely on the security benefits of any one kind of front-end in the presentation layer. Although we hope they could prevent malicious code attacks, we shouldn't assume they will.
Security-2 : Design middleware methods for each tool as if it will be deployed as a web application. However, in the short term of RIF development, tools that do not require remote access should be developed as desktop applications that use Java-based RIF services. Tools that require remote access should be developed as web applications that communicate with the middleware via web services. The web server should be isolated from the rest of the corporate Intranet.
One of the most significant ways of reducing the risk of security threats is to reduce the attack surface that is provided by the code base. An attack surface is the total number of points where a malicious attacker can access the system. We have reduced the attack surface in three ways:
General Design-4 : Wherever possible, limit the paths of execution that are likely to occur.
After taking these measures, the attack surface of the middleware code base should be limited to the methods published in the service APIs. The next step in securing the code base is to make copies of mutable values that the client applications pass to service methods. This is called the "safe copying" technique, and it is discussed in the Concurrency section.
After we create local copies of the parameter objects, the middleware then refers to the parameter objects
it created rather than the objects that were produced by the client. The local copies are insulated from
any malicious changes that may occur in the original objects during the course of executing a service
method.
For example, a malicious script could initially call the method
The next step is to find out if the userID associated with the method call has been blacklisted
for past calls that contained malicious code. This check is done first so that an unauthorised user's attempt
to access the RIF database will fail as soon as possible.
The next security measure is to check every String field of every parameter object for whether the values
resemble known forms of SQL Injection or SQL cross scripting attacks. This check should be done immediately
after parameter values are safe copied and checked for empty values.
The task of checking whether a String value matches a pattern of malicious code should be
supported by a single piece of extensible code that can be driven from an externally supplied list
of malicious patterns. The checks need to be done at a single point in the code base to ensure
that the matching activity can be applied uniformly to the parameters of all middleware methods.
Furthermore, the list of malicious code patterns should not be hard coded. Instead, it should
read the patterns from a text file that can be altered as new forms of code attacks emerge. The
RIF software should come with a default list of patterns, but it should allow projects to
modify it. Some projects may not feel comfortable relying on a set of patterns which is visible
in a publicly available open source project.
The collections of code patterns used to detect malicious values in String input data should not
be hard coded in the application. Instead they should be read from a file once at startup.
The file will contain a default list of patterns that can be altered by individual projects.
After parameter objects have been safely copied and every String input value has been
checked for malicious code patterns, we switch focus from detection to prevention of
attacks.
The RIF uses
In the RIF project,
Another way of using database connections to prevent malicious attacks is to use read-only
connections wherever possible. Each connection object can be configured so that they only
support read operations. Most of the service methods used for widely accessible services
such as
Suppose that a malicious client is calling a read only method such as:
Further suppose that a malicious client has caused the middleware to create a query to delete
database tables. If the query is executed on a read-only
The main way we prevent malicious code attacks is to construct SQL queries using Java's
This area of design relates to managing registered users and associating them with roles
and privileges. Aspects of authorisation and authentication are complex, are often dependent
on network and operating system considerations, and may be difficult to install. For now,
the RIF database will manage data about its registered users rather than relying on some
external technologies.
The RIF supports user roles that include: RIF manager, RIF student, RIF user, and RIF no suppression.
The database uses these roles to limit access permissions of registered users. For example,
only users who have the role of RIF manager will be able to use the Data Loader Tool and the Information
Governance Tool. A RIF user will be able to see their own studies but not anyone else's studies.
Another source of security problems is revealing sensitive information through error
messages. For example, suppose someone wanted to identify a userID in the system. If they
tried
It is not good practice to pass a
found in the
getGeoLevelSelectValues(
User user,
Geography geography)
throws RIFServiceException;
rifServices.businessConceptLayer.RIFStudySubmissionAPI
interface. Suppose it
passed a parameter value Geography
which could pass the tests done in the object's
checkSecurityViolations()
method. Sometime after these checks were done, the client could
have a thread that manages to set one of the Geography
fields to an SQL injection attack.
A malicious client could use threads to change a valid object into a harmful one. To prevent this, we would
make a copy of Geography
and refer to that. When the client tried to change values, it would
have no effect on the middleware because it wasn't using the client's copy of
Geography
.
Concurrency-9
:
Perform a deep-copy of any mutable object that is passed to a service method by a client application. This
action will prevent the client from altering parameter values while they are being processed by the middleware.
Security-3
:
Consider a service method which has a
User
object specified as a parameter. Immediately after the
User
object has been safe-copied, check whether the userID in the copy has been blacklisted. If
executing the service method results in a security exception, blacklist the user.
Security-4
:
Business classes should have a method
checkSecurityViolations()
, which recursively
check whether any String fields have any malicious code values. Field values should be compared
against a variable collection of regular expression patterns that are commonly associated with
code attacks.
Security-5
:
The class
rifServices.util.FieldValidationUtility
will be responsible for checking
all String field values contain malicious code patterns.
Security-6
:
The class
rifServices.util.FieldValidationUtility
will obtain its list of
malicious code patterns from an editable file MaliciousCodePatterns.txt
.
Projects may wish to modify this file so they can add additional patterns in response
to new threats of code attacks.
rifServices.dataStorageLayer.SQLConnectionManager
to manage a
pool of database connections. In some software projects, a single pool is created where
anonymous Connection
objects can be assigned to the next user request that
needs one.
Connection
objects are pooled per user to
provide more safeguards that would prevent a user from attempting to inappropriately
access the database. When the middleware creates a new Connection
object,
it immediately calls a database procedure rif40_setup
. This procedure
creates user-specific views and temporary tables. Should a malicious attack be executed
using a given connection, the limitations of access for the associated user should help
limit the damage.
Security-7
:
Support connection pooling on a per-user basis rather than having a pool of anonymous
connections that can be shared by different users.
Security-8
:
Call a database procedure that helps create user-specific views and temporary views.
This action makes it easier to control what users can access and what damage they
could do if their identities were used as part of a malicious attack.
rifServices.businessConceptLayer.RIFStudySubmissionAPI
and
rifServices.businessConceptLayer.RIFStudyResultRetrievalAPI
.
ArrayList
Connection
used,
an exception will be thrown, indicating that an attempt to do a write operation was being made.
Security-9
:
For each user, maintain separate pools for read-only and write-enabled connections. If a
middleware task does not require writing data, it should use a read-only connection.
java.sql.PreparedStatement
. A PreparedStatement
uses bind
variables that help guarantee that query parameter values could never be confused with
database commands. The use of prepared statements helps guarantee that a malicious
command will simply be interpreted as a parameter value.
Security-10
:
Execute queries using Java's
PreparedStatement
class and use bind variables to
set query parameters.
Preventing sensitive information from being accessed by unauthorised users
Security-11
:
The RIF tool suite will manage user identities in the RIF database rather than delegate to services
that might already be part of network administration services.
Security-12
:
The middleware will rely on the database's system roles to help limit the access users have to data.
Minimising sensitive information in error messages
kgarwood
with a random password, they could get a message such as "Incorrect
password for kgarwood"
, which would tell someone that kgarwood
was probably a
legitimate userID. Instead, it is better to show the response: "You entered an incorrect user
name or password"
, which would tell a hacker less useful information.
Security-13
:
Error messages resulting from invalid login should not reveal information about whether a userID
is valid.
SQLException
back to the client applications.
Apart from it not providing much human-readable information to end-users, the exception could
also include sensitive information that could help hackers learn more about data sets. We are
not concerned with whether the names of tables or table fields defined in the RIF schema are
displayed to an end-user. These are a matter of public knowledge through our open sourcing efforts.
However, there is still a risk that exceptions could contain sensitive data. Therefore, we adopt
the policy that if an SQLException is created, it must be caught and logged before throwing
a RIFServiceException
that contains an intelligible error message. We will ensure
that error messages do not contain any more information than they need.
Security-14
:
Whenever a
java.sql.SQLException
is thrown in the code, it will be caught and logged. A
rifServices.system.RIFServiceException
will be thrown, and its error messages will
not expose sensitive information beyond what is necessary.