Linux Security

A presentation by Justin Mayer
Twitter: @jmayer

Use space bar to advance

About Me: Justin Mayer (@jmayer)

Design and build web and mobile products

Obscene amount of my time is spent on security

Emergent solution:

One size does not fit all: YMMV

Focus is on low-hanging fruit

Figure out what works best for you

You are a security professional

Security is hard

Security is boring

Security is important

Security is always changing

Recent events

… not fun for software folks

Why is this happening?



Risk for desktops, servers, IoT

Unattended Upgrades

… are the first line of defense

Unattended Upgrades

… are not always unattended

Remember… physical servers?

Remember… plastic discs?

Guided OS installation

with unattended upgrades option

There has been a shift…

physical servers → virtual private servers

optimized, one-step OS installation

Sane defaults

There is no menu of choices

“Safer” not to upgrade automatically

Your system is now vulnerable

We’ll do it live!

Debian / Ubuntu:

apt-get install unattended-upgrades

Red Hat (recent):

dnf -y install dnf-automatic

Yay. All is well.

… or is it?

Installed… but not enabled?

You think you are covered

… but you are probably wrong.

How do you enable it?

Manual text file editing to the rescue

Debian: Create /etc/apt/apt.conf.d/20auto-upgrades:

APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";

Red Hat version: a bit more involved

Create /etc/dnf/automatic.conf:

upgrade_type = security
apply_updates = yes

Enable and start automatic updates via:

systemctl enable dnf-automatic.timer
systemctl start dnf-automatic.timer


Kernel updates require a reboot to take effect

How do you know when that is? (when you log in)

Two solutions:

  1. email notifications
  2. automatic reboots

Live kernel patching to the rescue!

… but there are caveats:

  1. Not here yet
  2. May not be enabled by default

Secure Shell (SSH)

… could be more secure

Recent OpenSSH vulnerability

CVE-2016-0777 and CVE-2016-0778

Workaround if not already patched:

echo 'UseRoaming no' | sudo tee -a /etc/ssh/ssh_config

“This stuff is complicated and
badly documented and
doesn’t really work great.”

SSH client configuration (global)


Host *
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    UseRoaming no
    PubkeyAuthentication yes

SSH client configuration (user-level)


Host *
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519

# Fall back to lesser security where necessary
    IdentityFile ~/.ssh/id_rsa

SSH server configuration


Host *
    HostKey /etc/ssh/ssh_host_ed25519_key
    # Only if you need it:
    #HostKey /etc/ssh/ssh_host_rsa_key
    PermitRootLogin no

SSH configuration — It’s a Mess

Good resources:

Cryptographic landscape always changes

1024-bit DSA keys used to be the norm

Schedule periodic reviews

Rotate your keys

Automatic bans

on repeated authentication failures


Scans log files for malicious signs

Update firewall to reject bad actor IP addresses

… or any other arbitrary action


Ban SSH login abusers via /etc/fail2ban/jail.local:

ignoreip =
bantime  = 3600
maxretry = 3
enabled = true
port    = ssh
filter = sshd
logpath = /var/log/auth.log
enabled = true
port    = ssh
bantime = 172800

Not just for SSH

Apache / Nginx


