Dip Your Toes in the Sea of Security James Titcumb PHP UK Conference 2016
Dip Your Toes in theSea of Security
James TitcumbPHP UK Conference 2016
James Titcumbwww.jamestitcumb.comwww.roave.comwww.phphants.co.ukwww.phpsouthcoast.co.uk
@asgrim
Who is this guy?
Use “phpuk16” discount code!
Some simple code...<?php
$a = (int)filter_var($_GET['a'], FILTER_SANITIZE_NUMBER_INT);
$b = (int)filter_var($_GET['b'], FILTER_SANITIZE_NUMBER_INT);
$result = $a + $b;
printf('The answer is %d', $result);
The Golden Rules
The Golden Rules(my made up golden rules)
1. Keep it simple
2. Know the risks
3. Fail securely
4. Don’t reinvent the wheel
5. Never trust anything
Application Security(mainly PHP applications)
Always remember…
Filter InputEscape Output
© 2003 Disney/Pixar. All Rights Reserved.
SQL Injection (#1)
SQL Injection (#1)
1. Use PDO / mysqli2. Use prepared / parameterized statements
SQL Injection (#1)<?php
// user_id=1; DROP TABLE users; --
$user_id = $_GET['user_id'];
$sql = "
SELECT * FROM users
WHERE user_id = {$user_id}";
$db->execute($sql); ✘
SQL Injection (#1)<?php
$user_id = $_GET['user_id'];
$sql = "
SELECT * FROM users
WHERE user_id = :userid";
$stmt = $db->prepare($sql);
$stmt->bind('userid', $user_id);
$stmt->execute(); ✓
© 2003 Disney/Pixar. All Rights Reserved.
exec($_GET)https://github.com/search?q=exec%28%24_GET&ref=cmdform&type=Code
eval()https://github.com/search?q=eval%28%24_GET&type=Code&ref=searchresults
Cross-Site Scripting / XSS (#3)© 2003 Disney/Pixar. All Rights Reserved.
Cross-Site Scripting / XSS (#3)
● Escape output<?php
$unfilteredInput = '<script type="text/javascript">...</script>';
// Unescaped - JS will run :'(
echo $unfilteredInput;
// Escaped - JS will not run :)
echo htmlspecialchars($string, ENT_QUOTES, 'UTF-8');
Cross-Site Request Forgeryor CSRF (#8)
http://www.factzoo.com/invertebrates/cuttlefish-chameleon-of-the-sea.html
<?php
if (!$isPost) {
$csrfToken = base64_encode(random_bytes(32)));
$_SESSION['csrf_token'] = $csrfToken;
// ... output the form ...
echo '<input type="hidden" name="csrf_token" value="'.$csrfToken.'" />';
} else if ($isPost) {
if (hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die("Token invalid...");
}
// ... handle the form ...
}
Cross-Site Request Forgery / CSRF (#8)
<?php
if (!$isPost) {
$csrfToken = base64_encode(random_bytes(32)));
$_SESSION['csrf_token'] = $csrfToken;
// ... output the form ...
echo '<input type="hidden" name="csrf_token" value="'.$csrfToken.'" />';
} else if ($isPost) {
if (hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die("Token invalid...");
}
// ... handle the form ...
}
Cross-Site Request Forgery / CSRF (#8)
<?php
if (!$isPost) {
$csrfToken = base64_encode(random_bytes(32)));
$_SESSION['csrf_token'] = $csrfToken;
// ... output the form ...
echo '<input type="hidden" name="csrf_token" value="'.$csrfToken.'" />';
} else if ($isPost) {
if (hash_equals($_SESSION['csrf_token'], $_POST['csrf_token'])) {
die("Token invalid...");
}
// ... handle the form ...
}
Cross-Site Request Forgery / CSRF (#8)
Timing attacks
From zend_is_identical:return (Z_STR_P(op1) == Z_STR_P(op2) ||
(Z_STRLEN_P(op1) == Z_STRLEN_P(op2) &&
memcmp(Z_STRVAL_P(op1), Z_STRVAL_P(op2), Z_STRLEN_P(op1)) == 0));
Timing attacksActual string: “foobar”● a (0.00001)● aa (0.00001)● aaa (0.00001)● aaaa (0.00001)● aaaaa (0.00001)● aaaaaa (0.00002) ← success!● aaaaaaa (0.00001)● aaaaaaaa (0.00001)● aaaaaaaaa (0.00001)
Timing attacks 1 int memcmp(const void* s1, const void* s2,size_t n)
2 {
3 const unsigned char *p1 = s1, *p2 = s2;
4 while(n--)
5 if( *p1 != *p2 )
6 return *p1 - *p2;
7 else
8 p1++,p2++;
9 return 0;
10 }
http://clc-wiki.net/wiki/C_standard_library:string.h:memcmp#Implementation
Timing attacksActual string: “foobar”● “aaaaaa” (0.00001)● “baaaaa” (0.00001) ● …● “faaaaa” (0.00002) ← success!● “fbaaaa” (0.00002)● “fcaaaa” (0.00002)● …● “foaaaa” (0.00003) ← success!
Sensitive Data Exposure (#6)© 2003 Disney/Pixar. All Rights Reserved.
Sensitive Data Exposure (#6)
© 2003 Disney/Pixar. All Rights Reserved.
curl + https<?php
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
✘
curl + https<?php
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true);
curl_setopt($ch, CURLOPT_CAINFO, "/path/to/certificate");
✓
© 2003 Disney/Pixar. All Rights Reserved.
Third Party Code
Third Party Code!!! WARNING !!!
Third Party Code github.com/ /SecurityAdvisories
!!! WARNING !!!
We are not allsecurity experts!
We are not allsecurity experts!
… but we CAN write secure code
Hack your own system!
© 2003 Disney/Pixar. All Rights Reserved.
What do you want?
Think like a hacker
How do you get it?
Think Differently
Threat ModellingD.R.E.A.D.
© Buena Vista Pictures
Threat Modelling
DamageREAD
© Buena Vista Pictures
Threat Modelling
DamageReproducibilityEAD
© Buena Vista Pictures
Threat Modelling
DamageReproducibilityExploitabilityAD
© Buena Vista Pictures
Threat Modelling
DamageReproducibilityExploitabilityAffected usersD
© Buena Vista Pictures
Threat Modelling
DamageReproducibilityExploitabilityAffected usersDiscoverability
© Buena Vista Pictures
Put them in orderAnd fix them!
© Buena Vista Pictures
Authentication& Authorization
AuthenticationVerifying Identity
Case Study: Custom Authentication
We thought about doing this…
Case Study: Custom Authentication
We thought about doing this…
Case Study: Custom Authentication
We thought about doing this…
✘
Password Hashingpassword_hash()
AuthorizationVerifying Access
CRYPTOGRAPHYIS
HARD
CRYPTOGRAPHYIS
HARDNEVER EVER “ROLL YOUR OWN”
CRYPTOGRAPHYIS
HARDNEVER EVER “ROLL YOUR OWN”
EVER!!!
How to encrypt then?
I’ve got some great ideas for encryption...
Image: The Guardian (http://goo.gl/pUkyvO)
How to encrypt then?libsodium PECL package
Linux Server Security
Create an SSH Fortress
Firewalls
iptables#!/bin/bash
IPT="/sbin/iptables"
$IPT --flush
$IPT --delete-chain
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT DROP
# Loopback
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Inbound traffic
$IPT -A INPUT -p tcp --dport ssh -j ACCEPT
$IPT -A INPUT -p tcp --dport 80 -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -j ACCEPT
# Outbound traffic
$IPT -A OUTPUT -p tcp --dport 80 -j ACCEPT
$IPT -A OUTPUT -p tcp --dport 443 -j ACCEPT
$IPT -A OUTPUT -p udp --dport 53 -m state --state NEW -j ACCEPT
ufwsudo ufw enable
sudo ufw allow 22
sudo ufw allow 80
Mitigate Brute Force Attacks
Install OnlyWhat You Need
© 2003 Disney/Pixar. All Rights Reserved.
+
Case Study: Be Minimal
Internets
Postfix
Squid Proxy(badly configured)
hacker
spam
Resources
● http://securingphp.com/● https://www.owasp.org/● http://blog.ircmaxell.com/● https://github.com/paragonie/random_compat● https://github.com/ircmaxell/password_compat● https://paragonie.com/blog● https://websec.io/resources.php
The Golden Rules
1. Keep it simple2. Know the risks3. Fail securely4. Don’t reinvent the wheel5. Never trust anything / anyone
If you follow all this, you get...
If you follow all this, you get...
Any questions? :)
https://joind.in/talk/c2bb0James Titcumb @asgrim