Federico Biancuzzi sits down with French researcher Loïc Duflot and speaks about the System Management Mode attack, how to mitigate it, what hardware is vulnerable, and why we should be concerned with recent X Server bugs.
A feature called System Management Mode, included in modern x86 cpus, opens the way to the land of kernel space and the quest for ring zero.
Could you introduce yourself?
I am a security engineer and researcher for the scientific division of the French National Security Agency, namely the Central Directorate for Information Systems Security in Paris. I am also a second year Phd student in Paris XI University. My research work is mostly focused on the security aspects of interactions between hardware components and software.
What is SMM?
SMM stands for System Management Mode. System Management Mode is one of the four modes of operation of most x86 processors (Intel Xeon, Intel Pentium, or AMD Athlon, for instance). Modern operating systems (such as Linux, BSD, or Windows) run in so-called protected mode. In protected mode, four different processor privilege levels (also called rings) are available, ring zero being the most privileged one and ring three the least privileged. Kernels of operating systems run in ring zero, whereas userspace code runs in ring three. The set of operations available to ring three code is restricted by hardware-enforced security mechanisms such as segmentation, paging, and I/O privilege restrictions. A few security-critical assembly language instructions are also restricted to ring zero operation. Most software security techniques (PaX on Linux, W^X on OpenBSD, and so on) heavily rely upon protected mode enforced mechanisms. On the contrary, System Management Mode is a 16-bit mode of operation dedicated to system maintenance. Code running in System Management Mode is running with full privileges on the system (free access to physical memory and to peripheral devices). Protected mode security mechanisms (paging, segmentation, rings, ...) are not enforced while in System Management Mode.
How did you have the intuition to take advantage of this feature?
The PhD thesis I started one and a half years ago deals with the security issues related to interactions between hardware components and software. I chose to read x86 processor-related documentation to get a better picture of what x86 processors were capable of. I read about the SMM functionality and I shortly noticed that it could be a threat to the global security policy of a system. I chose to look a little closer on the matter.
Is SMM used to do good things as well?
As a matter of fact, SMM is routinely used. Operating systems run in protected mode. But operating systems are not meant to be able to handle very specific hardware events (real time clock-related issues, thermal sensor signals or other external events, the list is really endless). In case such an event occurs, the chipset of the system generates a physical interrupt on the motherboard called an SMI (System Management Interrupt). Upon reception of the SMI, the processor will store its entire context and switch to SMM to run the code - which I'll call the SMI handler from now on.
By context, I mean most processor registers including control registers, task registers, instruction and stack pointers. It runs the code that has been written by the BIOS or motherboard manufacturer to handle the SMI, that is to handle the hardware-specific event that caused the SMI to be generated in the first place. When the handler runs the assembly language instruction "RSM", the processor will restore its entire context and switch back to protected mode.
So, as far as the operating system is concerned, nothing happened. The operating system did not notice the CPU switching to SMM and back to protected mode. Code execution in SMM is transparent from the operating system point of view.
During normal operation of a PC, SMIs are routinely generated, but neither the operating system nor the end user are aware they exist and that the CPU is handling them. I think it is pretty obvious that if such a mode can be misused, consequences on system security can be disastrous. As a matter of fact, the security of SMM comes from the fact that the SMI handler is loaded in memory at boot time by the POST sequence of the BIOS in a memory block called SMRAM located in main system memory.
On systems that are not equipped with a chipset that provides an 8-bit configuration register called the "SMRAM control register" (accessible via PIO accesses), protection of the SMRAM in protected-mode is only enforced by segmentation and paging.
On systems equipped with such a chipset however, the security model is essentially that only code running in SMM should be able to modify the content of the SMRAM. In other words, only the SMI handler should be able to modify itself.
What is the link between SMM and SMRAM control registers?
I said the security model was that only the SMI handler was able to modify itself. That is only a simplified picture. What the "SMRAM control register" does is first it enables the relocation of the SMRAM base address at physical address 0xA0000. This way, the SMRAM address range is in conflict with the legacy video RAM range. So what happens is that if the CPU is running in protected mode, all accesses to the SMRAM range are forwarded by the chipset to the display adapter. And if the CPU is running in SMM, the accesses are redirected by the chipset to the SMRAM in main system memory.
So far, the model seems consistent. The trouble is that there also is a bit called D_OPEN in the chipset. If this bit is set, the chipset forwards all accesses to the SMRAM range to the actual SMRAM. If this bit is set, SMRAM can be accessed whichever the mode of operation of the processor is. It should also be noted that there is in the SMRAM control register a bit called D_LCK. If this bit is set, the SMRAM control becomes read only, and only a hard reset can clear the D_LCK bit. If this bit was set after the D_OPEN bit has been cleared, then it would be impossible to modify the default trusted SMI handler while in protected mode. The trouble is that on all the desktops I tested the D_LCK bit was cleared.
Can you provide a summary of an attack vector?
To sum up what has been said so far, if the chipset encompasses such a "SMRAM control register", the contents of the default SMI handler can be modified at will by software code (with PIO access privileges and write access to the video RAM range). PIO accesses are required to set and clear the D_OPEN bit so that the SMRAM can be accessed while in protected mode. Write access to the video RAM range is compulsory to modify the default SMI handler. Also, a SMI can be generated by accessing PIO registers. So software code with the required privileges can modify the SMI handler at will and trigger the SMI to get full control over the system. It should be clearly noted that this does not require any physical access of any kind to the target system.
The goal of the attack seems to be enabling SMM. To do this in a previous example with OpenBSD, you said that you needed root privileges, and then you took advantage of X Window permissions. Was this path just one way to exploit the flaw, or do you think this is the only way?
It is not exactly true to say that to carry out the attack scheme the attacker requires root privileges. To carry out the general privilege escalation scheme, the attacker needs write access to various Programmed I/O registers and write access to the legacy video RAM range (0xA0000-0xbffff).
So we can assume that, on any system where a process or a set of processes is delegated such privileges, there will always be a way for attackers to exploit the flaw. The "root to kernel" proof of concept scheme on OpenBSD is really only an example. On OpenBSD (as well as on other systems) the X server requires way too many privileges (those required to be able to use the privilege escalation scheme and more). So it seems fair to assume that a vulnerability in the X server could be exploited by remote or local attackers to reach kernel privileges using the general privilege escalation scheme I depicted.
OpenBSD uses a privilege separated Xorg server. Would it stop the attack of a not-root user?
I think this kind of privilege separation is designed exactly to restrict the efficiency of such attacks. If the vulnerability is in the not-privileged part of the X server, it cannot be used to carry out SMM-based attack schemes.
If I'm using the account "simple-user" on a vulnerable hardware running GNU/Linux and XWindows, would I be able to use the privileges of my X processes to launch an attack?
On a Linux system running XWindows, it is theoretically possible for a "simple-user" account to use the privileges of X to launch an attack. The most simple way to do so would be to exploit an hypothetical [not so hypothetical, note from the interviewer] bug in the X server to get to execute random code with X server privileges. Another possibility would be to trick a vulnerability-free X server into accessing SMRAM while it believes it is actually modifying video RAM. This kind of attack seems quite complicated (the most difficult part would be to get the X server to modify the setting of the D_OPEN bit in the chipset) and no such attack has been proved to work at the time.
Why should I use your technique if I'm already root? What should I like to do on that box?
On most existing systems the superuser is granted far too many privileges. On most Linux systems, processes running under root identity can pretty easily escalate to kernel (ring 0 random code execution) privileges. It is the same for administrators on Windows systems. But why should it be so? After all the superuser is only a user (with other privileges than normal users) on the system. So why should he need to modify the inner structure of the operating system? The superuser could for instance only be authorized to modify some system settings.
In fact, many systems offer means of reducing superuser privileges. System administrators may be trusted, but what happens in case of when the superuser account is compromised? OpenBSD designers, for instance, perfectly understood the necessity of restricting superuser privileges. They chose to use the securelevel to do so. The securelevel has really been designed as the last line of defense against a possible compromise of the root account. Securelevel aims to reduce superuser privileges so that it is virtually impossible, even for the superuser, to modify the core of the operating system.
Apart from the secure level mechanism, POSIX capabilities or security labels, that attempt to minimise or separate privileges granted to system- or superuser-owned tasks, should be mentioned. On system using such mechanisms, it is meaningful for an attacker to go from reduced root privileges to kernel privileges. Moreover getting to kernel privileges allows an attacker to load rootkits that will better conceal his actions on the systems, making it harder to identify the system as compromised or to restore it.
In situations where the display server is to be used (i.e. where the machdep.allowaperture variable of the OpenBSD kernel is non-zero), the securelevel mechanism is one of those protections that can be circumvented using the attack scheme from the CanSecWest presentation [PPT].
When you are in SMM, could you read/write the BIOS code, config and passwords?
When the attacker switches the processor to SMM, he can write or read any area in physical memory that is reported as writable/readable by the chipset. This means for instance that he can access the BIOS. So there is no way to prevent the attacker from updating the BIOS (except if it is stored in ROM) if he wants to. But remember that updating the BIOS is not a trivial operation. The attacker has to know how it is done and what he wants to modify.
Can we use SMM to bypass barriers among systems placed by virtualization software such as VMWare or Xen or OpenVZ/Virtuozzo?
That is definitely something that crossed my mind several times. My intuition is that it is possible to bypass virtualisation barriers each time the virtual domain is granted PIO access privileges. I checked that the attack scheme did not work against Xen 2.0 some time ago. Basically, PIO accesses are not possible from invited domains except from domain0. So the attack scheme does not work from domains other than domain0. Domain0 is supposed to be a privileged and trusted domain anyway.
Though it might not be the simplest way to do this, attack schemes using PIO accesses can also theoretically be used to bypass chroot barriers.
Such as a FreeBSD Jail?
On FreeBSD, system calls that grant I/O access permissions are restricted to non-jailed superusers. Therefore, a jailed process should not be able to get the prerequisites for this attack scheme.
Is Windows vulnerable too?
Windows NT, XP, Vista are not vulnerable to this attack scheme since there seems to be no way for ring 3 code to request PIO access privileges.
But, as I said before, if there exists other means to modify SMI handler, then this functionality can be disastrous because execution in SMM is transparent from the operating system point of view.
So we need to find the right mix of vulnerable hardware AND software?
The real trouble with such a scheme is that some hardware are potentially vulnerable, other are not. When the hardware is potentially vulnerable, there are several possibilities:
- The system may not be vulnerable (No PIO accesses).
- The superuser is allowed PIO accesses but there is no restriction of superuser privileges on the system, so the attack scheme is pointless here (Linux).
- The system is vulnerable under some (highly improbable) configuration.
- The list of such configurations can be very long. Bad configurations of GRSecurity under Linux could be vulnerable.
- Some security mechanism (chroot, securelevel, capabilities, virtualisation...) may be circumvented using the attack scheme. Checking each of them on different hardware platforms will be a very difficult task.
All I can tell for the time being is that some configuration are vulnerable, and others are not.
How can we find out if our hardware is vulnerable?
Any x86 processor (whatever the manufacturer is) is theoretically vulnerable as long as it is used along with a chipset encompassing a "SMRAM control register". The few desktops I had the opportunity to test did actually encompass this functionality.
There does not seem to exist any tool to check. The best way is to check in the chipset's documentation or try to read the PIO address usually corresponding to the SMRAM control register.
In the paper [PDF] I saw a schema with an AGP bus for the video card. Is the video memory range still the same if the motherboard has just a PCI Express slot and card?
Yes, the legacy video RAM range is exactly the same for compatibility reasons.
Are other architectures (Sparc, PowerPC, ...) vulnerable?
To be able to carry out the privilege escalation scheme, the attacker needs to be able to write to Programmed I/O ports from userspace. As far as I know this is not possible on architectures other than x86.
I saw this email from Theo de Raadt that talks about other architectures too...
Actually, this email was written by Theo to remind people that they were not to set the allowaperture variable except if they were using the X server. It makes sense to follow this advice even though the system is not running on a x86 architecture (the general feeling that the X server requires too many privileges is not limited to x86 architectures). However, as far as I know only x86 architectures are vulnerable to the SMM-based privilege escalation scheme.
Since the OS is not aware of the CPU switching to SMM, would it be possible writing a tool to warn, or even better block, an attempt to do so?
I don't think it would be a good idea for antivirus to block the CPU from switching to SMM on a computer where the motherboard requires the functionality. What can be done on compliant chipsets is to set the D_LCK bit as early as possible as boot time. But as I said before, it is not always possible. Another idea would be to check the integrity of the SMI handler. This would require antivirus to get a "trusted" version of the SMI handler binary, and to check from time to time that it was not silently modified. Of course, such a countermeasure would still be vulnerable to a "race condition", should the attacker be able to modify the SMI handler and deactivate the integrity check functionality before it can actually check the integrity of the handler.
Is setting the D_LCK bit going to stop "good" features from working too?
Well, it shouldn't. If the D_LCK bit is set, only the SMRAM control register becomes read only. So the processor can handle the SMI anyway. The only difference is that there is no way for software code to modify the default handler except for the handler itself. But again, the operating system is not supposed to modify this handler anyway. However Theo de Raadt told me he noticed that with some laptops, setting the D_LCK bit caused the system to hang or the APM and ACPI to stop working correctly.
Can we say that this is a hardware feature that can be misused by an attacker? Or should we say that the vulnerability is caused by a bad design of software?
The "beauty" of the attack scheme is that it does not exploit any software or hardware bug. Each step of the attack can be considered legal in the operating system security policy. So basically we use legal operations to get to higher privileges and to do something that is against the operating system security policy. So who's to blame? The processor for being able to switch to SMM? The chipset for providing the SMRAM control register? The operating system for providing system calls and pseudo-files that allow userspace code to switch the processor to SMM using hardware mechanisms?
My opinion is that operating system designers (OpenBSD designers for instance) have been aware that delegating Programmed IO access to userspace code could lead to potential security problems. The trouble is that they were forced to provide ways to delegate Programmed IO privileges because such applications as the X server require such mechanisms.
Most of the time, the X server seems to be the only ring 3 application which requires to access Programmed I/O ports. If the X server (or any other application that requires PIO accesses) did not require such privileges, the operating system would not need to provide ways of delegating PIO accesses to userspace. And the overall security level of the system would be much higher.
How can this vulnerability be mitigated?
Concerning the particular proof of concept attack scheme on OpenBSD, a short term solution would be for system administrators to decide that the X server should not be used and to set the machdep.allowaperture variable to 0. Another possible short term solution would be for BIOS manufacturers to set the D_LCK bit of the SMRAM control register of the chipset in the early stages of the boot sequence. This would prevent attackers from being able to run random code in System Management Mode.
But I think the SMM-based privilege escalation scheme is only an example of what can be done with Programmed I/O privileges. Thus we should tackle the core of the problem. And the best solution by far would be for X designers to move the X server to a safer model. For instance, the X server could be split into two different parts. One of them (the one requiring PIO accesses or important privileges on the hardware) could run in kernel mode, providing an abstraction layer to the other one remaining in userspace. The part remaining in userspace would no longer require any particular privilege. As I said, the X server is the only widespread userspace component that requires such privileges as Programmed I/O access. So when the X server moves to a safer model, operating systems will be able to finally dispose of Programmed I/O delegation system calls in their default configuration. I think it is a urgent matter for true security will never be achieved otherwise.
This article originally appeared in Security Focus.
Copyright © 2006, SecurityFocus
Federico Biancuzzi is a freelancer. In addition to SecurityFocus he also writes for ONLamp, LinuxDevCenter, and NewsForge.