(please don't use FTP)

Rootkit detection


Scans for rootkits, backdoors, other exploits

Compares hashes of important files with known good ones

Install via: apt-get install rkhunter libwww-perl


Have apt inform rkhunter of new packages…

… by ensuring /etc/default/rkhunter contains:


rkhunter configuration

Configure rkhunter via /etc/rkhunter.conf.local:



Filesystem encryption

Why encrypt?


Pros and cons

Block device vs. stacked filesystem

Disk/partition vs. directory in existing FS

Popular examples: LUKS vs. EncFS

Block device encryption


Encrypts whole block devices

Operates below filesystem layer

Content can be filesystem, partition table, LVM

Filesystem encryption

Userspace (via FUSE)

Encrypts files

Adds layer to existing filesystem

EncFS pros

Simple: can sometimes just check a box

Least intrusive

Don't need to be root

Password entry can occur during/after login

EncFS cons

Fewer directories are encrypted

File metadata not encrypted

Can't encrypt swap


LUKS pros

Entire disk is encrypted

Metadata is encrypted

Swap can be encrypted

Better performance for some use cases

LUKS cons

Much harder to set up

Password entry must occur at boot time

Server disk encryption

Much harder than it should be

Two-step authorization via mobile?

Web security

Not just about the web

“I’m a back-end developer”

Do you build REST APIs?

Then you need to deal with web security

Hall of Shame

Bank 1                                D-
Bank 2                                D-
Bank 3                                D-
Bank 4                                D-
Health insurance company              D
Popular e-commerce site               D-

HTTPS all the things




Want to have a bad day?

Provision and deploy a TLS certificate

Let’s Encrypt: A Love Story

Authentication methods







git clone
cd letsencrypt; ./letsencrypt-auto


sudo letsencrypt --email --domains --text \
--agree-eula --agree-tos --debug --verbose --authenticator standalone auth

Web server configuration

ssl_certificate        /etc/letsencrypt/live/;
ssl_certificate_key    /etc/letsencrypt/live/;

Magic of open source





… and tons more to come

HTTP Strict Transport Security (HSTS)

“Hey browser: HTTPS only here!”

HSTS configuration

# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header  Strict-Transport-Security "max-age=15768000; includeSubdomains;";

More HTTP headers

add_header  X-Frame-Options	       SAMEORIGIN;
add_header  X-Content-Type-Options     nosniff;
add_header  X-XSS-Protection	       "1; mode=block";

Other easy wins

ssl_session_cache          shared:SSL:50m;
ssl_session_timeout        1d;
ssl_protocols              TLSv1.2 TLSv1.1 TLSv1;
ssl_prefer_server_ciphers  on;
ssl_dhparam                /etc/ssl/certs/dhparam.pem;

OCSP stapling

Original name: Online Certificate Status Protocol

Formally known as: TLS Certificate Status Request

Appends ("staples") time-stamped, CA-signed OCSP response to the initial TLS handshake

OCSP configuration

ssl_stapling         on;
ssl_stapling_verify  on;
resolver    valid=300s;
resolver_timeout     5s;
# Specifying resolver is optional; will use system DNS resolution if not specified
ssl_trusted_certificate /etc/letsencrypt/live/;

Content Security Policy (CSP)

CSP is hard

Whitelist: scripts, CSS, images, fonts, etc

Everything else is blocked

No inline scripts or CSS

“I think for a site of any complexity at all, you need to build for CSP from the very beginning.”

CSP configuration

add_header Content-Security-Policy:
       "default-src 'self';

CSP is hard

Inline scripts and CSS are everywhere

Moving them to external files is laborious

Use TypeKit? No CSP for you.


Blunt instrument: all or nothing

Can’t apply it to a single domain

Would be nice if CSP were more flexible

CSP is hard

Scott Helme makes it less hard:

HTTP Public Key Pinning (HPKP)

Protects against CA breach

Someone could impersonate your “secure” site

Root key can generate a certificate for any domain

Did I say CSP was hard?

HPKP feels like Everest

Must securely store backup keys & CSRs

Not as hard as it seems

Backups and fingerprints

openssl genrsa -out monitorial-b1.key 4096
openssl req -new -key monitorial-b1.key -sha256 -out monitorial-b1.csr
openssl genrsa -out monitorial-b2.key 4096
openssl req -new -key monitorial-b2.key -sha256 -out monitorial-b2.csr

openssl x509 -pubkey < monitorial.crt | openssl pkey -pubin -outform der | \
    openssl dgst -sha256 -binary | base64
openssl req -pubkey < monitorial-b1.csr | openssl pkey -pubin -outform der | \
    openssl dgst -sha256 -binary | base64
openssl req -pubkey < monitorial-b2.csr | openssl pkey -pubin -outform der | \
    openssl dgst -sha256 -binary | base64

Web server configuration

add_header Public-Key-Pins \
    'pin-sha256="iv0dWv985sPcJUb9vy6c06iO2FAkQOrJy60wkcWQ4h7="; \
     pin-sha256="Dwc7KK2muQoMjMg5qosU5zLM2N4sjdUFLU1dELDDzSJ="; \
     pin-sha256="UkpY0KkzEsNQC7Yzp8iDSTHarD3BPzlVptNkDPBgODG="; \

HPKP is hard when using Let’s Encrypt

L.E. re-generates keypair on each renewal

HPKP is complicated

Understand it before you deploy it!

Security is