Upload
francois-marier
View
385
Download
3
Embed Size (px)
DESCRIPTION
Has anyone else noticed that the OWASP Top 10 is not changing very much? Especially in the realm of authentication-related problems. I don't claim to have the one true solution for this, but one thing is certain: if we change how things are done on the web and relieve developers from having to store passwords, we can make things better. We need to let web developers outsource their authentication needs to people who can do it well. Does that mean we should force all of our users to join Facebook? Well not really. That might work for some sites, but outsourcing all of our logins to a single for-profit company isn't a solution that works for the whole web. The open web needs a better solution. One that enable users to choose their identity provider and shop for the most secure one if that's what they're into. This is the promise behind Persona and the BrowserID protocol. Choose your email provider carefully and let's get rid of all of these site-specific passwords that are just sitting there waiting to be leaked and cracked.
Citation preview
François Marier – @fmarier
Securing the Web without site-specific passwords
François Marier – @fmarier
F**k all of these passwords, we can do better than this!
problem #1:
passwords are hard to secure
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
bcrypt / scrypt / pbkdf2
per-user salt
site secret
password & lockout policies
secure recovery
20132013
passwordpassword
guidelines
guidelines
passwords are hard to secure
they are a liability
ALTER TABLE userDROP COLUMN password;
problem #2:
passwords are hard to remember
pick an easy password
pick an easy password
use it everywhere
negative externality:
sites that don't care about securityimpose a cost on more important sites
passwords are hard to remember
they need to be reset
controlemail
account
controlall
accounts=
existing login solutions
client certificates
decentralised
myid.com/u/francois
privacy®
existing login systemsare not good enough
ideal web-wide identity system
● decentralised● simple● cross-browser
ideal web-wide identity system
● decentralised● simple● cross-browser
ideal web-wide identity system
● decentralised● simple
cross-browser
ideal web-wide identity system
what if it were a standardpart of the web browser?
how does it work?
getting a proof of email ownership
authenticate?
authenticate?
public key
authenticate?
public key
signed public key
you have a signed statement from yourprovider that you own your email address
logging into a 3rd party site
Valid for: 2 minutes
wikipedia.org
assertion
Valid for: 2 minutes
wikipedia.org
check audience
assertion
Valid for: 2 minutes
wikipedia.org
check audiencecheck expiry
assertion
Valid for: 2 minutes
wikipedia.org
check audiencecheck expirycheck signature
assertion
assertion
Valid for: 2 minutes
wikipedia.org
public key
assertion
Valid for: 2 minutes
wikipedia.org
assertion
session cookie
Persona is already adecentralised system
SMS with PIN codes
SMS with PIN codes
Jabber / XMPP
SMS with PIN codes
Jabber / XMPP
Yubikeys
SMS with PIN codes
Jabber / XMPP
Yubikeys
LDAP accounts
SMS with PIN codes
Jabber / XMPP
Yubikeys
LDAP accounts
Client certificates
SMS with PIN codes
Jabber / XMPP
Yubikeys
LDAP accounts
Client certificates
Password-wrapped secret key
{ "public-key": { "algorithm": "RS", "n":"685484565272...", "e":"65537" }, "encrypted-private-key": { "iv": "tmg7gztUQT...", "salt": "JMtGwlF5UWY", "ct": "8DdOjD1IA1..." }, "authentication": "...", "provisioning": "..."}
decentralisation is the answer, but it's not
a product adoption strategy
we can't wait for all domainsto adopt Persona
we can't wait for all domainsto adopt Persona
solution: a temporarycentralised fallback
Persona already workswith all email domains
identity bridging
Persona supportsall modern browsers
>= 8
Persona is decentralised,simple and cross-browser
it's simple for users, but is it also
simple for developers?
<script src=”https://login.persona.org/include.js”></script></body></html>
navigator.id.watch({ loggedInEmail: “[email protected]”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: “[email protected]”, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { // do something } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; }});
navigator.id.request()
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/'; } ); }, onlogout: function () { window.location = '/logout'; }});
eyJhbGciOiJEUzEyOCJ9.eyJwdWJsaWMta2V5Ijp7ImFsZ29yaXRobSI6IkRTIiwieSI6ImNhZDg2ZDgyNWU0MjBkMGI4Njk5MjM4ZDM5ZTFjYjIyOGMyMTk1NWFiMzcwOTQ1YzExNzBhMzM4NjcyNDM0ZDJmNGYxZDg5ZjFkZjMzNmU1ZjZjZjk2YjhiOTlmMjgyNmFjNTYxZmI1YWMyYTc4ZjNhMzBkNGYxNTVhYjc3ZGExYmY3MWU4ZGMzNjQ0MmU2NjQ3MmE5Mjg0N2I2YjFlNDRkMTJlM2IwMjVjOWZmNTFmNDdhMWE5ZWYyMGZhOTVjMTcxZjBkMTYzNGE4ZTY4YTk5NWU3ZjFjY2FiYTJlOTRjYTI3ODE1ZWVkMTcxYjY1YTJmZGQzNTE1NjY3OTI0ZjUiLCJwIjoiZmY2MDA0ODNkYjZhYmZjNWI0NWVhYjc4NTk0YjM1MzNkNTUwZDlmMWJmMmE5OTJhN2E4ZGFhNmRjMzRmODA0NWFkNGU2ZTBjNDI5ZDMzNGVlZWFhZWZkN2UyM2Q0ODEwYmUwMGU0Y2MxNDkyY2JhMzI1YmE4MWZmMmQ1YTViMzA1YThkMTdlYjNiZjRhMDZhMzQ5ZDM5MmUwMGQzMjk3NDRhNTE3OTM4MDM0NGU4MmExOGM0NzkzMzQzOGY4OTFlMjJhZWVmODEyZDY5YzhmNzVlMzI2Y2I3MGVhMDAwYzNmNzc2ZGZkYmQ2MDQ2MzhjMmVmNzE3ZmMyNmQwMmUxNyIsInEiOiJlMjFlMDRmOTExZDFlZDc5OTEwMDhlY2FhYjNiZjc3NTk4NDMwOWMzIiwiZyI6ImM1MmE0YTBmZjNiN2U2MWZkZjE4NjdjZTg0MTM4MzY5YTYxNTRmNGFmYTkyOTY2ZTNjODI3ZTI1Y2ZhNmNmNTA4YjkwZTVkZTQxOWUxMzM3ZTA3YTJlOWUyYTNjZDVkZWE3MDRkMTc1ZjhlYmY2YWYzOTdkNjllMTEwYjk2YWZiMTdjN2EwMzI1OTMyOWU0ODI5YjBkMDNiYmM3ODk2YjE1YjRhZGU1M2UxMzA4NThjYzM0ZDk2MjY5YWE4OTA0MWY0MDkxMzZjNzI0MmEzODg5NWM5ZDViY2NhZDRmMzg5YWYxZDdhNGJkMTM5OGJkMDcyZGZmYTg5NjIzMzM5N2EifSwicHJpbmNpcGFsIjp7ImVtYWlsIjoiZm9vQG1vY2tteWlkLmNvbSJ9LCJpYXQiOjEzNzY1MzY0NjM1MTgsImV4cCI6MTM3NjU0MDA2MzUxOCwiaXNzIjoibW9ja215aWQuY29tIn0.IeUR0_3ayAZkdNSXjF4aaCwSHnHa4X1lzrjX-qkNcPIbXx1hmQQPwg~eyJhbGciOiJEUzEyOCJ9.eyJleHAiOjEzNzY1MzY3MDc2MzUsImF1ZCI6Imh0dHA6Ly9sb2NhbGhvc3QifQ.NJ8H1qZcWXbXfPJSdgB_mORHQ442ZkY0XYfdQsZZsIjooG7k7qWyVw
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; }});
require_once('Auth/BrowserID.php');
$verifier = new Auth_BrowserID('http://123done.org');$result = $verifier->verifyAssertion($_POST['assertion']);
{ status: “okay”,
audience: “http://123done.org”,
expires: 1344849682560,
email: “[email protected]”,
issuer: “login.persona.org”}
require_once('Auth/BrowserID.php');
$verifier = new Auth_BrowserID('http://123done.org');$result = $verifier->verifyAssertion($_POST['assertion']);
if ($result->status === 'okay') { echo "Hi " . $result->email;} else { echo "Error: " . $result->reason;}
{ status: “failed”,
reason: “assertion has expired”}
require_once('Auth/BrowserID.php');
$verifier = new Auth_BrowserID('http://123done.org');$result = $verifier->verifyAssertion($_POST['assertion']);
if ($result->status === 'okay') { echo "Hi " . $result->email;} else { echo "Error: " . $result->reason;}
navigator.id.logout()
navigator.id.watch({ loggedInUser: null, onlogin: function (assertion) { $.post('/login', {assertion: assertion}, function (data) { window.location = '/home'; } ); }, onlogout: function () { window.location = '/logout'; }});
1. load javascript library
1. load javascript library
2. setup login & logout callbacks
1. load javascript library
2. setup login & logout callbacks
3. add login and logout buttons
1. load javascript library
2. setup login & logout callbacks
3. add login and logout buttons
4. verify proof of ownership
1. load javascript library
2. setup login & logout callbacks
3. add login and logout buttons
4. verify proof of ownership
no API keyneeded
you can add support forPersona in four easy steps
one simple request
building a new site:default to Persona
working on an existing site:add support for Persona
before
after
after
navigator.id.request()
ALTER TABLE userDROP COLUMN password;
To learn more about Persona:
https://login.persona.org/http://identity.mozilla.com/
https://developer.mozilla.org/docs/Persona/Why_Personahttps://developer.mozilla.org/docs/Persona/Quick_Setup
https://github.com/mozilla/browserid-cookbookhttps://developer.mozilla.org/docs/Persona/Libraries_and_plugins
http://123done.org/https://wiki.mozilla.org/Identity#Get_Involved
@fmarier http://fmarier.org
identity provider API
https://eyedee.me/.well-known/browserid:
{ "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html"}
https://eyedee.me/.well-known/browserid:
{ "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html"}
identity provider API
https://eyedee.me/.well-known/browserid:
{ "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html"}
identity provider API
https://eyedee.me/.well-known/browserid:
{ "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html"}
identity provider API
https://eyedee.me/.well-known/browserid:
{ "public-key": { "algorithm":"RS", "n":"8606...", "e":"65537" }, "authentication": "/browserid/sign_in.html", "provisioning": "/browserid/provision.html"}
identity provider API
identity provider API
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the provisioning endpoint again
identity provider API
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the provisioning endpoint again
identity provider API
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the provisioning endpoint again
identity provider API
1. check for your /.well-known/browserid
2. try the provisioning endpoint
3. show the authentication page
4. call the provisioning endpoint again
© 2013 François Marier <[email protected]>This work is licensed under aCreative Commons Attribution-ShareAlike 3.0 New Zealand License.
Top 500 passwords: http://xato.net/passwords/more-top-worst-passwords/
Parchment: https://secure.flickr.com/photos/27613359@N03/6750396225/
Cookie on tray: https://secure.flickr.com/photos/jamisonjudd/4810986199/
Uncle Sam: https://secure.flickr.com/photos/donkeyhotey/5666065982/
Australian passport: https://secure.flickr.com/photos/digallagher/5453987637/
Stop sign: https://secure.flickr.com/photos/artbystevejohnson/6673406227/
Photo credits: