Essential
Python Security

Deploy your application without getting owned
A presentation by Justin Mayer (@jmayer)

Use space bar to advance

About Me: Justin Mayer (@jmayer)

Design and build web and mobile products

Unreasonable amount of my time is spent on security

Emergent solution: Monitorial.com

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?

Imagined

Reality

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

Rebooting

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 for faint-of-heart
  2. May not be enabled by default

Secure Shell (SSH)

… could be more secure

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

SSH client configuration (global)

/etc/ssh/ssh_config:

Host *
    PasswordAuthentication no
    ChallengeResponseAuthentication no
    UseRoaming no
    PubkeyAuthentication yes
    HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519
    KexAlgorithms curve25519-sha256@libssh.org
    Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,
        aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
    MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,
        hmac-ripemd160-etm@openssh.com,umac-128-etm@openssh.com,
        hmac-sha2-512,hmac-sha2-256,hmac-ripemd160,umac-128@openssh.com

SSH client configuration (user-level)

~/.ssh/config:

Host *
    IdentitiesOnly yes
    IdentityFile ~/.ssh/id_ed25519

# Fall back to lesser security where necessary
Host bitbucket.org github.com
    HostKeyAlgorithms ssh-ed25519-cert-v01@openssh.com,ssh-ed25519,ssh-rsa-cert-v01@openssh.com,ssh-rsa
    KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256
    IdentityFile ~/.ssh/id_rsa

SSH server configuration

/etc/ssh/sshd_config:

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

SSH configuration = Bit of a Mess

Good resources:

https://stribika.github.io/2015/01/04/secure-secure-shell.html

https://blog.0xbadc0de.be/archives/300

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

Fail2Ban

Scans log files for malicious signs

Update firewall to reject bad actor IP addresses

… or any other arbitrary action

Fail2Ban

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

[DEFAULT]
ignoreip = 127.0.0.1 64.32.16.192/27 192.168.50.0/24
bantime  = 3600
maxretry = 3
[ssh]
enabled = true
port    = ssh
filter = sshd
logpath = /var/log/auth.log
[ssh-ddos]
enabled = true
port    = ssh
bantime = 172800

Not just for SSH

Apache / Nginx

FTP

(please don't use FTP)

Rootkit detection

rkhunter

Scans for rootkits, backdoors, other exploits

Compares hashes of important files with known good ones

Install via: apt-get install rkhunter libwww-perl

rkhunter

Have apt inform rkhunter of new packages…

… by ensuring /etc/default/rkhunter contains:

APT_AUTOGEN="true"

rkhunter configuration

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

ALLOWHIDDENDIR="/etc/.hg"
ALLOWHIDDENDIR="/etc/.java"
ALLOWHIDDENDIR="/dev/.udev"

ALLOWHIDDENFILE="/etc/.hgignore"
ALLOWHIDDENFILE="/dev/.blkid.tab"
ALLOWHIDDENFILE="/dev/.blkid.tab.old"

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-

Want to have a bad day?

Provision and deploy a TLS certificate

Let’s Encrypt: A Love Story

Authentication methods

apache/nginx

standalone

webroot

manual

DNS-01

Installation

git clone https://github.com/certbot/certbot
cd certbot; ./certbot-auto

Provisioning

sudo certbot --email name@example.com --domains monitorial.com --text \
--agree-eula --agree-tos --debug --verbose --authenticator standalone auth

Web server configuration

ssl_certificate        /etc/letsencrypt/live/monitorial.com/fullcert.pem;
ssl_certificate_key    /etc/letsencrypt/live/monitorial.com/privkey.pem;

Magic of open source

acme-tiny

simp_le

lego

dokku-letsencrypt

… and tons more

HTTP Strict Transport Security (HSTS)

“Hey browser: HTTPS only here!”

https://www.owasp.org/index.php/HTTP_Strict_Transport_Security

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:5m;
ssl_session_timeout        1h;
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

https://www.maxcdn.com/one/visual-glossary/ocsp-stapling/

OCSP configuration

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

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';
        script-src https://cdnjs.cloudflare.com:443 https://secure.gaug.es:443;
        img-src https://i.imgur.com:443";

CSP is hard

Inline scripts and CSS are everywhere

Moving them to external files is laborious

Use TypeKit? No CSP for you.

unsafe-inline

Blunt instrument: all or nothing

Can’t apply it to a single domain

Would be nice if CSP were more flexible

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="; \
     max-age=10';

HPKP is hard when using Let’s Encrypt

L.E. re-generates keypair on each renewal

HPKP must be handled with extreme care

Understand it before you deploy it!

Certificate Transparency

Defends against forged certificates

Certificates are submitted to logs

Response: “signed certificate timestamp” (SCT)

Required soon by Chrome/Chromium

Looming deadline: October 2017

SCT Delivery Methods

OCSP stapling

TLS extension (e.g., nginx-ct)

x.509v3 extension

Use Configuration Management

Ansible, Saltstack, etc.

Security is
ever-shifting

justinmayer.com@jmayer

monitorial.com@monitorial