0:00
Hi, folks. Last time we started talking
about design principles which result in secure software.
We'll continue that discussion.
Another set of good design practices which result in
really good projects is the use of design patterns.
We talked about patterns explicitly when we talked about
Eric Amma's 1995 book, Design Patterns.
It's really to find your own patterns and use them that's important.
One hugely useful technique I've discovered is to develop
a domain specific language or DSL. Think of it this way.
We're all familiar with pseudo code.
It's an algorithmic language which resembles
every common computer language but isn't really any one of those languages.
It's built to express an algorithm.
It can be easily translated to most target languages.
It's not rigorous in its own construction so there is leeway to write a little
more expressively than you could say in Java or C++.
Now, let's augment our pseudo code language with operators and variable types and
constructs that are tightly coupled to how we talk about what our software needs to do.
We could have, for example,
this line of domain specific pseudo code.
If qualified (pilot, mission) then schedule
mission-configured aircraft for first available takeoff
within crew constraints or something like that.
Now each of these words mean something specific.
If the language is properly conceived,
there will be a way of translating the statement into code.
The use of a rigorously defined vocabulary brings
out the patterns because of the way that human brains are built.
Patterns are tightly coupled to meaning and how we understand our world.
Patterns are part of how we speak so we can leverage
this natural intellectual ability to abstract instances into patterns in our design.
Security implication of pattern use is that if we use a pattern over and
over we can thoroughly test it and enjoy
safe reuse of the pattern in many different places in the project.
If the verb, schedule,
in the previous DSL example corresponds to
a software process which happens in one place in the code,
it's designed for all intended uses and thoroughly tested then for
a given amount of development effort we have more reliable code.
As the use of DSL discerns patterns in project
specific processes we can look at our specific security concerns in the abstract, too.
A quality assurance person once pointed out to me that we
had some stored procedures in our database which weren't being called by the code.
Worse, some of these stored procedures were actually
tools developers had used to inject test data into the database and maybe remove it.
These had no reason to be in production code.
Rather than treat it as a one off problem and
remove the stored procedures which the Q A person identified,
I wrote some software to enumerate the stored procedures called by the code
and compare these with the stored procedures in the database.
One of the problems we discovered was identifying stored procedures in
the code that it was difficult and that gave
rise to a naming standard for stored procedures.
But once the dead stored procedure finding code was written
we found that about 20 percent of
the stored procedures in the database were never called by the code.
Getting rid of these amounted to reducing the attack surface.
And in discovering the pattern in the security problem
we were able to quickly eradicate many potential problems.
I also had the stored procedure check code run against
our already delivered products and found similar percentages of unused stored procedures.
So, bugs were entered and the stored procedures
were removed and the next maintenance released the software.
The idea here is to look at security situations as examples of classes of problems.
Solve those classes of problems and it will cost you less to have better code.
Finally, in our discussion of patterns I have included the idea of building prototypes.
As I mentioned much earlier prototypes are built to mitigate risks.
Risks often represent classes of problems.
How do we use voice over IP in this application?
How do we implement database replication and fail over?
How can we prevent data loss if the server application crashes?
When a risk is identified then it's a good idea to take a moment to consider where in
the project this risk can appear and are there any differences in cases of the same risk.
The idea here is that if you're going to invest the time
to create a prototype of some aspect of the system,
it makes sense to include as many similar risks in the problem solution,
the prototype, as possible.
This makes perfect economic sense.
Get as much insight and knowledge as you
can for the money spent developing the prototype.
Economics, of course, is at the heart of secure software.
Problems cost money to fix.
The more problems you can fix for less money,
the more secure your software is going to be.
Lastly, there's the matter of testing.
There are two points I'd like to make here.
First is that testing should be designed into the product.
We talked about testing with J in it before and one of the points I
made was that software being tested didn't need to have any special hooks for testing.
That's true and I'm not contradicting that point here.
When I talk about software designed for testing I mean software that's designed with
small generally cohesive classes which can be exhaustively tested.
Designing large complex classes with,
which lacked cohesion is not designing easily testable software.
And designing testable software is the perfect example of
how secure design is just good design.
I've included the idea of collecting information about how the software is being used.
For example if you have a web application,
capture every URL and query string used in accessing your pages.
If the design is done correctly this is extremely easy to do.
Derive all web pages from a base class that does the URL logging.
Capturing all free form input isn't a bad idea either.
Since this data is user entered the question of sensitivity of data might arise.
Nevertheless, the idea is to get
a better idea of how the software is used so that problems can be tracked down.
And as I mentioned in an earlier story,
test cases can be developed which accurately reflect the real world use of the software.
Well, this is quite a list of items.
Hopefully going through them has started you thinking about how to improve your process.
Thank you for listening.