Don’t get too excited, the following bugs are actually shitty bugs, nothing glorious like a Linux x86 Memory Sinkhole Privilege Escalation but still, they are a privilege escalation exploit and an SSH auth bypass exploit (working as of now 11/08/2015 in OSx 10.10.4).
(Due to the ‘weight’ of this topic I’m gonna write this blog entry in English for the first time in the history of Aitch) (yay! international! \o/)
“Why does SSH ask so many things?? Keep it simple™”
I use SSH almost every day, and I discovered this bug randomly while doing my job. Yeah, randomly.
Prerequisites: one or more than one (.+) SSH server using keypair authentication, OSx as client.
In any linux/unix system I ever tried (and I tested many, believe me) and in every ssh client I ever tried there’s one thing that neverhas to be done when talking about SSH keypairs: storing the key in memory, accessible for every process in the same machine.
The SSH command in linux works like that:
Where private.key is the path to the keypair’s private key and example.com is the ip/domain name we want to be connected to.
After the command execution, the client searches private.key and, if encrypted, asks for the password every time.
That’s not the case of the OSx’s ssh command at all.
When we type the same command in OSx a popup asks for the keypair password and a flag asks if we want to save the password in the keychain. Then we do what we had to do with the SSH session and terminate it.
The problem is exactly in what happened in the meanwhile.
SSH command is called
SSH checks for the key’s presence and tries to decrypt it
SSH asks for a password to decrypt the key (and a flag to save it in the keychain)
SSH saves the decrypted key into memory
/*random user commands*/
SSH connection is terminated.
Noticed something wrong?
The key is NEVER unloaded.
So yeah, if you try again:
Without knowing the key’s password don’t worry dude! It’s still in memory! It’ll connect you without asking.
Yeah Shoto, that’s boring! If I leave my keypairs in a folder accessible to others I’m just a fool..
Wait: have I said that you actually need the key?
Not at all!
You don’t have the key? Just… run the command with a random key path, or just avoid the -i flag, it’ll use the cached version.
Funny thing is, if I remove the private key file this basically just does not matter at all, because I still can connect using the cached ssh session! Totally unsafe!!
Real-life example I’ve done to test this:
My boss is used to store important keypairs in his pendrive.
He connects the pendrive to the mac, connects to the ssh server and then disconnects the pendrive when work is done.
I managed to leave a script running as the current user, that basically did nothing except waiting for an “ssh -i ” command to spawn in the command list ( ps -o command | grep “^ssh ” | grep ” -i ” )
When that command was found the script would replicate the same command, removing the -i part “just for fun”
( sed “s/ -i *[^ ]*/ -i \/dev\/null/g” ) resulting in a successful connection to the ssh server used by the boss (i could have appended evil code and run it on his server!!)
But knowing that he already had extablished connections to other ssh servers I created another little script that parses .bash_history and tries to connect to every ssh server he finds was called with the “-i” flag (keypair login)
In less than 30s I had gained unauthorized access to 12 servers.
( “[…]this is expected behavior. Let us know if you feel otherwise.[…]” )
Privilege escalation AKA “sudo is meant to make you root”.
Again, this technique was possible only due to misconfiguration of the sudo binary, issue not present in any other *nix os I ever tried (arch, debian, slackware, (k|x|^)ubuntu, android, and such)
When I run sudo in arch for example, the current shell session and just that session is enabled to use sudo after entering the password correctly.
This means that if i’ve two instances of Konsole (default KDE console) running, or two tabs on the same console, just the tab that has correctly entered the password is allowed to run other sudo commands without asking for password.
In OSx that’s totally not what sudo does.
If I, user “shotokan”, run ‘sudo’ on an isolated terminal, every other application in the system, run by user ‘shotokan’, is allowed to run sudo without asking for passwords.
Basically every browser/plugin/component exploit may use this technique to gain root access on my machine!! Ew!
So again, I coded a tool to test this thing.
In 70 rows of bashscripting I managed to create a full-working silent privilege escalation exploit that:
once executed, copies itself into ~/Library/
creates an ad-hoc property list file into ~/Library/LaunchAgents/ with property “RunAtLoad” to autorun the exploit copied in ~/Library/ , starts the service, and then removes the old copy.
silently waits for a sudo command to be executed ( ps -o command -u root | grep “^sudo ” )
when detected, uses sudo, automatically gaining root privileges without passwords, to copy himself into /Library/ (not ~)
again uses sudo to create an ad-hoc property list file into /Library/LaunchDaemons/ win property “RunAtLoad” to autorun the exploit copied in /Library/ automatically as root.
starts the service, and then removes the old copy ( ~/Library/ and the old xml)
At this point I’ve configured the script to just use the “say” command to tell me “I’m root”, but a malicious user…
Could do everything.
( “[…]We were aware of the sudo privilege escalation this issue. It is being investigated.[…]” )
I’m scared a whole lot about this, ‘ssh’ and ‘sudo’ should be the most tested commands in every system and yet here they totally seem… Unsecure.
As for sudo… I seriously think this was the easiest privilege escalation exploit ever made, I don’t even know how to say it but.. Everything can be root. And that scares me a lot.
No, I’m not going to release the two exploits but I already gave you guys everything to make them, so just don’t ask.
I seriously don’t know how OSx is still one of the most used operative systems used by security experts.