Apertis reference implementation provides packages and images geared towards development, allowing more flexibility than actual products. This guidance is targeted towards teams building products with Apertis to aid them with “hardening” the general-purpose development Apertis image/packages to reduce the attack surface on products. This document also lightly touches on measures that can be taken to physically harden a device.
The procedures detailed below reduce the attack surface of the Apertis image and in some cases will provide improvements to other facets such as storage optimization and boot performance which are also likely to be important to product teams.
The aim with hardening is to close off any avenues that may be used to alter the operation of the device, be that with or without the knowledge and consent of its owner. This may take the form of malicious hacking by a third party with the aim of extracting something from the owner or the owner trying to modify the device to operate in ways that it wasn’t designed to and which may violate legally enforced regulations. In essence this is done by removing or disabling any functionality that isn’t critical to the operation of the device.
Many of the techniques highlighted below will require thought to be given during device design. We thus advise that security be considered from early on and not left too late in the design process, when a lot of the techniques may not be able to be applied without significant effort and changes to the devices design.
During early development of Apertis, research was carried out looking at the various threat models which may apply to Apertis, the security solutions adopted by popular platforms and recommendations of how best to approach this in Apertis.
An adventurous user will not be stopped by “warranty void if broken” stickers and security or obscure headed screws. Depending on your threat models, it may be necessary to:
- Ensure the hardware provides functionality to securely store cryptographic. Many ARM SoCs will have such functionality built in, on x86 systems design in a TPM chip.
- Don’t expose unneeded ports and buses as these might be usable as part of a compromise.
- Don’t route out a serial port for use as a debug interface on the finally release of the PCB. As this is likely to be very useful for an attacker trying to break into the device.
- Ball grid array (BGA) Flash parts make it harder to short pins to block/corrupt reading of the flash. This is a common technique for forcing a device into a debug mode.
- Ensure the bootstrapping configuration of the SoC is provided and stops fallback to boot options such as network/USB boot if supported by the hardware. This can enable the user to provide alternative boot firmware.
- Ensure any One Time Programmable (OTP) Fuses that may be available to limit boot options and debugging interfaces (such as JTAG) are blown prior to shipping device.
The boot firmware covers the software that runs after boot and is responsible for initial hardware configuration and loading the Linux kernel. This is typically UEFI on x86-based systems and U-Boot on ARM and other architectures.
The boot process needs to be guarded against tampering. The ability for a user to compromise the boot process would potentially allow them to modify it and thus gain unwanted access to the device.
Certain common steps can be taken:
- Disable any alternative boot mechanisms to avoid these being used.
- Remove/disable functionality providing interactive control.
- Enable functionality to only run signed binaries.
ARM Based Systems
There are a large number of boot firmwares available for ARM based systems, but in Apertis we standardize on U-Boot where possible and hence will discuss that here.
U-Boot provides an interactive command-line interface enabled. This opens the
door for attacks, such as like with the
Depthcharge tool. The
command-line interface can be disabled by ensuring that the
option is not enabled in the U-Boot configuration.
If fully disabling the command-line interface is undesirable and even when disabling it, consider minimizing the functionality provided by the U-Boot build to just those that are required to boot the expected configuration. This reduces the commands that can be leveraged to alter the boot process.
U-Boot can store environment variables in a number of places to allow these to be changed and saved for later boots. This ability should be disabled with default environment variables provided by the U-Boot binary to avoid alterations by attackers.
Likewise, U-Boot can utilize boot scripts or configuration stored on the root file system to determine how to boot the system, with scanning being performed to find such scripts or configuration. We advise disabling the ability to boot using boot scripts, though we suggest that the EXTLINUX configuration should still be used (as this allows for clean separation between kernel and firmware packaging, with the configuration needed to boot a specific kernel being provided in the kernel package). The locations scanned for the EXTLINUX configuration should be tightly controlled to avoid attackers being able to force the device to boot from alternative locations, such as removable media.
Secure boot can be implemented in order to ensure only the expected binaries are booted. This requires the binaries booted by the system to be cryptographically signed with a private key that corresponds to a public key that is securely stored on the device so that it can’t be changed. This functionality is implemented differently by different ARM vendors and is sometimes known by different names, for example it is known as High Assurance Boot (HAB) on NXP i.MX processors.
Intel/x86 Based Systems
Most x86 based systems now utilize UEFI. Such systems:
- Should have the UEFI Shell disabled.
- Consider configuring the device to use Secure Boot so that it will only boot correctly signed binaries.
A first step in hardening the Linux kernel is to evaluate the drivers and features that are enabled (including as modules) and tailor the kernel configuration to build just what is needed by the device. This reduces or removes the ability for an attacker to connect extra hardware that could provide extra unintended access (such as USB network devices that may enable extra binaries to be uploaded). There are also many features that the kernel may have enabled to support various workloads, but present a minor security risk which can be closed if these features are not required. As an added advantage, disabling unrequired options may make the kernel boot faster (less to load into memory if nothing else) and will require less storage space.
Beyond this, the kernel provides many configuration settings that can be used to harden it, protecting against certain attack vectors. Many of these are detailed as part of the Kernel Self Protection Project, with further options detailed by the kconfig-hardened-check tool.
Effort should be taken to understand the impact that disabling features or enabling security features will have on your use case. Many of the security features will incur runtime overhead and some options that these tools suggest to be disabled may be required for certain use cases. The device will need to be tested and characterized after any changes are made to ensure that the device still performs as expected.
Most if not all software contains bugs, with an industry average of 15 to 50 errors per 1000 lines of code. These bugs typically don’t become apparent during “normal” usage, hence why they manage to escape any testing that is performed, but can prove to be exploitable by someone looking for ways to break into a device, by using the code outside of it’s normal parameters.
In order to reduce the number of opportunities, it is advisable to minimize the software installed on a device to that which is necessary.
Minimize Application Privileges
Some of the software installed on a device may have bugs that can be used to cause it to perform actions it wouldn’t normally perform or for someone that wouldn’t normally perform them for. This is especially problematic where applications have been given increased privileges, such as being configured to run with root privileges or being given certain capabilities, thus enabling privilege escalation.
This can be mitigated to some degree by not running applications as root and
thus it is advised to not run software as root unless absolutely necessary.
Finer grained privileges can be given to applications via Linux
control of these capabilities can be
enforced via the systemd,
This can sometimes be further enhanced by splitting out privileged functionality to system services and using D-Bus to communicate between the privileged system service and unprivileged user application.
It is important that authentication used to identify the device and users of the device are kept secret. A need to authenticate may be present in many aspects of an Apertis based device:
- To authenticate users of the device
- Gaining access to protected download services
- Using online services associated with the device
- Accessing encrypted storage provided by the device
- Signing of binaries as part of trusted boot
These features may have been implemented in Apertis as part of a demo provided by Apertis and thus will have been signed using a key or password provided for the purposes of demonstrating the functionality. Such credentials should be changed to custom values.
Default passwords associated with the device should be unique to each unit produced and not shared between all units. Such passwords are typically easily found in the device literature (such as the common “admin, admin” username and password combination), frequently don’t get changed by most users and this results in lots of devices being let running with poor security. It is far better to implement better security from the outset.
Where keys need to be stored on the device for authentication with remote services, these should be stored securely on the device, not hard coded into the application or left on storage that could become accessible when the device is attacked. This can be encrypting data stored on the device, or more rigorously by using a Trusted Execution Environment.
Finally, it is not expected that Apertis powered devices will require users to
access the root account. The reference images rely on
sudo for access to a a
privileged state and thus the root password is locked (the root password field
contains the invalid password
*, ensuring no one can login using root
directly using a password).
- Don’t leave a terminal available on a serial port, even if this is a hidden debug port. These can end up providing a way to access the device.
Storing user data unencrypted on a device leaves such data open to being extracted. If sensitive data is expected to be data stored on the device, it is advised that this data is stored on an encrypted partition.
Unless necessary, disable automounting of USB storage, if this is necessary (such as part of an offline update mechanism) perform plenty of validation on the USB storage before trusting anything found on it.
Ensure use of strong user passwords where relevant, the
pam_cracklib.somodule can be used in the PAM configuration to enforce password requirements.
If multiple users are expected to use the device, consider the guidance on multi-user setups.
Ensure that Discretionary Access Control (DAC) is properly configured so that users can’t access each others home directories.
Sandboxing applications and services
Sandboxing utilizes the features provided by Linux to isolate applications and services from each other, allowing configuration to be provided to restrict access by a process to parts of the system or restricting access to only predefined parts. This reduces the impact that a compromised application or service can have on the running of the system as a whole.
Apertis provides 2 complementary tools that can be used to configure such sandboxing:
- Applications can be restricted via the use of AppArmor profiles, a form of Mandatory Access Control, enabling access from specific processes to files, sockets, d-bus communication and IPC to be restricted.
- systemd provides sandboxing functionality which can be used to alter the environment in which the process is run.
Network and firewalls
A network interface provides a potentially large attack surface for an attacker, it can also prove useful to an attacker even if it’s not the primary route used to access the device. There are a number of measures that can be taken to protect such interfaces when they form part of the devices functionality:
- Ensure there are not remote access services running that don’t need to be provided (such as telnet, rlogin, sshd, etc).
- Do not use remote services that require the use of plain text passwords (such as telnet and ftp).
- Ensure that the network is well firewalled using iptables rules. This should be done for both the ingress and egress of data to both protect the device and ensure that data from the device can’t be sent back to the attacker should it be compromised.
- Ensure that communications with network services are encrypted to reduce the risk of leaking sensitive information and to provide authentication between the device and the service.
Upgrades should have their authenticity verified before being installed to guard against attackers crafting modified updates. This is handled as part of the Apertis encrypted updates support.
If rollback support is provided, to return to a known working state should an update seem to fail, logic should be employed to stop rollbacks from being forced once the update has been marked as successful to stop downgrade attacks. This is provided by the Apertis OSTree updates and rollback support.
Ensure that devices regularly check for new updates, with either updates being applied automatically or notify the user of the availability of new updates.