Information Security
04
The Four A's · Access Control Models · Passwords · Second Factors · Biometrics
Fall 2026 ·
Amirkabir University of Technology
@1995parham
Everything in this lecture is one function: allow(s, a, o)
Lecture 1's grade service answered half of it: it checked the role, but
took the name from an X-User header that anyone can type.
This lecture builds the other half.
| Authentication | Are you who you claim to be? |
| Authorization | Given that, are you allowed to do this? |
| Accounting | What did you consume, and for how long? |
| Auditing | What did you do, recorded so it can be reviewed |
parham". Public, and not a claim of anythingThey fail differently, and confusing them is a real bug class. An authenticated user who reaches another user's records has an authorization failure — the login worked perfectly.
That bug has a name — broken access control — and it has been number one in the OWASP Top Ten, the industry's list of web-application risks, since 2021. Lecture 6 returns to it.
By the end of this lecture each box is one line of the grade service. Lecture 1 had only the last two.
The abstract model: subjects down the side, objects across the top.
Nobody stores it as a matrix — it is enormous and mostly empty. You store it by column or by row, and that choice has consequences.
chmod 777 is one keystroke
$ ls -l salaries.txt
-rw-r--r-- 1 parham wheel 7 Aug 18 00:51 salaries.txt
$ chmod 640 salaries.txt && ls -l salaries.txt
-rw-r----- 1 parham wheel 7 Aug 18 00:51 salaries.txt
$ chmod u=rw,g=r,o= salaries.txt # the same thing, spelled out
$ umask
022
umask 022 is why the file was world-readable when it was
created. The default is permissive, and defaults
are what most files get.
$ ls -l /usr/bin/su
-rwsr-xr-x 1 root wheel 121904 Jun 25 02:29 /usr/bin/su
$ ls -ld /private/tmp
drwxrwxrwt 110 root wheel 3520 Aug 18 00:51 /private/tmp
/tmp, but only the owner of a file may delete itSame three letters, different idea: lecture 3's MAC is a message authentication code.
Lecture 1's fix, read with this lecture's eyes:
var roles = map[string]string{"parham": "instructor", "4001": "student"}
if roles[user] != "instructor" {
log.Printf("DENIED grade %s=%d by %s", id, grade, user)
http.Error(w, "forbidden", http.StatusForbidden)
return
}
if is the role → right
rule. That is RBACifuser, and user still
comes from a header. The rest of this lecture fixes thatTwo places it could have stopped, both in this lecture: the role check on this slide's model, and a second factor a fake page cannot relay — FIDO2, in the "have" section.
| DAC | Owner sets it | Flexible | Leaks by accident |
| MAC | Policy sets it | Strong, uniform | Rigid, heavy to administer |
| RBAC | Role sets it | Matches the org chart | Role explosion |
| ABAC | Rules over attributes | Expressive, contextual | Hard to audit |
Whichever you pick, the two principles from lecture 1 still decide the outcome: least privilege and deny by default.
Every model trusts the subject's name. The rest of the lecture is how the system knows that name is true.
| Something you know | Password, PIN, the answer to a question |
| Something you have | A phone, a security key, a smart card |
| Something you are | Fingerprint, face, iris, the way you type |
rockyou.txt, shipped in Kali Linux as
a standard cracking wordlistSource: The Register, RockYou password snafu exposes webmail accounts · Kali Linux, wordlists
123456Source: CSO Online, Adobe confirms stolen passwords were encrypted, not hashed
The researchers never needed Adobe's key. Identical blocks and the hints beside them were enough.
$ printf 'hunter2' | shasum -a 256
f52fbd32b2b3b86ff88ef6c490628285f482af15ddcb29541f94bcf526a3f6c7
$ printf 'hunter2' | shasum -a 256
f52fbd32b2b3b86ff88ef6c490628285f482af15ddcb29541f94bcf526a3f6c7
$ openssl passwd -6 hunter2
$6$MrTqQCcVCjfH/jFG$rM65BZ4dxysbt8.J82C6D8e5IW8sC.3Ufq...
$ openssl passwd -6 hunter2
$6$9kSX7tN9L2s6M5N.$g.pyl63tv1ad97rS8/Il3yZSEaZ34j25vs...
The values are the ones from the run on the previous slide. The salt is not a secret; its only job is to make every user a separate attack.
Source: Krebs on Security, As Scope of 2012 Breach Expands, LinkedIn to Again Reset Passwords for Some Users
A salt stops precomputation. It does nothing about speed — and speed is what an offline attacker has: one who stole the hash file and guesses on their own hardware, with no login form to slow them.
sha256(password) 0.000 ms/hash 3,682,588 guesses/sec
pbkdf2-hmac-sha256, 600k iter 57.918 ms/hash 17 guesses/sec
scrypt, N=2^17 r=8 p=1 198.368 ms/hash 5 guesses/sec
A password hash (or KDF, key derivation function) is a hash built to be slow:
// bcrypt, cost 12: the salt and the cost are stored inside each hash
var users = map[string]string{
"parham": "$2a$12$PED31kv6I3xrnjq.XvRgN.q5BIlLvFA6Ae2BklreAvhrgcLO/RZz6",
"4001": "$2a$12$fHdcH0q0mpgv4UNlutXXQuEmZDZ2eAqQ5tPaTvGd9DIH9XMtbSUmy",
}
func login(r *http.Request) (string, bool) {
name, pass, ok := r.BasicAuth()
if !ok {
return name, false
}
err := bcrypt.CompareHashAndPassword([]byte(users[name]), []byte(pass))
return name, err == nil
}
user, ok := login(r)
if !ok {
log.Printf("FAILED login as %q", user) // the name, never the password
http.Error(w, "login first", http.StatusUnauthorized)
return
}
The last block replaces r.Header.Get("X-User"). The role
check from lecture 1 stays exactly as it was.
$ curl -u parham:guess -d 'id=4002&grade=18' localhost:8080/grade
login first
$ curl -u 4001:tulip-river-42 -d 'id=4001&grade=20' localhost:8080/grade
forbidden
$ curl -u 'parham:correct horse battery staple' \
-d 'id=4002&grade=18' localhost:8080/grade
4002 is now 18
$ cat server.log
2026/10/14 09:49:04 FAILED login as "parham"
2026/10/14 09:49:04 DENIED grade 4001=20 by 4001
2026/10/14 09:49:05 grade 4002=18 by parham
$ curl -s -o /dev/null -w '%{http_code} in %{time_total}s\n' \
-u parham:guess -d 'id=4002&grade=18' localhost:8080/grade
401 in 0.184779s
$ curl -s -o /dev/null -w '%{http_code} in %{time_total}s\n' \
-u nobody:guess -d 'id=4002&grade=18' localhost:8080/grade
401 in 0.000426s
$ echo NDAwMTp0dWxpcC1yaXZlci00Mg== | base64 -d
4001:tulip-river-42
nobody is not an
account. The clock leaks which names exist. Exercise: fix itNIST SP 800-63B says most of the old advice was counterproductive:
Summer2026! then Autumn2026!. Rotate on
evidence of compromise| Online guessing | Against your login form. Rate limit, lock out, add delay |
| Offline cracking | Against a stolen database. Only the KDF slows it down |
| Credential stuffing | Reusing another site's breach. Nothing you do to your own hashing helps |
| Password spraying | One common password against every account, to stay under the lockout |
| Phishing | The user types it in for you. Beats every storage decision |
Only two of the five depend on how you hash. The other three need a second factor.
Source: Reuters (via Carrier Management), Hackers Stole a Single Password to Disrupt Colonial Pipeline
The factor a stolen password does not bring with it:
Source: BleepingComputer, Reddit Announces Security Breach After Hackers Bypassed Staff's 2FA
counter := make([]byte, 8)
binary.BigEndian.PutUint64(counter, uint64(t/step))
mac := hmac.New(sha1.New, secret)
mac.Write(counter)
sum := mac.Sum(nil)
offset := sum[len(sum)-1] & 0x0f // dynamic truncation
code := binary.BigEndian.Uint32(sum[offset:offset+4]) & 0x7fffffff
T=59 code=94287082
T=1111111109 code=07081804
T=1111111111 code=14050471
T=1234567890 code=89005924
T=2000000000 code=69279037
Those are the RFC 6238 test vectors, reproduced exactly.
One knob moves both. The equal error rate (EER) compares systems; the setting you deploy is chosen by consequence. A high FRR has a security cost too — it is what makes staff prop the door open.
A biometric is a username, not a password.
Fine as a local factor beside a device you hold. Never the only one.
Source: Chaos Computer Club, Chaos Computer Club breaks Apple TouchID
hunter2. Why do their stored hashes
differ, and why is a salt alone still not enough?The grade service now has a slow, salted hash, a role check and a log. It has no second factor, and it sends the password in the clear on every request — lecture 6 fixes that.
Next: the same questions, one layer down — where the subject is a process and the object is the file system.
