AppArmor
AppArmor can be used to define policies for programs. It can be used to define access controls beyond the permissions of the user.
AppArmor is path-based: the target and the restrictions are paths.
$ sudo apt-get install apparmor apparmor-utils
Use the command aa-genprof
to generate a policy for a program. The command aa-complain
can be used to monitor violations.
To check if there is an apparmor policy in place:
$ cat /proc/self/attr/current
π unconfined
means there is no apparmor.
AppArmor With Docker
AppArmor is commonly used with docker. Given, my_apparmor_conf
:
#include <tunables/global>
profile docker_apparmor flags=(attach_disconnected,mediate_deleted) {
#include <abstractions/base>
# Allow them to execute commands
/bin/** ix,
/usr/bin/** ix,
# Forbid access to the flag
/ r,
/** r,
deny /flag.txt r,
}
The following Dockerfile
:
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y apparmor bash
WORKDIR /home/dummy
RUN cp /bin/bash bash
RUN echo "flag{you_found_me}" > /home/dummy/flag.txt
Run these commands:
$ docker build -t apparmor_dummy .
$ sudo apparmor_parser -r ./my_apparmor_conf
$ docker run -it --rm --security-opt "apparmor=docker_apparmor" apparmor-dummy
And the flag should be neither readable nor modifiable.
AppArmor Bypasses
Unconstrained Mode
Some configurations may allow executables or libraries to be loaded in unconstrained mode: the policy is not applied on them.
/usr/bin/head ux,
/lib/x86_64-linux-gnu/ld-*.so mrux,
...
You need to find a way to exploit them:
root# cat flag.txt
cat: flag.txt: Permission denied
root# head flag.txt
flag{you_found_me}
root# /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 cat flag.txt
flag{you_found_me}
Nested Profiles β Broad Rules
If a profile is applied on a specific executable, the rules of the parent may be overridden by the new profile.
profile docker_apparmor flags=(attach_disconnected,mediate_deleted) {
/tmp/bash px -> custom_apparmor,
deny /flag.txt r,
}
profile custom_apparmor flags=(attach_disconnected,mediate_deleted) {
# The rule on /flag.txt is overriden
/ r,
}
Mount Permission
More on this later. Refer to the unshare
command.
mount,
Nested Profiles β Lax File Permissions
If we have enough permissions to replace an executable, we may be able to create an unconstrained executable.
Assuming we are forced to use a constrained executable /opt/wrapper
, and other executables are not constrained.
/opt/wrapper px -> wrapper_profile,
If we have write access to /opt/wrapper
, we can link it to an unconstrained executable and effectively bypass the wrapper_profile
.
$ ln -s /bin/bash /opt/wrapper
$ exit # and connect back or whatever you did to get in