Cybersecurity Lab
PW3 — Access Control Models
Implemented and compared DAC, RBAC, MAC, and ACLs on a single Linux host — chmod/chown, group-based RBAC, an AppArmor 4.1.7 profile, and setfacl/getfacl — each tested with real user accounts.
Objective
Configure four access control models on one Linux host and establish, by testing rather than assertion, how they differ in who holds the authority to decide permissions.
Tools Used
Steps Performed
- Configured DAC with ownership and permission bits on a file owned by alice, and tested read and write as bob.
- Configured RBAC with hr_group and finance_group, directory ownership, and modes 770 and 750.
- Identified AppArmor as the MAC framework in use and confirmed SELinux was absent.
- Installed apparmor-utils and apparmor-profiles, taking the host from zero profiles to 135 loaded.
- Wrote and enforced a custom AppArmor profile confining a purpose-built hrviewer binary.
- Applied named POSIX ACL entries with setfacl and verified them with getfacl.
Key Findings
- Under DAC nothing prevented alice from granting bob write access at any moment with chmod 646 — the control depends entirely on the owner's judgement.
- The decisive MAC test: root read the file successfully via cat but was denied via the confined hrviewer, with the kernel recording removal of CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH.
- AppArmor confines programs, not users — it has no native concept of a per-user rule, so the user-specific denial required an ACL, which belongs to the discretionary family.
- The ACL mask is a ceiling rather than a grant, and a conventional chmod adjusts the mask, silently reducing the rights of named entries.
Contents
Lessons Learned
- The four models are separated by the source of authority: DAC and ACLs are discretionary, RBAC is administrative, MAC is mandatory.
- A MAC framework that is installed but carries no policy provides no protection — a gap that is common in practice.
- The -a flag on usermod is essential; without it, -G replaces every group and can remove a user from sudo.
- The trailing plus sign in a directory listing is the only visible sign of an extended ACL, which is why ACLs are overlooked during audits.
Future Improvements
- Develop the AppArmor profile in complain mode first and promote it to enforce once the log is clean.
- Combine RBAC as the foundation with ACLs for exceptions and MAC on the highest-value systems.
- Audit ACL masks periodically, since a later chmod can silently reduce effective rights.
References
- AppArmor documentation — Ubuntu Server Guide
- POSIX 1003.1e draft 17 — Access Control Lists
- NIST RBAC model — Role-Based Access Controls (Ferraiolo & Kuhn)
Overview
This report implements and compares four access control models on a single Linux host. The models differ principally in one respect: who holds the authority to decide permissions.
| Model | Who decides | Mechanism used |
|---|---|---|
| DAC | The resource owner | chmod, chown |
| RBAC | The organisation / administrator | group membership |
| MAC | System security policy | AppArmor profile |
| ACL | Owner or administrator, per user | setfacl, getfacl |
Each model was configured, tested with real user accounts, and the outcome recorded. All testing was performed using sudo -u, which executes a command under another user's identity without requiring an interactive login session.
Section 1: Discretionary Access Control (DAC)
Discretionary access control means that the owner of a resource decides who may access it, at their own discretion. This flexibility is the model's defining characteristic and also its principal weakness.
1.1 Configuration — Two users were created, and a file was created under alice's ownership with permissions allowing bob read-only access:
sudo useradd -m -s /bin/bash alice
sudo useradd -m -s /bin/bash bob
sudo passwd alice
sudo passwd bob
echo "HR salary data - confidential" | sudo tee /corp/alice_file.txt
sudo chown alice:alice /corp/alice_file.txt
sudo chmod 644 /corp/alice_file.txt
-rw-r--r-- 1 alice alice /corp/alice_file.txtThe mode 644 grants the owner read and write, the group read only, and all other users read only. Bob is neither the owner nor a member of alice's group, so he is evaluated against the others field and receives read access without write.
1.2 Testing
sudo -u bob cat /corp/alice_file.txt
-> HR salary data - confidential (granted)
sudo -u bob bash -c 'echo "bob was here" >> /corp/alice_file.txt'
-> bash: /corp/alice_file.txt: Permission denied (denied)
sudo -u alice bash -c 'echo "alice edit" >> /corp/alice_file.txt'
-> file grew from 30 to 41 bytes (granted)1.3 Analysis — Bob could read the file but not modify it, and alice could modify her own file. The results confirm that the permission bits were enforced as configured.
The significant observation, however, concerns what was not prevented. Alice could grant bob write access at any moment by running chmod 646, or transfer ownership entirely with chown. No system-level policy prevents this, and no administrator approval is required. Under DAC, the security of a resource depends entirely on the judgement of whichever user happens to own it.
This is why DAC scales poorly in an organisational setting. Every file represents an independent decision by an individual owner, and there is no central mechanism to verify that those decisions are consistent with policy.
Section 2: Role-Based Access Control (RBAC)
Under RBAC, permissions attach to roles rather than to individuals. A user obtains access by holding a role, and loses it by leaving that role. The permissions on the resource itself never change.
2.1 Configuration
sudo groupadd hr_group
sudo groupadd finance_group
sudo usermod -aG hr_group alice
sudo usermod -aG finance_group bob
groups alice -> alice : alice hr_group
groups bob -> bob : bob hr finance_groupThe -a flag is essential. Without it, usermod -G replaces every group a user belongs to rather than appending, which can remove a user from administrative groups such as sudo and lock them out of the system.
sudo mkdir -p /corp/hr_docs /corp/finance_docs
sudo chown root:hr_group /corp/hr_docs
sudo chown root:finance_group /corp/finance_docs
sudo chmod 770 /corp/hr_docs # HR: full access
sudo chmod 750 /corp/finance_docs # Finance: read-only
drwxrwx--- 2 root hr_group /corp/hr_docs
drwxr-x--- 2 root finance_group /corp/finance_docs2.2 Testing
| User | Directory | Action | Result | Reason |
|---|---|---|---|---|
| alice | /corp/hr_docs | create | Granted | Holds hr_group; group bits rwx |
| bob | /corp/hr_docs | create | Denied | No role; falls to others (---) |
| bob | /corp/finance_docs | list | Granted | Holds finance_group; r-x permits read |
| bob | /corp/finance_docs | create | Denied | Group bits r-x — no write |
2.3 Analysis — The contrast with Section 1 is the substance of this section. In DAC, bob was granted read access by editing the permission bits of one specific file. In RBAC, alice was granted write access to an entire directory by adding her to a group — the directory's permissions were never modified for her individually.
The consequence is that the model scales. If fifty additional employees joined the HR department, the permissions on /corp/hr_docs would not change at all; only group membership would. Access decisions are made once per role rather than once per person per resource.
The third and fourth test results are also worth noting together. Bob is a member of finance_group and was still denied write access to the finance directory, while his listing of the same directory succeeded. Group membership determines which of the three permission sets applies to a user; the bits within that set determine what is permitted. Membership is necessary but not sufficient.
Section 3: Mandatory Access Control (MAC)
Mandatory access control differs from the previous two models in one decisive respect: the resource owner cannot override the policy. Under DAC and RBAC, an owner or administrator retains the ability to change permissions. Under MAC, the policy is defined at the system level and enforced by the kernel regardless of ownership or privilege.
Identify if SELinux or AppArmor is running.
sudo aa-status
apparmor module is loaded.
Failed to get profiles: 2....
which getenforce sestatus -> not found
SELinux not presentAppArmor is the mandatory access control framework on this system; SELinux is not installed. This is expected, as AppArmor is the standard on Debian-based distributions while SELinux is used on Red Hat derivatives.
The initial status output is itself a finding. The kernel security module was loaded, but no profiles were present, so no mandatory controls were in effect. A MAC framework that is installed but carries no policy provides no protection — a gap that is common in practice.
sudo apt install apparmor-utils apparmor-profiles -y
sudo systemctl enable --now apparmor
sudo aa-status
135 profiles are loaded.
15 profiles are in enforce mode.
44 profiles are in complain mode.After installation, 135 profiles were active. AppArmor distinguishes enforce mode, in which violations are blocked, from complain mode, in which violations are logged but permitted — the latter being used to develop and test a profile before enforcing it.
Create and enforce a rule that denies access even where DAC/RBAC would allow it.
AppArmor confines programs rather than users. A profile constrains what a given executable may do, irrespective of who runs it. A custom profile was therefore written for a purpose-built program, denying it all access to the HR directory:
/usr/local/bin/hrviewer {
#include <abstractions/base>
#include <abstractions/bash>
/usr/local/bin/hrviewer r,
/bin/bash rix,
/usr/bin/cat rix,
deny /corp/hr_docs/** rwklx,
}
sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.hrviewer
sudo aa-enforce /usr/local/bin/hrviewer
-> Setting /usr/local/bin/hrviewer to enforce mode.3.1 Evidence of Mandatory Enforcement — The test was run as root, the account that bypasses all discretionary permissions:
=== TEST 1: root via normal cat (DAC) ===
sudo cat /corp/hr_docs/alice_test.txt
-> CONFIDENTIAL - HR payroll records (granted)
=== TEST 2: root via confined hrviewer (MAC) ===
sudo /usr/local/bin/hrviewer /corp/hr_docs/alice_test.txt
-> cat: Permission denied (denied)The same user reading the same file obtained opposite results depending on which program performed the read. This is the essential demonstration of mandatory access control: the policy applied to the process, not to the user, and root's privileges did not override it.
The kernel audit log identifies precisely what was blocked:
apparmor="DENIED" operation="capable" capability=2 capname="dac_read_search"
apparmor="DENIED" operation="capable" capability=1 capname="dac_override"CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH are the two Linux capabilities that allow root to disregard file permission checks. AppArmor removed them from the confined process. The kernel is therefore recording, in its own audit trail, that the mandatory policy overrode the discretionary privileges of the most privileged account on the system. Neither DAC nor RBAC can produce this outcome, because under both models root is unconditional.
3.2 User-Specific Denial and a Note on Model Boundaries — The assignment requires a rule denying a specific user. AppArmor has no native concept of per-user rules, because its unit of confinement is the executable rather than the identity. The user-specific denial was therefore implemented with a deny ACL:
sudo setfacl -m u:bob:--- /corp/hr_docs
sudo -u bob ls /corp/hr_docs
-> ls: cannot open directory: Permission denied
getfacl /corp/hr_docs
user::rwx
user:bob:---
group::rwx
other::---This distinction should be stated plainly rather than glossed over: an ACL belongs to the discretionary family, not to MAC. Bob was denied by an entry that the directory's owner could remove at will, whereas the AppArmor denial above could not be removed even by root without editing the system policy. The two mechanisms produce a superficially similar result through fundamentally different authority models.
Section 4: Access Control Lists (ACLs)
Standard Unix permissions provide exactly three permission sets: owner, one group, and everyone else. A requirement such as "alice may write, bob may only read, and no one else has access" cannot be expressed within three sets without creating an additional group for each combination. Access control lists remove this constraint by permitting an arbitrary number of named user and group entries on a single object.
4.1 Configuration — The deny entry from Section 3 was first removed so that it would not affect these results:
sudo setfacl -x u:bob /corp/hr_docs
sudo setfacl -m u:alice:rwx /corp/hr_docs
sudo setfacl -m u:bob:r-x /corp/hr_docs
getfacl /corp/hr_docs
# owner: root
# group: hr_group
user::rwx
user:bob:r-x
user:alice:rwx
group::rwx
mask::rwx
other::---4.2 Testing
sudo -u alice touch /corp/hr_docs/acl_alice.txt -> created (rwx)
sudo -u bob ls -l /corp/hr_docs -> listed (r-x)
sudo -u bob touch /corp/hr_docs/acl_bob.txt -> denied (no w)
ls -ld /corp/hr_docs
drwxrwx---+ 2 root hr_group /corp/hr_docsEach result matched the configured entry. The trailing plus sign in the permission string is the indicator that an object carries an extended ACL; it is the only visible sign in a standard directory listing, and its absence is a common reason ACLs are overlooked during an audit.
4.3 The Mask Entry — The mask::rwx line is not a permission grant but a ceiling. It defines the maximum rights that any named user or named group entry can be granted. If the mask were set to r--, the entry user:alice:rwx would still be listed, but alice would effectively hold only read access, and getfacl would append an #effective: comment to indicate the reduction.
This behaviour is the most frequently misunderstood aspect of POSIX ACLs, because the listed entry and the effective permission can differ. It is also the mechanism by which a conventional chmod on a directory carrying an ACL can silently reduce the rights of named entries, since chmod adjusts the mask rather than the individual entries.
Section 5: Objectives (Disclosure, Integrity, Confidentiality)
| Model | Primary objective | How it was enforced in this practical |
|---|---|---|
| DAC | Integrity (weakly) | Bob could read alice's file but not alter it, protecting the content from unauthorised modification. The guarantee is weak because alice could revoke or extend the restriction at any time. |
| RBAC | Confidentiality via roles | Bob was denied access to /corp/hr_docs because he does not hold the HR role. Non-disclosure is enforced by role membership rather than by rules about individuals, so it holds as the organisation grows. |
| MAC | Confidentiality (strongest) | The AppArmor profile denied access even to root, whose discretionary privileges were explicitly stripped by the kernel. This is the only model tested that constrains the most privileged account. |
| ACL | Confidentiality, granular | Alice received rwx and bob r-x on the same directory simultaneously — a distinction the three standard permission sets cannot express. Precision is high, but access is recorded per object rather than centrally. |
The models can be separated by the source of authority. DAC and ACLs are discretionary: the owner decides, and can change that decision unilaterally. RBAC is administrative: the organisation defines roles, and users obtain access by holding them. MAC is mandatory: the system defines the policy and no user, including root, may override it at runtime.
The evidence in Section 3 demonstrates the last point directly rather than by assertion, since root was denied and the kernel recorded the specific capabilities it removed to achieve that.
Section 6: Comparative Analysis
| DAC | RBAC | MAC | ACL | |
|---|---|---|---|---|
| Who defines permissions | Resource owner | Organisation / admin | System policy | Owner or admin |
| Ease of management | Simple at small scale; unmanageable at scale | High — one change per role | Low — requires policy expertise | Moderate; fragments over time |
| Flexibility | High | Moderate | Low by design | High |
| Security strength | Weak — owner can undo any control | Strong | Strongest — root cannot override | Moderate |
| Best supported objective | Integrity | Confidentiality via roles | Confidentiality | Confidentiality, granular |
6.1 Reflection: Which Model Is Most Practical for Enterprises — Role-based access control is the most practical model for enterprise use, and the reason is visible in the difference between Sections 1 and 2 of this practical. In Section 1, bob was granted access by editing the permission bits of a single file. In Section 2, alice was granted access to an entire directory by adding her to a group, and the directory's permissions were never modified. If fifty employees joined the HR department, that configuration would not change at all — only membership would.
DAC cannot survive this scale. It distributes security decisions to individual users, each acting on individual files, with no central point at which policy can be verified. An organisation running on DAC alone has no reliable way to answer what a given employee can access.
MAC is demonstrably stronger, as Section 3 showed by denying root itself, but that strength comes from rigidity. Writing and maintaining policy requires specialist expertise, and every legitimate change requires a policy modification rather than a membership change. It is well suited to high-value systems and poorly suited to general-purpose file sharing.
ACLs handle exceptions elegantly but fragment under growth. Because entries live on individual objects, access ends up distributed across thousands of files with no single place to review it, which makes auditing progressively harder.
RBAC succeeds because it matches how organisations already describe themselves — by job function. It makes the joiner, mover and leaver processes a single membership change, and it allows the question of who can access a resource to be answered by inspecting one group. In practice, enterprises use RBAC as the foundation, ACLs to handle exceptions that do not justify a new role, and MAC on systems where compromise would be most damaging.
Conclusion
Four access control models were configured and tested on a single Linux host. Discretionary access control was implemented through ownership and permission bits, role-based access control through group membership and directory ownership, mandatory access control through an enforced AppArmor profile, and access control lists through named per-user entries.
Every configuration was verified empirically using sudo -u, and all results matched the intended policy. The most significant result was obtained in Section 3, where a confined process was denied access while running as root, and the kernel audit log recorded the removal of the CAP_DAC_OVERRIDE and CAP_DAC_READ_SEARCH capabilities. This provides direct evidence of the defining property of mandatory access control: that the policy is enforced independently of user privilege.