AppArmor (Application Armor) is a Linux security module that offers a way to restrict programs’ capabilities with per-program profiles. These profiles can confine the access rights of any process and allow us to take precise control over what resources a process can use. In this post, we’ll explore how to leverage AppArmor to restrict the ubiquitous curl command’s capabilities (as an example) :) .
Before we delve into our example script, let’s take a brief look at what the curl command does. curl is a powerful command-line tool used to transfer data to or from a network server. It supports multiple protocols, including HTTP, HTTPS, FTP, and many more. By default, curl can interact with any URL that you throw at it, making it an incredibly flexible tool. However, in some scenarios, we may need to limit curl’s capabilities for security reasons, and that’s where AppArmor comes into play.
Our example script begins by setting up the AppArmor utilities, if they aren’t already installed, and then proceeds to create an AppArmor profile for curl. The profile path is typically /etc/apparmor.d/usr.bin.curl, adhering to the convention of using the absolute path of the binary with slashes replaced by dots.
The actual profile definition is relatively simple:
/usr/bin/curl {
#include <abstractions/base>
/usr/bin/curl r,
/etc/ld.so.cache r,
/lib/@{multiarch}/lib*.so* mr,
/usr/lib/@{multiarch}/lib*.so* mr,
}
The profile starts with the path of the curl binary and then lists the access permissions for various resources. In this case, it allows curl to read its own binary, the dynamic linker’s cache, and any shared libraries it might need.
The permissions are:
rfor read,mfor memory mapping, and*as a wildcard for any file.
This profile effectively denies all other actions, including network access. As a result, when you try to use curl to access a URL, it will fail because it doesn’t have the necessary permissions.
The script provides two main functions: start and stop. The start function enables the AppArmor profile by removing any disable symlink and loading the profile into the AppArmor kernel module. The stop function, on the other hand, disables the profile by creating a symlink in the disable directory and unloading the profile from the kernel module.
One thing to note is that this profile will block all network access for curl, including TCP and UDP. If you want to allow TCP or UDP access for specific addresses, you would need to include rules like the following in your profile:
network inet tcp,
network inet udp,
This would allow curl to use any TCP and UDP sockets. If you want to restrict it to particular addresses, you can specify them like so:
network inet tcp (to "192.0.2.0/24"),
network inet udp (to "203.0.113.0/24"),
Copy Paste Example:
#!/bin/bash
PROFILE_PATH="/etc/apparmor.d/usr.bin.curl"
function install_apparmor {
if ! dpkg -s apparmor apparmor-utils >/dev/null 2>&1; then
echo "Installing AppArmor and its utilities..."
sudo apt-get update
sudo apt-get install -y apparmor apparmor-utils
fi
}
function create_profile {
cat << EOF > ${PROFILE_PATH}
#include <tunables/global>
/usr/bin/curl {
#include <abstractions/base>
/usr/bin/curl r,
/etc/ld.so.cache r,
/lib/@{multiarch}/lib*.so* mr,
/usr/lib/@{multiarch}/lib*.so* mr,
}
EOF
}
function start {
install_apparmor
if [ ! -f ${PROFILE_PATH} ]; then
create_profile
fi
if [ -L "/etc/apparmor.d/disable/usr.bin.curl" ]; then
sudo rm /etc/apparmor.d/disable/usr.bin.curl
fi
sudo apparmor_parser -r -W ${PROFILE_PATH}
# alternatively, you could use the following command,
# but it offers less control over the profile loading process:
# sudo aa-enforce ${PROFILE_PATH}
}
function stop {
install_apparmor
sudo ln -s ${PROFILE_PATH} /etc/apparmor.d/disable/
sudo apparmor_parser -R ${PROFILE_PATH}
# alternatively, you could use the following command,
# but apparmor_parser provides more detailed control:
# sudo aa-disable ${PROFILE_PATH}
}
case "$1" in
start)
start
;;
stop)
stop
;;
*)
echo "Usage: $0 {start|stop}"
esac
And to add internet you add the inet options described above:
/usr/bin/curl {
#include <abstractions/base>
network inet tcp,
network inet6 tcp,
network inet udp,
network inet6 udp,
/usr/bin/curl r,
/etc/ld.so.cache r,
/lib/@{multiarch}/lib*.so* mr,
/usr/lib/@{multiarch}/lib*.so* mr,
}
Remember that AppArmor provides a powerful way to control what each process on your system can do. However, with great power comes great responsibility. Misconfiguring an AppArmor profile can lead to unexpected behavior or system instability, so always be careful and test your profiles thoroughly.
Buy Me a Coffee