6 ms·
Arbitrary code execution during compilation – rust
- deleted 4y ago[deleted]
- eleijonmarck 4y agoPOC to demonstrate how to delete files when cargo build runs
- revelio 4y agoWe must start systematically sandboxing developer tools. It's scary how sensitive dev workspaces are, and how much random crap we run. After decades of training the world's parents and grandparents not to download and run programs from untrusted sources we now routinely do it ourselves.
- jagrsw 4y agoMost reasonable companies/projects do that. I believe the compiler explorer project - https://godbolt.org/ https://godbolt.org/ - uses nsjail or maybe firejail for that - https://github.com/compiler-explorer/compiler-explorer/tree/b059bc7b4e7d021cf7c65e2307ed7ef684bf989c/etc/nsjail https://github.com/compiler-explorer/compiler-explorer/tree/... asm(".section .text\n" ".global ls\n" ".global le\n" "ls:\n" ".incbin \"/etc/passwd\"\n" "le:\n"); int main() { extern char ls __asm__("ls"); extern char le __asm__("le"); write(1, &ls, &le - &ls); }
- eleijonmarck 4y agoI filed a issue on `rust-analyzer` and apparently it is by design - https://github.com/rust-lang/rust-analyzer/issues/14375 https://github.com/rust-lang/rust-analyzer/issues/14375
- landr0id 4y agoI mean it’s fairly obvious. You can do this through build.rs files as well. There was talk about trying to compile proc macros to WASM and run them sandboxed in the compiler. Not sure what happened to that RFC (by dtolnay?)
- the_mitsuhiko 4y agoThere is a POC. https://github.com/dtolnay/watt https://github.com/dtolnay/watt
- alkonaut 4y agoAfaik you don’t even need to use macros for this, can’t you just put a build.rs file in the crate and it will execute on build? Almost all build/project systems I know have this functionality simply because execution of arbitrary programs is too useful to go without. Any C# project (.csproj) for example can include a task that eats your homework. It’s scary but I don’t see a solution like sandboxing being very easy to retrofit either.
- jiggawatts 4y agoThe mistake is that arbitrary transformations != arbitrary code. I want the build process to be able to generate arbitrary code based on the inputs given to it from the source control — but nothing else. No reaching out to HTTP command and control endpoints, making database calls, or deleting my home directory. It’s not just because of security. Security is a side-benefit here. The real benefit is that unrestricted build processes cannot be versioned with source control. If the build process can “reach out” and pull in data from external sources, then it will always use the “latest” version, not the version in that branch or commit. It’s about being hygienic.
- jhgg 4y agoThen avoid crates that do such things. Other people however are able to make use of compile time code execution to do some pretty awesome things. For example, a database library sqlx can check all the SQL in your code as being syntactically correct, and also typed correctly against a test database at compile time. A feature that is useful and convenient for users of the library.
- dymk 4y agoI agree with you and I'm not sure why you're being downvoted. That being said, it's nice to be able to have guarantees about your build without having to look at the transitive closure of dependencies in your project. It'd be nice if crates could be marked as "hygienic build" or something, and a hygienic crate can only depend on other hygienic crates. And then something like `cargo check-hygienic` which fails if any dependencies are non-hygienic.
- Longlius 4y agoI would expect any sufficiently powerful macro system would have to be this way. Don't most editors ask you whether or not you want to trust some code before opening it with full privileges anyway?
- proctrap 4y agoOld, it's not new that macro expansions, build files and build tooling can do that. (And if we sandboxed that, you still get infected release builds, check your deps..) See NPM installations and "please sponsor this project" messages, which can also give you a virus.
- winstonewert 4y agoSo... if I'm using a third party crate, I'm already trusting it not to do bad things in my running application. Why is it such a big deal that it could do bad things during build time just before I run it? If I'm using a third party crate... I've got to trust it one way or the other. So what's the big deal here?
- mocko 4y agoIn the context of a long-lived build server it could permanently compromise the machine, allowing an attacker to modify any other package you publish from there and maintain that access even after Rust has been fixed.
- the_mitsuhiko 4y agoIf that build server runs tests too the surface area of such an attack is similar.
- ojkelly 4y agoA lot of things could also potentially compromise a long-lived build server, to the point where it’s better not to be long lived. If it’s not practical to use a fresh machine/vm/container/function for each build, at least rotate them out more than once a day. You need full repeatable control over the execution environment for hermetic builds. I also agree rust needs to either fix mitigate this. One option you have is to disable networking on the build machine.
- yazzku 4y agoYou can sandbox your application when it runs, but nobody's doing much about the dev environment. If you're working for a company and using VSCode, you are often just one malicious plugin update away from leaking the company's IP and/or having your system compromised. Similar case for Python packages and such Internet-facing code environments.
- winstonewert 4y agoAre you sandboxing your applications when you run them on your dev machine?
- jasonpeacock 4y agoNothing new to see here... Any of these steps could do the same to your system, and it's been the "standard" for 30+ years: ./configure make sudo make install Or literally any other language/package manager that supports build scripts.
- speed_spread 4y agoAt least you had to unpack the source archive and install the dependencies yourself, which gave one time to appreciate just how much you depended on and how trusting you were. Nowadays the bad code can be in any one of your 300 auto-downloaded public unsigned dependencies. It feels light, easy and fun but it's actually powerful dark magic to summon the work of thousands of individuals into your pet project.
- kalkin 4y agoA makefile can run arbitrary shell commands.
- speed_spread 4y agoSure. And the code you're compiling will also at some point be executed. So you're trusting the persons who wrote _that_ project. Also, if a Makefile looks like it's doing anything else than setting up the compile env and building you can be sure I'm interrupting it quickly to look at what it's doing. OTOH a declarative build manifest with transitive dependencencies is like a self-replicating invite to an open house party inside your computer. It's only a matter of time before some _bad people show up_. (cue Beastie Boys' "Fight For Your Right to Party" )
- throwaway67743 4y agoSuch a safe language, better than everything else so much so that what amounts to a linter does compiles
- throwaway67743 4y agoHaha rust zealots are amazing, stay salty sea dwellers!
- WilliamBerglund 4y agoD does this "the right way", which is to say free of side-effects. https://tour.dlang.org/tour/en/gems/compile-time-function-evaluation-ctfe https://tour.dlang.org/tour/en/gems/compile-time-function-ev... https://wiki.dlang.org/Compile-time_vs._compile-time https://wiki.dlang.org/Compile-time_vs._compile-time You're supposed to be able to trust the compiler, you can't trust people. (https://forum.dlang.org/post/po2734$20mq$1@digitalmars.com https://forum.dlang.org/post/po2734$20mq$1@digitalmars.com)
- camel-cdr 4y agoAs does C, it even guarantees that the preprocessor terminates, but it's just a tiny bit harder to write programs in the c preprocessor.
- Ao7bei3s 4y agoC the core language incl. preprocessor _may_ not allow arbitrary code execution during build. But in the C ecosystem, there are no build systems with fully declarative configuration. Every project is expected to come with build configuration that is both very ad-hoc / unique to the project, and often includes tens of thousands of lines of unreadable auto-generated boilerplate (e.g. if people commit the later stages of auto-tools, which is common practice) which can run arbitrary code. So in practice C is not better at all. Also, C still has several ways to do file inclusion from arbitrary paths, as well as ways to cause arbitrary long compile times and object size with tiny source code. Compilation time may be guaranteed to be finite, but it is certainly not bounded.
- donatj 4y agoIsn't that one of the main selling points of Jai?
- WirelessGigabit 4y agoI think this is actually a good case for development containers. That way you're very explicit in what you expose in the container. It could still read your AWS keys that you pass in through the ENV though and upload those to some server in China / Russia. Or it could delete all your source code, but that's counter productive.
- 0atman 4y agoThis is a feature, not a bug: https://youtu.be/MWRPYBoCEaY https://youtu.be/MWRPYBoCEaY