Filed under: Security
ARDAgent setuid allows root access, but there's a sort-of fix
Updates: See the end of the post for current info.
We've been getting quite a bit of email since yesterday's anonymous Slashdot posting of a security problem with ARDAgent on Mac OS X 10.4 and 10.5, and there's plenty of Twittering going on over the issue.
Here's the deal: ARDAgent is the application that responds to Apple Remote Desktop remote administration requests, screen sharing and the like; you can find it in /System/Library/CoreServices/RemoteManagement on 10.5 machines.
In order to go do the voodoo that you do so well when you're administering remote Macs, ARDAgent needs to be 'setuid root' -- it needs to run with the privileges and access that belong to the system administrator, the same way you do temporarily whenever you unlock a system preference or install an application with Apple's installer. This is normal and expected behavior.
What's not so normal and expected is that ARDAgent will execute the 'do shell script' AppleScript command (on behalf of remote admins, normally, who need to run Unix commands from time to time). The problem here is that since ARDAgent is setuid root, any subprocess it launches is running with administrator permissions, and in fact with the right malicious scripting here it would be possible to do a great deal of damage. Granted, in order to activate this vulnerability the attacker would either have to be at the machine, or logged in remotely with the same account that is currently in use... or just convince the user to run a malicious downloaded application. Yikes.
The good news is, there's a very simple workaround (courtesy of the fine folks at Intego -- note that if you actually use VirusBarrier to disable ARD's shell script access as they recommend, and your machine is managed remotely, your administrator may take some umbrage). It turns out that if ARD's remote access features are turned on, via the Sharing pane in System Preferences, you're clear. Even if there aren't any users permitted to administer your machine, the 'do shell script' command that ARDAgent runs is neutered and cannot be exploited in this fashion. Most home and small office Macs wouldn't normally have this turned on, but once you activate it you should be protected. Our basic instructions can be found here. [See update below -- turns out the fix may not protect you fully.]
Stay safe out there!
Update: Thomas Ptacek of Matasano weighs in on this flaw and offers some additional workarounds, but he doesn't seem overly concerned.
Update 2: Commenter (and Mac OS X security pro) Zack Smith, along with Chris Barker, points out that it's possible to kill the ARDAgent process and immediately run the osascript command, which bypasses the protection that running ARDAgent under launchd provides. Under those circumstances an attacker or someone sitting at your machine could still run commands as root, much to your chagrin.
To prevent this, one approach is to change the permissions on the ARDAgent application bundle -- note that this will both break with future system updates or permissions repairs, and may adversely affect administrative access to your machine from legitimate managers:
sudo chmod -R u-s /System/Library/CoreServices/RemoteManagement/ARDAgent.app
You can also simply archive and remove ARDAgent.app if you don't plan to be managed by anyone.
Thanks to everyone who sent this in, and thanks to Intego for pointing out the workaround.

