10 ms·
> Even in supposedly "memory safe" languages like Java, XML (and json) parsers are often riddled with bugs and design problems that can be exploited for remote
by ekidd 4y ago
> Even in supposedly "memory safe" languages like Java, XML (and json) parsers are often riddled with bugs and design problems that can be exploited for remote execution.
Why do we think this is OK, even for a moment? For how many decades will we accept massive vulnerabilities everywhere? We can't rewrite everything, but why isn't Chrome's "Rule of Two" a minimum professional standard for new code?
This isn't just a Rust thing. For example, why don't more languages allow me to say, "This XML parser is forbidden from talking to the network or file system"? Why could log4j load code without being granted special permission?
- lanstin 4y agoI think there is an opportunity here for language design. I should be able to import a library and mark it as nothing but computation, or as network only no file system, or file system only but no network, and have the language itself enforce that guarantee. I believe it has to be at the language/compilation level as executable segments can always just trap into the OS. If there were some syntax, then you could even specify the particular network endpoints or file system paths allowed. It is sort of old fashioned, a sort of dynamic scoping of access context, but would be better than you call a shared library which starts up some threads with network connections all invisible to you. There would be some idea of the main function and spawning threads or green threads would also need to specify what that thread can do, a subset of what the creating thread can do.
- PaulDavisThe1st 4y ago> I should be able to import a library and mark it as nothing but computation, or as network only no file system, or file system only but no network, and have the language itself enforce that guarantee. There is no sheriff to enforce this guarantee. There's nobody come to save you (us) from ourselves. You can try to build walls around things, but meanwhile other people are building ladders (or digging tunnels). It gets worse though. Virtuality, whether via literal VMs or COWbuilder-style containers, means that defining what is means to access certain resources is hard to do. For the most part, this resolves nicely (i.e. you almost always have less significant access to "the real world" than you might believe), but it's not trivial to determine.
- marcosdumay 4y agoIt's funny to read those threads of people saying how nice would it be to have, or that things are impossible, and yet those same things are there in Haskell since forever.
- PaulDavisThe1st 4y agoSo tell me, I run a Haskell program inside a VM and it accesses the root of the filesystem. What happens? It accesses the network interface, what happens? The point is that the code, at runtime, cannot determine what context it is running in, and it may be entirely appropriate for it to do certain things, or highly inappropriate, depending on that context. It has nothing to do with language.
- JonChesterfield 4y agoPut the library in a different process and seccomp it
- tremon 4y agoYes, this, exactly. In our current operating systems models, the process is the most granular resource that we can confine. The OS model doesn't allow for more fine-grained resource control than that, so code with different authorization scopes should run in different processes. Maybe we need a different OS/process model?
- bhawks 4y agoThe fuchsia os has a very interesting security model in this respect : https://fuchsia.dev/fuchsia-src/concepts/principles/secure https://fuchsia.dev/fuchsia-src/concepts/principles/secure The tldr being a very powerful and lightweight sandboxing mechanism complemented with a OS mediated ipc layer wrapped by language idiomatic libraries. Unfortunately fuchsia is taking it's own sweet time to play out.
- gavinhoward 4y agoAuthor here. My language will have some sort of what you are talking about.
- lanstin 4y agoYeah, the replies all sort of show ways of wedging this in, but why not add it to the language/compiler? It would be very useful, and also interesting to see attacks against it. It would also be interesting to see how this sort of dynamic scoped feature would be implemented these days. (In old LISP stuff, you used to be able to do like: (with-stdout-redirected-to-printer (whatever-func etc)) and all the stuff whatever-func called would print but it would be redirected to printer.
- gavinhoward 4y agoThat sort of redirection will absolutely be possible, but that won't be the language-level thing my language will support. In my language, there are packages. You might have a left-pad package, for example. (Okay, it's a bad example, but whatever.) The programmer/user gives permissions to packages at the package level, so you might give the left-pad no permissions at all except for allocating memory (for generating a formatted string), which means something else will need to do the output. These permissions can include anything, like being able to use other packages, network access, filesystem access, etc. Static dependencies will be the first line of defense, but if something need dynamic access, say access to specific files such as `/dev/urandom` or `$HOME/.config/<program>/config.txt`, there will be a dynamic way to give permission. This dynamic way will probably serve a lot of the use case you suggest. This will be at the compiler IR level, by the way. The build system of dependencies might otherwise be able to get around it. But with IR, you can tell the dependency's build system to generate the LLVM-like IR for its code, and its build is done and can have no more influence. Then without using any of the dependency's code, you can then specialize the IR while inserting permission checks. You can even use this to generate cross-platform "binaries". The "binaries" would just be a tarball of IR. Most IR would be used for any platform, but some would be platform-specific. If you include all of the platform-specific IR with the platform-independent stuff, you can then ship that tarball to any machine, which, on trying to run it for the first time, will realize it needs to be specialized for that machine. This includes inserting permission checks based on the policy for that machine. Yes, it will be that powerful. My main concern is that it will be too powerful and thus have bad user experience or a steep learning curve. UX matters. I don't have it solved yet, but I'm trying.
- atoav 4y agoIt is a culture thing. The damage that broken code has caused was either not big enough to shift that culture, or (more likely) everybody involved convinced themselves that software errors are both inevitable and a welcome excuse to pin things onto — just try how often some privacy leak/hack/error is blamed on "software failure" as if this was one of gods lightning bolts nobody can protect against. If we did electrical engineering like we did software every gadget would come with a fire extinguisher. If we did civil engineering like we did software engineering we would have daily bridge collapses. In the dawn of modern civil and electrical engineering indeed many catastrophes happened, and they did happen till culture changed and had an inpact on the education of future engineers. This point has not been reached at all with software engineering outside of safety critical applications.
- taeric 4y agoBecause that is a lot easier said than done, all told? As we get faster and faster machines with more and more spare cycles, we can probably devote a lot to this sort of thing. Maybe. And, really, this is no different than anything else. Just in an odd "reverse" direction. Lets say someone makes brake pads for your car that have an antenna and compute on them. How would you keep them from communicating your location to anyone else? You can work on detection, of course, but for the VAST majority of vehicles out there, this would be silly at that point. Same goes for why you use locks that can typically be unlocked with a toothpick in bathrooms. Privacy locks are vastly different from security locks. Even though they look roughly the same on paper. And this is clearly ignoring every other thing that makes you vulnerable outside. Why do we allow satellite imagery of people in their backyard? Mainly because we don't have a realistic way of disallowing it.
- tremon 4y agoFor example, why don't more languages allow me to say, "This XML parser is forbidden from talking to the network or file system"? Because that's not up to the programming language to decide. In which context a particular piece of code is executed is out of scope for the design and compilation phase of your program -- that's part of the application deployment, and that deployment is usually not written in the same language as your program. What you're asking for is basically the microkernel approach applied to applications: each microservice has its own capabilities and data access, and control is passed through RPC. This exists, and it can be implemented in any language (though more readily in some than in others), but this is not a programming language feature: it's a runtime feature that must be provided by the environment (whether JVM, Linux, Docker, SeL4 or browser) in which your code is deployed.
- ekidd 4y ago> Because that's not up to the programming language to decide. There's actually a lot of really neat research in this space, including: - "Row types" for effect systems, which allow the compiler to cleanly keep track of what code has access to what parts of the outside world. - Capability systems, where you essentially need "handles" to access things in the outside world. - Strong-typed unikernals, which use either of the above approaches to replace the process boundaries in a regular microkernel. Admittedly, none of this is exactly ready for the mainstream yet. But there are plenty of ways to help address these issues at the programming language level. And I think this is worthwhile, because as the Chrome team has pointed out several times, trying to stick every parser in a seccomp-isolated process is a lot of hard work. And it rarely gets done in practice. Given the sheer number of dependencies many projects have the days, and the growing number of "supply chain" attacks against libraries, I think this is worth all the effort that's going into right now. Maybe in 10 or 20 years, we'll see some commercially-acceptable languages that explore this space.