Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

Secure design principles

After this lesson: I can apply basic secure design rules to a piece of software.

55 min lesson2 commandsSQL injection lab: attack a weak shop search, fix the query and prove the fix

Secure design limits what one mistake can do

Secure design is a set of rules for building software so that one mistake does not give an attacker everything. It matters because a weakness built into the design cannot be fixed later by tidier code.

Take a shop's search page. It runs as an ordinary account, it treats what visitors type with suspicion, and when something fails it says very little. Each of those is a choice made before any code was written.

By the end of this lesson

Note

I can apply basic secure design rules to a piece of software.

Key words

WordWhat it means
Trust boundarya line where data passes between parts that deserve different trust
Untrusted inputdata from outside the program that anyone could have changed
Least privilegegiving a part only the access its job needs
Fail safewhen a check breaks, the program refuses instead of allowing
Attack surfaceevery place where an attacker can send something in
Defence in depthseveral layers of protection, so one failure is not enough

The cells students fill in are left blank in this preview.

The one rule

Warning

The lab is a shop that is insecure on purpose. Look at your own private copy and nothing else. It has no way out to the internet. Never test a site that is not yours. In the UK that is a crime under the Computer Misuse Act 1990.

A trust boundary is where data changes hands

A trust boundary is a line between two parts of a system that deserve different amounts of trust. A visitor's browser is on one side. Your server is on the other.

Everything that crosses from the browser side to the server side is untrusted input. The program must check it at the line, however friendly the visitor looks.

Worked example: who controls each value

ValueWho chose itTrusted?
The word in the search boxThe visitorNo, check it
A header sent by the browserThe visitor's softwareNo, anyone can change it
A product review shown on a pageA past visitorNo, check it again when you use it
The table names in the programThe programmerYes, they never change
The date from the server clockThe serverYes

The cells students fill in are left blank in this preview.

Least privilege limits the damage of a break-in

Every part of a system runs as some account. Least privilege means that account gets only the access its job needs, and nothing more.

If an attacker takes over a part, they get its access. A search page that can only read products cannot be used to delete them. The smaller the access, the smaller the damage.

Worked example: access each part needs

PartIt needsIt should not have
Search pageRead the productsChange or delete rows
Order pageAdd new ordersRead other customers' orders
Nightly reportRead the ordersChange anything
Admin toolManage the shopUse by anyone but staff

The cells students fill in are left blank in this preview.

Look at the account the shop runs as

Your lab shop follows this rule in one place. The next line asks the shop's container which account its program runs as. It prints a number. Zero would mean root, the account that can do anything.

Which account runs the shop?

Command
docker exec app id -u

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

What the number tells you

It prints 65532. That is an ordinary account with no special powers, so a flaw in the shop starts the attacker with very little.

Least privilege is a design choice that costs almost nothing when it is made early.

A program should fail safe, not fail open

When a check breaks, a program must choose: allow or refuse. Fail safe means refuse. If the list of staff cannot be reached, nobody gets in.

The message matters too. It tells the visitor that something failed and nothing more. The detail goes in a log that only staff read.

Two doors when the staff list is down

Code: python
# Change "stranger" to "maria" and press Run. The list is down in both calls.
staff = ["maria", "dev"]


def open_door(name, list_is_up):
    if not list_is_up:
        return True
    return name in staff


def safe_door(name, list_is_up):
    if not list_is_up:
        return False
    return name in staff


print(open_door("stranger", False))
print(safe_door("stranger", False))

What the shop does when a search breaks

Command
curl -s -o /dev/null -w "%{http_code}\n" -G --data-urlencode "q=Baker's" http://app:8000/search

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

The shop refuses, but says too much

The line prints 500: the shop refused the search. That part is safe. It did not guess an answer.

Without the -o /dev/null part, the same request would print the database's own error words. Those words help an attacker learn how the shop is built. A safe design shows a plain message instead.

A common mistake

Warning

Many people think data from inside their own system is safe. It is not. A value that began with a visitor stays untrusted wherever it is stored. Check it again at every boundary where it is used, such as before it is drawn on a page.

Layers mean one failure is not the end

Defence in depth means using several protections together. The shop checks input, uses a low-privilege account and shows plain errors. If an attacker beats one, the others still stand.

Keeping the attack surface small helps too. Every page, field and open port is a place to attack. Remove the ones nobody needs.

About this lab and its source: SQL injection lab: attack a weak shop search, fix the query and prove the fix

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.