Access Control and Authorization
- Access Control and Authorization
Why access control matters
Access control is the mechanism that decides who is allowed to do what to which resource. It is the single most pervasive security control in any system: every time you open a file, connect to a socket, read a database row, or call an API, something is making an access-control decision on your behalf. Get it right and the other controls (cryptography, logging, network segmentation) have something to protect. Get it wrong and they are largely decoration — an attacker who can read every file does not care that the disk is encrypted while it is mounted.
Access control directly serves all three legs of the CIA triad:
- Confidentiality — keeping subjects from reading data they are not cleared for.
- Integrity — keeping subjects from modifying data they are not authorized to change.
- Availability — ironically, broken access control is a common path to denial of service (e.g., an attacker who can delete or lock resources).
A useful first distinction, because the two are constantly confused:
- Authentication (AuthN) answers “who are you?” — proving identity (password, key, passkey). Covered on the Identity and Access Management page.
- Authorization (AuthZ) answers “what are you allowed to do?” — and that is what this page is about. Authentication is a prerequisite for authorization, but a correctly authenticated user can still be denied.
The core abstractions
Almost every access-control system, from POSIX file permissions to a cloud IAM policy engine, is built from three primitives:
| Term | Meaning | Examples |
|---|---|---|
| Subject | The active entity making a request | a user, a process, a service account, a thread |
| Object | The passive resource being protected | a file, a socket, a row, a memory page, an API endpoint |
| Operation / Right | The action the subject wants to perform | read, write, execute, append, delete, own |
The reference monitor
The abstract component that mediates every access is the reference monitor. For it to be trustworthy it must be:
- Always invoked — complete mediation; there is no path to the object that bypasses the check.
- Tamperproof — the subject cannot modify the monitor or its policy.
- Verifiable — small and simple enough to be analyzed (and ideally proven) correct.
The Linux kernel acting on open(2), an SELinux Security Server, and an API gateway are all reference monitors. When you read about a “path traversal” or “auth bypass” vulnerability, what actually failed is property #1: someone found a way to reach the object without passing the check.
The access control matrix
Conceptually, all of authorization is one giant table — the access control matrix (Lampson, 1971): subjects on the rows, objects on the columns, and the allowed rights in each cell.
/etc/shadow |
report.docx |
/usr/bin/passwd |
|
|---|---|---|---|
| alice | — | read, write | read, execute |
| bob | — | read | read, execute |
| root | read, write | read, write | read, write, exec |
Nobody actually stores the full matrix — it is enormous and mostly empty. Real systems store it sliced one of two ways, and the choice has deep consequences:
- Access Control Lists (ACLs) store the matrix by column — each object carries the list of subjects and their rights. This is what POSIX file permissions and
setfacldo. Easy to answer “who can touch this file?”, hard to answer “what can alice touch?” and hard to revoke a subject everywhere at once. - Capabilities store the matrix by row — each subject holds unforgeable tokens (“keys”) naming the objects it may use. Easy to answer “what can this subject reach?”, and easy to delegate, but historically hard to revoke and to audit. Linux capabilities (
cap_net_raw, etc.) and cloud bearer tokens are practical examples.
⚠️ The two slices answer opposite questions cheaply. Many real-world authorization bugs trace back to a team picking the slice that makes their hard question expensive, then “optimizing” with a cache that drifts out of sync with policy.
Design principles
In 1975 Saltzer and Schroeder published a set of design principles that have aged remarkably well. The ones most relevant to access control:
- Least privilege — a subject should hold only the rights it needs, for only as long as it needs them. The single most important principle on this page; almost every privilege-escalation attack is the exploitation of an over-privileged subject.
- Fail-safe defaults — base decisions on permission, not exclusion: deny by default and grant explicitly. An allowlist fails closed; a denylist fails open the moment you forget an entry.
- Complete mediation — every access is checked, every time (the reference-monitor property above). Beware caching a decision and reusing it after the underlying authority has changed.
- Separation of privilege — require more than one condition/key to grant access (the spirit behind two-person control and, loosely, MFA).
- Least common mechanism — minimize shared mechanisms that multiple subjects depend on, since they become shared attack surface.
- Economy of mechanism & Psychological acceptability — keep it simple, and make the secure path the easy path, or users will route around it.
Access control models
How the matrix gets populated and administered is the defining difference between the classic models. Course objective #2 calls out discretionary, mandatory, and originator-controlled by name.
Discretionary Access Control (DAC)
The owner of an object decides who may access it. POSIX file permissions are the canonical example: if you own a file, you can chmod it however you like. DAC is flexible and intuitive, which is exactly why it is everywhere — and also why it is weak: discretion can be abused or tricked. Once bob can read your file, nothing stops bob from copying it and sharing it with the world. DAC cannot enforce a policy that follows the data.
Mandatory Access Control (MAC)
A system-wide policy set by an administrator overrides individual discretion. Subjects and objects carry labels (e.g., Unclassified < Secret < Top Secret), and the kernel enforces the rules regardless of what the file owner wants. SELinux and AppArmor bring MAC to Linux; this is the model behind military multi-level security. MAC can enforce policies DAC cannot — but it is heavier to administer and famously easy to misconfigure (the reflex setenforce 0 is the security equivalent of disabling the smoke detector because it keeps going off).
Role-Based Access Control (RBAC)
Permissions are attached to roles, and users are assigned roles, rather than wiring permissions to individuals. NIST/INCITS standardized this (INCITS 359). Core RBAC has four element types — users, roles, permissions, and sessions — plus optional role hierarchies and separation-of-duty constraints (e.g., the same person cannot hold both “request payment” and “approve payment”). RBAC scales administration enormously: when someone changes jobs you swap their role, not 400 individual grants. It is the dominant model in enterprise IT and is detailed further on the IAM page.
Attribute-Based Access Control (ABAC)
Decisions are computed from attributes of the subject, object, requested operation, and environment, evaluated against policy rules — e.g., “allow if user.dept == file.dept AND time is business hours AND device.is_managed.” NIST SP 800-162 is the reference. ABAC is far more expressive than RBAC (a single rule can replace thousands of role grants) at the cost of being harder to reason about and audit. Its architecture introduces the vocabulary you’ll meet in modern policy engines (OPA, AWS IAM conditions): PEP (enforcement point), PDP (decision point), PIP (information point), and PAP (administration point).
Originator-Controlled (ORCON)
A hybrid the course calls out by name: the originator of the data, not the current owner, retains control over redistribution. “You may read this, but you may not forward it without my permission.” Neither pure DAC (the owner can re-share) nor pure MAC (a fixed label lattice) expresses this cleanly. ORCON is the conceptual ancestor of DRM and of modern information-rights-management / data-loss-prevention systems.
Security models: enforcing a policy goal
Models above describe who administers the matrix; the following describe what security goal the rules are built to achieve.
Bell–LaPadula — confidentiality (“no read up, no write down”)
Designed for military secrecy. With subjects and objects on a lattice of classifications:
- Simple Security Property (“no read up”) — a subject may not read an object at a higher level. A Secret-cleared analyst cannot read Top Secret.
- *-property (“no write down”) — a subject may not write to an object at a lower level. This blocks the leak where a Top Secret process copies classified data into an Unclassified file. Summarized as “write up, read down.”
Biba — integrity (“no write up, no read down”)
The mathematical dual of Bell–LaPadula, protecting integrity instead of confidentiality. A high-integrity subject must not read low-integrity data (it might be corrupt) and must not be written by low-integrity subjects. Think of it as “don’t let untrusted input flow upward into trusted components” — exactly the failure behind countless injection bugs.
Note that Bell–LaPadula and Biba pull in opposite directions. Enforcing both strictly collapses each subject to reading and writing at a single level — a clean illustration of why confidentiality and integrity goals can conflict.
Clark–Wilson and Chinese Wall
- Clark–Wilson models commercial integrity through well-formed transactions (data may only be changed by certified programs) and separation of duty. It is closer to how real accounting/database systems actually protect integrity than Biba’s lattice.
- Chinese Wall (Brewer–Nash) encodes dynamic conflict of interest: once a consultant accesses Bank A’s data, the policy itself denies them Bank B’s. What you may access depends on the history of what you have accessed.
Worked examples on Linux
The abstractions above are not just theory — you use them every time you touch a Unix system. The course VM is Linux, so let’s make each concrete. (Run these on your Kali VM; see User Management for the broader treatment.)
DAC: POSIX permissions
The classic owner/group/other × read/write/execute matrix, sliced as an ACL per file:
$ ls -l report.txt
-rw-r----- 1 alice staff 1240 Jun 17 09:02 report.txt
│└┬┘└┬┘└┬┘ │ └ group: staff (members get r--)
│ │ │ └ other: --- (no access)
│ │ └ group bits: r--
│ └ owner bits: rw- (alice can read+write)
└ regular file
$ chmod 640 report.txt # rw- r-- --- (symbolic: u=rw,g=r,o=)
$ chmod o+r report.txt # grant "other" read -> world-readable now
The three octal digits are one column of the access-control matrix. Because alice owns the file she may relax or tighten it at her discretion — that discretion is what makes this DAC.
DAC, finer-grained: POSIX ACLs
Plain owner/group/other can’t express “and also let bob read it.” That’s where setfacl/getfacl extend the ACL:
$ setfacl -m u:bob:r report.txt # add a named-user entry
$ getfacl report.txt
# file: report.txt
# owner: alice
# group: staff
user::rw-
user:bob:r-- <- bob specifically, beyond group/other
group::r--
mask::r--
other::---
$ setfacl -x u:bob report.txt # revoke bob's entry
Least privilege gone wrong: setuid
A setuid binary runs with the file owner’s identity, not the caller’s. This is how an ordinary user changes their own password (the file /etc/shadow is root-only):
$ ls -l /usr/bin/passwd
-rwsr-xr-x 1 root root 59976 Feb 6 2024 /usr/bin/passwd
↑
's' = setuid: any user running this executes it AS root
Setuid is a deliberate, narrow privilege grant — and a perennial escalation target. A setuid-root program with a single command-injection or path bug hands the attacker root. find / -perm -4000 to enumerate them is one of the first things both auditors and attackers run. This is the principle of least privilege in tension with usability.
Capabilities: slicing root into pieces
Linux capabilities break the all-or-nothing root into ~40 discrete rights — a row-sliced (capability-style) refinement. Instead of making a packet sniffer setuid-root, grant only the one right it needs:
$ setcap cap_net_raw,cap_net_admin+eip /usr/bin/dumpcap
$ getcap /usr/bin/dumpcap
/usr/bin/dumpcap cap_net_raw,cap_net_admin=eip
Now dumpcap can open raw sockets without being able to read /etc/shadow, overwrite system files, or anything else root could do. Compromising it yields packet capture, not the box. That is least privilege made operational.
MAC: SELinux contexts
On an SELinux system (getenforce → Enforcing), every subject and object carries a security context the kernel checks in addition to DAC. DAC can say “yes” and MAC can still say “no”:
$ ls -Z /var/www/html/index.html
unconfined_u:object_r:httpd_sys_content_t:s0 index.html
└─ type: web content the httpd domain may read
$ ps -eZ | grep httpd
system_u:system_r:httpd_t:s0 1337 ? 00:00:02 httpd
└─ the web server runs confined in the httpd_t domain
Even if a misconfiguration made index.html mode 0777 (DAC wide open), the httpd_t process still cannot write to a _t type its policy forbids, and cannot read /etc/shadow (shadow_t). That confinement is precisely why a web-app compromise on a hardened host so often fails to escalate — the policy is mandatory and the file owner cannot waive it. (This is also why blindly running setenforce 0 to “fix” a permission error throws away your strongest containment layer.)
How attackers think about access control
Most real-world compromise is, at bottom, an access-control failure:
- Privilege escalation — turning a low-privileged foothold into a high-privileged one by finding an over-privileged setuid binary, a writable service file, a too-broad
sudorule, or a capability that shouldn’t have been granted. (Least privilege is the defense.) - The confused deputy — tricking a more-privileged program into misusing its authority on your behalf. CSRF, SSRF, and many path-traversal bugs are confused-deputy problems; capability systems exist partly to prevent them.
- Broken access control — consistently at or near the top of the OWASP Top 10: missing function-level checks, insecure direct object references (IDOR), forced browsing. The reference monitor was not always invoked.
- TOCTOU (time-of-check to time-of-use) — the check passes, then the object changes before use. A failure of complete mediation over time.
When you model threats (Threat Modeling) the recurring question is simply: for each asset, which subjects can perform which operations, and is anything more permissive than it needs to be?
Key takeaways
- Authorization (what you can do) is distinct from authentication (who you are), and is enforced by a reference monitor that must be always-invoked, tamperproof, and verifiable.
- All authorization is conceptually an access control matrix, stored as ACLs (by object) or capabilities (by subject) — a choice that determines which questions are cheap to answer.
- DAC, MAC, RBAC, ABAC, and ORCON differ in who controls the policy; Bell–LaPadula, Biba, Clark–Wilson, and Chinese Wall differ in what goal the policy enforces.
- Least privilege and fail-safe defaults are the principles you will reach for most; the majority of escalation attacks are violations of them.
- On Linux you meet these directly: POSIX permissions and ACLs (DAC), setuid and capabilities (privilege granting), and SELinux/AppArmor (MAC).
References
- J. H. Saltzer and M. D. Schroeder, The Protection of Information in Computer Systems, Proc. IEEE, 1975 — the eight design principles. https://www.cs.virginia.edu/~evans/cs551/saltzer/
- B. W. Lampson, Protection, 1971 — origin of the access control matrix. https://www.cs.utexas.edu/~shmat/courses/cs380s/lampson74.pdf
- D. E. Bell and L. J. LaPadula, Secure Computer Systems: Mathematical Foundations (MITRE, 1973) — Bell–LaPadula model. https://csrc.nist.gov/csrc/media/publications/conference-paper/1998/10/08/proceedings-of-the-21st-nissc-1998/documents/early-cs-papers/bell76.pdf
- NIST/INCITS, INCITS 359 — Role Based Access Control and the NIST RBAC project. https://csrc.nist.gov/projects/role-based-access-control
- V. C. Hu et al., Guide to Attribute Based Access Control (ABAC) Definition and Considerations, NIST SP 800-162. https://csrc.nist.gov/pubs/sp/800/162/upd2/final
setfacl(1)/getfacl(1)man pages (Linuxaclpackage). https://man7.org/linux/man-pages/man1/setfacl.1.htmlcapabilities(7)— overview of Linux capabilities. https://man7.org/linux/man-pages/man7/capabilities.7.html- The SELinux Project documentation. https://github.com/SELinuxProject/selinux-notebook/blob/main/src/toc.md
- OWASP, A01:2021 – Broken Access Control. https://owasp.org/Top10/A01_2021-Broken_Access_Control/
Related course pages: User Management · Identity and Access Management · Working with Files · Threat Modeling · Application Security
🛠️ Maintenance note: verify the
setuid/setcaptranscript output and the SELinux context strings against the current Kali image each term — capability syntax (+eip) and default SELinux types are stable, but binary paths/versions drift. The OWASP Top 10 is re-versioned periodically (current cited edition: 2021); check for a newer edition before each term.