Beware of sudo on OS X
blog.rongarret.info
blog.rongarret.info
Why does anyone still care about root escalation on workstations? When do we stop pretending our MacBooks are multi-user UNIX mainframes?
App sandbox to full user privilege escalation may be scary. But if someone can run arbitrary code as my user, then by all means, have root as well.
This is actually a good point, even if I disagree with your minimization of privsep's importance.
Thinking like this annoys me, because it assumes a specific implementation for OO. Are people conflating OO with Java? Are they conflating it with Smalltalk? Are they unaware you can write C in an OO style?
> It's not until the time I graduated college that machines and VMs of managed environments started to get faster than "embarrassingly slow" in mainstream hands.
Yes. People are apparently conflating OO with Java or Smalltalk.
There were very few fast OO languages and they were emerging at the time. The most prominent examples of those languages are those languages GP names, and they do not exactly live up to the promises of even contemporary OO research, much less modern research.
It was clearly an after thought and a bit of a hack, but it works, and it makes it transparent how everything works. I had been taught Java at university before that, and the whole OOP thing was a bit of a hidden mystery. Perl gave me a far better understanding of OOP.
That mindset. Like I said. Did you not read my post?
Steve Jobs wasn't an engineer technically, so he wouldn't know the specifics here, but at the time object-oriented programming had a stigma associated with it because programmers did know of these drawbacks. Using Objective-C was obviously a fundamental choice by the software engineers.
Writing C in an object oriented style is what a lot of programmers did then. But there's a difference between associating data with methods and supporting polymorphism. Hence the talk of virtual function tables.
Examples include inheritance, abstraction, and encapsulation which you can achieve merely by changing syntax. What requires extra resources at runtime is polymorphism, and that's one of the most important, functional aspects of object oriented programming.
Consider if you will that the things you are describing as slow - chiefly the indirection of a virtual call - are slow relative to other things because of relatively recent CPU advancements. If a CPU does no branch predicting or caching, I think the overhead of a virtual call doesn't sound so bad. So, if we're talking about why to avoid OO in the late 80s, I'm not as convinced the cost of a virtual call is the barrier.
That said, my point was that C++ lets you do these things, but you have to ask for them. If you want virtual calls, go nuts. But if you don't, you're not going to suffer from mandatory bloat - your object code will still look good, as if you had written it in a language without such mandatory frivolities.
In any case, modern CPUs and compilers can use aggressive optimization, sure, and the runtime speed is only equally as important as the ease of development and concerns about reliability.
On an older system, though, using a liberal OOP design in an operating system would be akin to creating structs that have arrays of function pointers associated with them, and having every function call routed through those pointers. Looking at the machine executing this code, you would reliably see jumps to similar codepoints in-between function calls, and a lot of wasted time or space. And I'm not sure anyone has mentioned this, but exception handling especially can add a lot of overhead.
Obviously, the benefits significantly outweighed the cons, especially in this case (NeXTSTEP and Objective-C), but I think that was helped substantially by the fact that projects Steve worked on always had much better computer hardware.
Given the above link, I deny there's any single useful definition for OO: It's been defined and redefined over and over again for decades, to the point people can't even agree on what languages are capable of writing software in an OO style.
So I think Steve's attitude has to be put into the context of that conflict. But as MrTonyD shows, there were people at NEXT who understood how to translate that attitude into practical terms. And to be fair to Steve that's because he knew how to hire absolutely tip-top talent and trust them to do their jobs right, even when they disagreed with him.
I don't really see that they were wrong. After all, C and POSIX are also very high level and abstracted compared to the assembler-based OSes which existed before them.
The big problem now is that to be a successful alternate OS one needs to be bug-for-bug compatible with POSIX, and have a C compiler, in addition to one's own language and OS. Perhaps recent years' developments in virtualisation and containerisation will make it easier for a non-Linux host to run a Linux kernel and hand containers to it as needed.
Maybe one day OS and systems research will once again pay off.
My user, however, gives them my email, my photos, my tax returns, etc.
Separation still sounds like a good theory, but I do wonder if we're putting a lot of effort into defending the wrong user.
You still see a ton of comments saying things like "OS X and linux are secure because they use unprivileged accounts". But the security on unix is primarily to secure user alice from something that user bob does. It doesn't secure user alice from something that alice does. If alice gets infected with a cryptolocker trojan, it can't touch bobs files, but it can encrypt all of hers.
On a single user system that only has an alice account, what is needed is to secure 'tax program' from something that 'web browser' does.
E.g. I have a separate user that I switch to just to contact a handful of credit card / bank sites. Same with tax returns. I don't do them as my normal user. They are not readable from my main account. But I don't do enough. E.g. email and photos are still accessible.
Fortunately I lead an uninteresting life. The main threat to/from my photos is accidental deletion, filesystem corruption, drive crashes, etc. TMZ isn't going to pay anyone to steal them!
The problems are not simple to solve. What I've done is simple half-measures. It's very hard to do more than that.
Edit: and, of course, my normal user is "Standard", not "Admin". I switch to the admin user whenever I do sys admin. I never elevate privileges from my normal account.
It's also something 95% of OS X users don't do or care about.
If you want robust security, you will need to forget about OSX/BSD/Linux and look at Qubes OS. It's the best we have right now and nothing else comes close. Alternatively, compartmentalize and segregate (at the hardware level, all virtual machines have tons of host escalation bugs) and accept the fact that you will get owned.
Someone creates a sandbox profile for a program and then distributes it to others.
There are certain inconveniences when it comes to sandboxing applications, especially applications that require an X server, which is why sandboxing is not done by default on any popular Linux OS.
On Linux, GNOME is working on something that looks quite a bit like how OS X did it:
https://wiki.gnome.org/Projects/SandboxedApps
So I think we're actually moving in the right direction, albeit extremely slowly and imperfectly.
What does it mean in practice: if you set up appropriate restrictions and run (for example) `curl http://...` and curl gets exploited via malformed response:
- it cannot write to system configuration
- it cannot write to user configuration
- it cannot spawn shell
- it cannot bind port to get remote commands
- even if it could, it cannot receive traffic, because it's configured as outbound-only
- while it can send data on the same connection, there's not much to send, because:
- it cannot read your browser saved items (password, history, etc.)
- it cannot read your ssh configuration / keys
...
So yes, superuser access is still important, because it can set up defences which only superuser can override. Not many systems use it so far, but the frameworks are available.
I think the biggest impact currently in this area is the Chrome sandbox, but this one can be actually user-activated.
I think mobile actually leads the way in this area, with applications restricted in actions they can take, regardless of who they're running.
Of course this is tricky in case of browsers. But that's also why I don't keep my password in the browser ;)
My computers at home have multiple users, because they have their individual preferences setting their desktops and browsers the way they like
My computers at work, laptops and otherwise, have other devs' accounts on them, so they can ssh in and grab stuff, or play with setups I have on my machine. It's a particularly easy way for me to distribute VPN keys... and of course, users can't read each other's private files. If I'm away and someone needs a computer to work, they can use my machine without each of us messing with each other's setup.
Multiple-meatspace-user machines certainly aren't as popular these days, but they're not as dead-and-buried as you're implying. Just because mainframes are no longer the big cheese doesn't mean that there's no call for multiuser machines.
This is going to be the most exciting thing about SGX, which is allegedly coming out in a month, after many many years of anticipation.
And that is good for the user.
That kind of argumentation usually ends badly, especially when it's about security.
But even if you enable TTY tickets, a malicious process on your system can still elevate itself by patching the shell (in memory, using /proc/id/mem) to inject commands alongside the original sudo command. For example:
User types:
sudo apt-get update
shell executes: sudo bash -c "apt-get update; evil.sh"Although, OS X is a bit like Windows. A bad program running in userspace can essentially ruin your system as much as a program running as root. Privilege escalation is not a relatively big deal when you can `shred -u ~/` without root.
Erm, OS X has sandboxing. So, no. Except if you use unsigned third party stuff.
As long as its your account files that matter, and you're running an app un-sandboxed, then it has access to them.
Nothing Windows or OS X particular about it.
As about "ruining your system", no, without root privileges it cannot, in either OS X or Windows. Of course it can if there's a privilege escalation bug, but there are tons of those for GNU/Gnome/KDE packages too.
...like Windows. A bad program running in userspace can essentially
ruin your system as much as a program running as root.
How so?Are you talking about pre-Vista - i.e. versions of Windows in which the user created during first run was an Administrator, and UAC didn't exist - though you could certainly create non-administrator accounts? Vista came out eight years ago...
Or do you mean pre-NT, when there was no separation of any kind? NT came out 22 years ago...
This is mostly true on personal Linux machines as well. I'm just expressing my opinion that you don't need root access to pwn someone's machine.
In this model, the real problem here is sudo, which bridges a uid-1000 session to a uid-0 one. If you're administering a security-conscious, multi-user UNIX system, you should not be using sudo from your regular account. Either make a separate account and log in as that, or log in as root directly. (But if you want your Minecraft and your bash to not be able to interact with each other, the traditional approach doesn't have an answer for you.)
Of course, most UNIX deployments today are not multi-user remote-access systems, the way they were 30+ years ago when this policy was set. Most desktop UNIX deployments are effectively single-user systems, and the UNIX isolation model doesn't make much sense there. As a stopgap measure, direct access to another process's memory has been disallowed, but there are other ways for processes that share UID to mess with each other.
However, the most common single-user UNIX systems today are smartphones, either Android (Linux) or iOS (BSD + stuff). Android takes advantage of the UNIX model by assigning each app its own user ID. Angry Birds running as uid 1000 cannot mess with the Chase mobile app running as uid 1001. iOS technically runs all apps with the same uid, but applies extensive kernel-level sandboxing to limit the ways that apps can interact with the rest of the system, which essentially eliminates the rest of the leakiness.
There's a Chromium security document that expands on the traditional "1-part principal" model (identity of the human) and how we need to get to "2-part principals" (identity of the human + identity of the app), which I hope that someone will figure out how to extend to desktop UNIX someday:
https://www.chromium.org/Home/chromium-security/prefer-secur...
On most desktop operating systems, that functionality has been disabled. Ubuntu, Fedora, etc. all have Yama, which disables the ability for one process to access another's process via ptrace or ptrace-equivalent mechanisms (like /proc/*/mem) without special permissions. OS X has no procfs, but the equivalent functionality, using task ports, has had similar restrictions since the 10.5 days -- see `man taskgated`. You can't call task_for_pid() without having a particular code-signing entitlement or having administrator privileges.
This is why Xcode prompts you for administrator privileges when you first run it; gdb / lldb needs to be able to trace other processes and access their memory, and a normal process can't do that.
Security is always in tension with usability.
Anecdotally, I ran OS X for years with timestamp_timeout set to 0 so that sudo always prompted for a password. This broke absolutely nothing.