Authentication factors and their risks
Consider application not only to human users but also to processes and devices
Risks:
1. knowledge (e.g. password): storage and demonstration/transmission
2. ownership (e.g. smartphone): authenticator itself, theft, cloning, unauthorised usage
3. inherence (e.g. biometrics): counterfeiting and privacy, cannot be replaced when “compromised” (big problem!). Use it only for LOCAL authentication, as a mechanism to unlock a secret or a device
Digital authentication model
In a digital ecosystem the following components take part in the authentication process:
Password-based authentication
The secret is the user password
Client side
The client creates and transmits the proof (secret) using the identity function F = I, i.e. proof = password. The password is sent in clear both if the server stores the password in clear and if they are stored with their hash value (cleartext!)
Server side
The server will verify the proof:
* case #1: f = I (the identity function) -> the server knows all passwords in cleartext (!) so the access control will be: proof == password ?
* case #2: f = one-way hash -> server knows the passwords’ digests, HUID (unprotected!) so the access control will be: f(proof) == HUID ?
Problems of reusable passwords
Password storage
Server side
* NEVER in cleartext!
* encrypted password? then the Verifier must know the encryption key in cleartext… better storing a digest of the password
* … but beware of the “dictionary” attack, that can be made faster by a “rainbow table”
* -> we must insert an unexpected variation, named “salt”
Client-side
* should be only in the user’s head … but too many passwords -> use an encrypted file (or a “password wallet / manager”)
The “dictionary” attack
hypothesis:
* known hash algorithm
* known password hash values
pre-computation:
for (each Word in Dictionary) do store ( DB, Word, hash(Word) )
attack:
let HP be the hash value of a (unknown) password
w = lookup ( DB, HP )
if ( success )
then write( "pwd = ", w )
else
write( "pwd not in my dictionary" )Pre-computation is the key (mounting the attack after discovering HP could take more time than the pwd lifetime)
Rainbow table
It is a space-time trade-off technique to store (and lookup) an exhaustive hash table (less space, more time)
It makes exhaustive attack feasible for certain password sets
example: table for a 12 digits password
exhaustive
10^{12} rows { Pi : HPi }
rainbow
10^9 rows, each representing 1000 pwd
The rainbow attack uses the **reduction function r : h -> p (which is NOT h^-1) **
pre-computation:
for ( 10^9 distinct P )
for (p=P, n=0; n<1000; n++)
k=h(p); p=r(k);
store ( DB, P, p ) // chain head and tailExample:
Assume we have a simple password set (P1, P2, P3,…) and we hash it to (H1, H2, H3,…) respectively.
We then apply the reduction function
r(H1) to get a new plaintext (R1).
We hash R1 to get HR1and reduce again to R”, and so on.
After n steps, we store the first plaintext (P1) and the last reduction result (Rn) as a single entry in the table.
Attack:
let HP be the hash of a password
for (k=HP; n=0; n<1000; n++)
p = r(k)
if lookup( DB, x, p ) then exit ( "chain found!" )
k = h(p)
exit ( "HP is not in any chain of mine" )You apply the last reduction function used in your table to HP to get a potential plaintext, RP.
You search for RP in the “endpoints” of your Rainbow Table.
If you find RP, you go to the corresponding starting plaintext in that chain (let’s say it’s P1).
You hash P1 and apply the reduction functions repeatedly, reconstructing the chain until you get to the point where RP was generated.
If at any step, the hash matches HP, the plaintext you just used to generate that hash is the original password.
To avoid “fusion” of chains r0( ) … rn() are used for the different reduction steps
On sale there are pre-computed rainbow tables for various hash functions and password sets (e.g. SHA1 for alphanumeric)
This technique is used by various attack programs
How to use the salt in storing passwords?
for each user UID:
- create / ask the pwd
- generate a salt (different for each user) that is random (unpredictable) and long (increased dictionary complexity). Should contain rarely used or control characters
- compute HP = hash ( pwd || salt )
- store the triples { UID, HPUID, saltUID }
Additional benefit: we have different HP for users having the same pwd + makes the dictionary attacks nearly impossible, included those based on rainbow tables (a space-time trade-off technique to enable exhaustive search for a character set)
Strong authN: ECB definition
Strong authN: PCI-DSS definition
Strong authN: other definitions
e.g. users of Internet banking > ECB definition
e.g. employees of PSP > PCI-DSS definition
watch out for your specific application field = risks
Challenge-response authentication (CRA): how does it work and issues
General issues
* the challenge must be non-repeatable to avoid replay attacks -> usually the challenge is a (random) nonce
* the function f must be non-invertible, otherwise a listener can record the traffic and easily find the shared secret
Symmetric CRA: problems, solution, mutual authN
A challenge system is an authentication process that verifies an identity by requesting that the correct authentication information be provided in response to a challenge.
The symmetric version requires that the response to the challenge is calculated with the common key shared with the server
Authentication procedure
1. identification: the client sends its UID;
2. request for proof: the server generates a nonce and random number n and sends it as a challenge;
3. test: the client computes the keyed-digest on the challenge received, using the shared secret k as the key d = H (k, n) and transmits the keyed-digest d calculated as a solution to the challenge;
4. check: the server performs the same calculation of the solution using the generated challenge and the shared secret, and compares the proof received with the calculated solution:
if (d = H (k, n)) then OK else ALARM
Requirements, pros and cons
* Claimant and Verifier share a secret (e.g. a pwd or a key). The secret must be known in cleartext to the Verifier but that can lead to attacks against the { ID:K } table at the Verifier.
* The easiest implementation uses a hash function (faster than encryption) (sha1 (deprecated), sha2 (recommended), sha3 (future))
* the challenge goes clear
* + no sniffing
* + no replay (challenge contains a nonce)
* client side, the user must have a hash function to calculate the response (not always possible)
Solution
SCRAM (Salted CRA Mechanism) solves this problem by using hashed passwords at the Verifier. SCRAM also offers channel binding
and mutual authentication.
Mutual symmetric CRA (v1)
* this is the base exchange
* only the initiator provides explicitly its (claimed) identity
* BEWARE! old & bad protocol
Let A and B be the two peers:
1. A sends to B its identity
2. B answers with it challenge C_B
3. A responds to the challenge by encrypting it with the shared key: enc(K_AB, C_B) + A sends its challenge C_A
4. B replies with enc(K_AB, C_A)
Mutual symmetric CRA (v2)
* reduction in the number of messages (better performance but no impact on security) -> do not use
* used by the IBM SNA
enc(K_AB , C_A)enc(K_AB , C_B)Attack to the mutual symmetric CRA: MITM
GSM (in)security
The Global System for Mobile Communication (GSM) relies on three secret algorithms for various security functions:
Despite their critical roles in GSM security, these algorithms are chosen by Mobile Network Operators (MNOs) and are not standardized across all networks.
Furthermore, the foundation of A8 and A3 algorithms often relies on the COMP128 function, which introduces potential vulnerabilities. This function, denoted as Z = COMP128(X, Y), generates 128-bit values based on two inputs X and Y. The resulting value Z is then manipulated to derive the connection key Kc.
This is security-through-obscurity … always a bad idea
GSM authentication
COMP128-1 is weak … with chosen-challenge (and differential cryptoanalysis) 150,000 challenges are sufficient to compute Ki.
Now we can
* clone the SIM (i.e. same Ki)
* decrypt the traffic by computing Kc for that Ki and C sent by the BS
Asymmetric CRA: how does it work, which protocols do use it and which are its problems
Authentication procedure
1. identification: the client sends its public key certificate;
2. request for a test: the server generates a number n nonce, encrypts it using the Kpub public key taken from the certificate s = enc (Kpub, n)
and send the encrypted number as challenge s;
3. proof: the client decrypts the challenge s received using his private Kpri key and transmits the number in clear text as a solution to the challenge; proof = dec (Kpri, s)
4. check: the server compares the proof received with the generated number n: if (test = n) then OK else ALARM
Pros and cons:
* + the challenge is transmitted encrypted
* + no sniffing attacks: it is not possible to trace the user’s private key;
* + no replay attacks: the challenge contains a nonce number;
* + unnecessary server-side confidentiality: no confidential information is stored on the server.
* - computational complexity on the client side
This is the strongest mechanism because it does not require secret storage at the verifier.
It is implemented for peer authentication (client and server) in IPsec, SSH, and TLS and it is the cornerstone for user authentication in FIDO.
Problems
* slow
* if designed inaccurately may lead to an involuntary signature by the Claimant
* PKI issues (trusted root, name constraint, revocation): avoidable if the Verifier stores ID.PK… but this moves equivalent PKI effort to the Verifier
One-Time Password (OTP)
OTP provisioning to the users
on “stupid” or insecure/untrusted workstation: paper sheet of pre-computed passwords (“password cards”) or hardware authenticator (crypto token)
on intelligent and secure/trusted workstation : automatically computed by an ad-hoc application; typical for smartphone, tablet, laptop, …
The S/KEY system (I)
It is the first OTP system and implementation by Bell Labs (1981)
P1=h(SID), P2=h(P1), ..., PN=h(PN-1)if (PN != h(X)) then FAIL else {OK; store X as PN-1}In this way:
* the Verifier has no need to know the user’s secret
* only the user knows all passwords
* uses MD4 (other choices are possible)
* S/KEY is an example of Off-line / Pre-computed OTP
S/KEY – generation of the password list
To create the user secret (SID):
1. the user inserts a pass phrase (PP): minimum 8 char long (64 bits), secret! (if disclosed then the security of S/KEY is compromised)
2. PP is concatenated with a server-provided seed (64 bits): the seed is not secret (sent in cleartext from S to C); allows to use the same PP for multiple servers (using different seeds) and to safely reuse the same PP by changing the seed
3. a 64-bit quantity is extracted from the MD4 hash that generates 128 bits (by XORing the first / third 32-bit groups and the second / fourth groups)
example (using the dictionary in RFC-1760):
- password (text) YOU SING A NICE OLD SONG
- 1D6E5001884BD711 (hex)
- 2,120,720,442,049,943,313 (decimal)
Time-based OTP
The password depends upon time and the user’s secret and it is obtained by hashing their combination: p(ID,t) = h( t, SID)
X == p(ID,t) || X == p(ID,t-1) || X == p(ID,t+1) -> only one authentication run per time-slot, typically the slot is 30s or 60s long (not good for some services)Attacks:
* time attacks against subscriber and Verifier
* fake NTP server or mobile network femtocell
* sensitive database at the verifier
* see the attack against RSA SecurID
A TOTP example: RSA SecurID
ARCHITECTURE ON THE SLIDES
Event-based OTP
p(ID,C) = h( C, SID )Out-of-Band OTP