![TUAW [Cafepress]](http://www.blogsmithmedia.com/www.tuaw.com/media/tuaw-cafepress-promo.png)


Reader Comments (Page 2 of 3)
Michael Rose said 5:22PM on 6-19-2008
Replying to Chris/Zack's note about killing the process...
$kill 5964; osascript -e 'tell app "ARDAgent" to do shell script "/usr/bin/whoami"'
23:56: execution error: ARDAgent got an error: Connection is invalid. (-609)
Doesn't matter what I do, it never comes back with 'root' as the response when Remote Management is enabled. Perhaps the behavior is different on Tiger, have only been checking on Leopard this afternoon.
Zack said 5:20PM on 6-19-2008
Actually if you run the command right after you kill it using basic shell syntax like ";", launchctl has not had enough time to relaunch it and so it is relaunched as root ( because the Apple Script will launch it if its not already running ), it does this every try on my Mac Book but even if it didnt you could just loop it until it worked in your exploit code, turning on ARD will not fix this exploit.
Zack said 5:31PM on 6-19-2008
michael try kill -9 , thats what I originally told chris but he did not c/p right ;)
Reply
Zack said 5:32PM on 6-19-2008
Also you haver to execute this command as the console user, but that basically what the exploit implies anyway ( someone is logged in and clicks on somthing nasty)
Reply
Michael Rose said 5:33PM on 6-19-2008
Zack, if the osascript command is launching it, it should come up in my user context and not as root. Are you sudo-ing the command?
As noted, I can't reproduce the kill/relaunch approach suggested above, but it would not surprise me if there are other ways around this fix. Changing permissions on ARDAgent is fine if you're not actually using it in your environment (I am, so that's a bad idea for me).
Reply
Zack said 5:42PM on 6-19-2008
Michael ARDAgent is setUID so when not launched by virtue of launchctl is runs as the files owner which is root. Thats why my trick works as it launches outside the context of launchctl which would otherwise launch siwtch it to the user context.
Zack said 5:36PM on 6-19-2008
I just verified this on Mac OS X Leopard Server will a console user logged in.
kill -9 $(ps -axww -U $USER | grep ARDAgen[t] | awk '{print $1}') ; osascript -e 'tell app "ARDAgent" to do shell script "/usr/bin/whoami"'
Reply
Michael Rose said 5:44PM on 6-19-2008
OK, tried it a few times and eventually it did come back as root. Darn it.
Chris said 5:58PM on 6-19-2008
(back from lunch)
kill sometimes works (which is why I didn't post -9, because it worked in my testing), kill -9 works better, but again, its a timing issue. if you can get your osascript to run before launchctl has a chance to reload ARDAgent, it runs as root.
I get some failures with a script similar to Zack's (which I wrote on my own, thank you ;) ), that greps for the current ard process, kills it, then runs the osascript, but running it consecutively will eventually result in an execution as root.
I've tested on 10.5 and 10.4 machines, with the same eventual result (even if it fails the first time, subsequent attempts succeeds).
Zack said 5:53PM on 6-19-2008
Michael , you should probably update the main section to confirm this as people are thinking this is fixed but in fact can still easily be exploited, granted you can reboot and system and root in if you are in front of it, I worry mostly about server rooms where any user can login by default and root the box. ) This is while Service ACls are soo important for SSH and the loginwindow.
If you want to learn more about setuid check out my book [ shameless plug]
http://www.amazon.com/Foundations-Leopard-Security-Books-Professionals/dp/1590599896/ref=sr_1_1?ie=UTF8&s=books&qid=1213912212&sr=8-1
Reply
Michael Rose said 5:59PM on 6-19-2008
I'm doing that right now. Thanks for keeping me on my toes.
Chris said 6:04PM on 6-19-2008
Michael- I suggest that you update the blog post to show that the fix isn't a fix, and will only give people a false sense of security. As Zack has provided with his sample script, it is bypassed.
Also, you should update the ardfix page also to reflect this, for folks who are being linked to it without going to the blog.
Chris said 6:13PM on 6-19-2008
Michael-
Sorry for the pile on, your comment wasn't present when I posted.
Glad to see the update (also, don't forget about the ardfix page!).
rob said 6:20PM on 6-19-2008
I have this book and consulted it for this issue. Where is setuid discussed? I couldn't find it.
rekkart said 6:34PM on 6-19-2008
First of all, for those that admin lab/public machines, who is allowing users to run Terminal? Why would you?
Reply
rob said 6:36PM on 6-19-2008
Repair Permissions will undo changes like in the Update 2.
Permissions differ on "System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent", should be -rwsr-xr-x , they are -rwxr-xr-x .
Reply
RobK said 11:03PM on 6-19-2008
I can reproduce this exploit on Leopard 10.5.3 but NOT on Tiger 10.4.11. (And NO - I am NOT running ARD or Remote Management service).
When I try the exploit in Tiger, I get:
23:47: execution error: ARDAgent got an error: Connection is invalid. (-609)
Has anyone been able to reproduce this in Tiger.
Reply
Chris Deke said 11:06PM on 6-19-2008
The solution here is not permissions, it is ownership. The reason it can execute things as root is because the file is OWNED by root. Chown the file to a non-admin user (you all run as these anyway, right?) and the security risk goes away. I have tested it and it works perfectly and ARD still functions in my testing.
Reply
Michael Rose said 11:34AM on 6-20-2008
[excerpting a direct email conversation between me and Chris]
I see there's a lot of confusion over the difference between 'owned by root' and setuid permissions. Changing the ownership may prevent ARDAgent from running setuid but that's a side effect, not the core of the problem (and I believe it will prevent legitimate ARD admins from running shell scripts or doing other tasks that require root).
When you say
The solution here is not permissions, it is ownership. The reason it can execute things as root is because the file is OWNED by root.
that's not accurate. Lots of files are owned by root (most of your Applications folder, usually) but can't run with root permissions outside of an authenticated/su session.
Chris Deke said 12:25AM on 6-21-2008
Test it. I have, and in my testing changing the ownership of /System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/MacOS/ARDAgent to non-root (but still admin) user preserved all of the functionality of a normal admin, but without the unwanted side effect of executing as root. I don't use ARDAgent for anything incredibly complicated though, so please test this, but in the mean time this DOES fix the problem.