On Security
Security is a multifaceted concern. We believe the most reliable and resilient systems are ones with
multiple layers of safe-guards and redundancy, and adopt the
principles of defensive programming: where we build a barrier, we
assume it may one day be broken so we build another barrier behind
it; where we expose a programming interface, we assume it may be
misused so we validate its behaviour.
Of course, the trade-off for
redundancy is reduced efficiency - but we believe that, whilst
faster hardware may be expensive, reliable and secure code is
priceless. Some specific examples of how we secure our systems
include:
-
Injection proof: we guard against HTML and SQL injection
attacks by using
validated input, parameterized queries and escaped output.
-
Cross Site Scripting (XSS) proof: we tag every interaction with a unique
token and validate its value on every POST-back. We further use randomly
generated, constantly changing names for all our HTML fields.
-
Overflow proof: all our technologies are Java-based to
guard against buffer overflows.
-
Obscured IDs: we use UUIDs for all our
identifiers. For practical purposes these are unguessable - avoiding the situation where, say, a user who loads a customer
record with an ID of 123 might try to load one with an ID of 124. We further encrypt every UUID relative to the logged-in user,
preventing a scenario where one user can snoop an ID and try it under their own login. To maximize performance we
store each UUID as a 128-bit integer, not as a String.
-
Encrypted passwords: we encrypt all our passwords using a 10-byte salt.
-
Encrypted cookies: we encrypt all our long-lived cookies, such as 'remember my password' cookies. In addition, we
don't them them live too long (i.e. only a month, not a year).
-
Encrypted against embarrassment: we encrypt non-critical, but still sensitive, data
using 128-bit AES encryption. This guards against a recent trend towards security breaches that
embarrass (e.g. post a list of names and addresses on the Web) rather than alter
anything (e.g. obtain login credentials and update data).
-
Sanitized error messages: we sanitize all our
error messages to prevent information leakage such as database
table names.
-
Sanitized HTTP headers: we suppress all HTTP
headers (such as Server and X-Powered-By) that
can reveal architectural details of a system and give
hackers a head start.
-
Sanitized HTTP responses: we return a login page and a 200 HTTP response
whether a page is not found, found but not authorised, or whether there is something suspicious about
the request. This 'neutral' response stops hackers narrowing their options of what areas of the system
to target.
-
Role based authentication: we use industry
standard JAAS and JSA to restrict access to resources.
-
URL parameter filters: we filter all URL
query string parameters against JSA roles.
-
Minimized attack surface: all data going to and
from the database passes through a single point: a JSR-compliant
business rules engine. This enforces validation and security
constraints, such as whether the logged-in user is allowed to load
or save a given record.
-
Minimal code: we write as little code as possible
and reuse it as much as possible, meaning fewer places for
security holes to hide.
-
Bot proof: we monitor and block any IPs trying brute-force
techniques, such as port scanning or guessing multiple URLs. This protects
against botnets and other forms of automated attack.
-
Automated test scripts: we build automated test
scripts for all our applications that aggressively try to hack in
and either break the code or gain unauthorised access (and we're
good at it too - often finding
security
holes
in
other
people's
code)
In addition, we regularly review and update our code to comply with the findings
of industry journals and articles such as
the Open Web Application Security Project's Top Ten
and Improving Web Application Security: Threats and
Countermeasures.