-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Env sanitization in Graphene pre-main wrapper #158
Comments
Thanks, @mkow for reviewing our pre-main code and reaching out! |
That's true. But if it is not set and at the same time you have |
Why can't this be a part of the enclave? The problem is that a lot of popularly used envs are really dangerous and should really get into the measurement and be verified. If your "dynamic configuration" allows changing the code which will execute inside the enclave, maybe it shouldn't actually be dynamic? :) |
As said in the other ticket in Graphene, we don't care about |
Seems the discussion got split between those two issues, so just for bookkeeping I'll copy my response here: Until we get this feature [gramineproject/graphene#2356], please ensure that LD_LIBRARY_PATH is actually defined in the user manifest, otherwise this will be completely insecure (and we can't expect users to know this quirk). |
I am wondering, is there actually any sane way to check the current manifest from inside Graphene's environment? Because I am not sure how we could reliably check against the set values in the manifest without making certain assumptions, e.g. manifest lies in the current working directory and has a certain name pattern. What would you suggest would be a reliable way to check this? Does not need 100% perfect as we plan to switch to the feature in gramineproject/graphene#2356 in the future, but also should not be a terrible hack ;) |
@Nirusu I don't think there is any sane way to peek into the current manifest. Technically, we have an internal VMA that holds the manifest content (in raw UTF-8 text): https://github.com/oscarlab/graphene/blob/5230827b3206049add4b2f5331e057bc1fd7b797/LibOS/shim/src/bookkeep/shim_vma.c#L539. The We don't expose internal VMAs when the in-enclave app does We could provide a new pseudo-file like |
Why do this at the Graphene / pre-main wrapper level? The coordinator knows the manifests, right? It could do sanity check on them and refuse to run such insecure configs. |
Uh, I don't quite get what you mean. We should define The premain establishes contact to the Coordinator, and the Coordinator does not know the Graphene manifest. It knows its own manifest, containing MRENCLAVE / MRSIGNER (+ related) and the environment variables / files which should be provisioned from the Coordinator (not from Graphene directly). Except for the quote generation code (and the standalone premain), the Coordinator has no libOS specific code. During the launch of the premain, the Coordinator is not involved so far. The premain launches just as any other Graphene application. The application authenticates itself to the Coordinator during the premain based on the SGX SIGSTRUCT values, but not before. |
Yup, otherwise you'll pass unstrusted
Ok, I see.
Yeah, I know, maybe I wasn't specific enough - what I meant is forbiding such insecure configurations during attestation of premain or somewhere in the toolchain used for enclave creation. |
After thinking quite a bit about a potential workaround, I am not sure if it makes sense to invent a temporary solution for the time being until the selective environment pass-through feature is implemented in Graphene. Here are my thoughts about this issue:
However, there does not seem to be an easy workaround here:
I think the only real effective workaround for this issue seems either to build our premain process statically, let the user define However, the latter one makes configuration through K8s more difficult, and both workaround would become redundant for the future. anyway. This poses the question if all this is really worth the hassle when we are dealing with non production-ready software so far, given that you wanted to implement a more proper fix into Graphene soon. Reworking the premains, rewriting the docs and making the "Getting Started" process more difficult yet still carrying the "insecure" flag due to host env pass-through seem like quite the effort to go for a temporary solution. I guess for the time being, we would choose to warn the users in our documentation / samples that they should really set Does this work out for you for the current time being? Of course we would keep the issue open here and not run away from it, however so far the workaround do not seem good, and we think it is not too critical as this is not production-grade yet (and screams "insecure" on launch anyway). |
I have no objections. Thanks for the detailed analysis!
Why is this? The default library paths are not enough for you premain? |
Which default library paths? LD_LIBRARY_PATH is unset by default on my host system. Otherweise, there is nothing so special about the needed libraries. But it does not launch LD_LIBRARY_PATH unset in Graphene, but fine when running on my host directly. $ ldd premain-graphene
linux-vdso.so.1 => (0x00007fffda3db000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fe34c320000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fe34bf50000)
/lib64/ld-linux-x86-64.so.2 (0x00007fe34d400000) |
See also https://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html, Section 3.3.1. Looking at the output of your |
I'm confused. Isn't the default way that a Graphene app mounts its libs at /lib and sets LD_LIBRARY_PATH accordingly? |
Yes, this is correct. Sorry, I was thinking about But I got lost somewhere here. If you have something like this in the Graphene manifest file:
Then I have a feeling that @mkow confused us all :) Michal, what was your problem with all this exactly? |
This is a very brittle assumption to rely on. If you want to go this way, then I think you should explicitly check if this path is set in the manifest and disallow running without it, there's no guarantee from Graphene side that "not customizing Anyways, this is just a tip of the iceberg, |
The point is understood, though this makes it sound worse than it is because all these LD shenanigans still only works when the malicious libraries are trusted or pass-through mounted. If not, well that seems to be an issue with Graphene in my opinion when a malicious host can just pass any unblessed executable code into an enclave. Anyway, I think we all agree that Until we get gramineproject/graphene#2356, what do you suggest we could do here to mitigate this without compromising the dynamical configuration, if we do not want to pass |
Only a single pass-through mount is required for this. Also, a "malicious" library may not even be needed, its the usage which is malicious, not necessarily the library itself. E.g.
Same as above. Placing untrusted executables inside the enclave FS is perfectly fine, as long as it's inside the paths which the user allowed in the manifest. If you want to block this, then I think you're addressing the problem at a wrong point (as explained above).
Depends if you want the config file to be integrity-checked or not. If you treat it as untrusted, then just pass it's name through argv. Untrusted argv is much less dangerous if you control the entry executable (but in your case, please carefully check if Go doesn't have any magic argvs, like it does with env). Or maybe even skip the config file, and pass everything through argv?
As above, argv is much less dangerous if the entry executable is your own binary :) (contrary to e.g. using Python interpreter as entrypoint). I mean, it's possible to do this securely without too much effort. |
Nope, not trying to adjust it the problem by saying "your fault for putting this inside the enclave". But these kinds of wrong approaches is also why I am not happy about replacing |
Thanks for all the input @mkow, much appreciated! We now understand that untrusted/insecure env is a no-go and there is no reliable way to secure it. argv poses problems on our side, and is also flagged insecure in Graphene, so we don't want to go with that. For now, we will hardcode the env vars in the simpler samples. Regarding the samples that need dynamic env vars, we will document that this is not ready for production yet. We would be grateful if you can add a feature like gramineproject/graphene#2356 in the near future. |
@daniel-weisse If I didn't miss anything the feature is in the official Gramine release and already used in our Gramine integration, right? If so, feel free to close the issue. |
Hi,
I took a look at your Graphene pre-main code and I noticed that you allow
LD_LIBRARY_PATH
to be passed from untrusted (if I understand correctly) source. This sounds very risky to me - if user manifest contains some allowed directories (kind-of "passthrough" mounts in Graphene's confusing terminology) it will allow for arbitrary code execution from attacker.See:
marblerun/cmd/premain-graphene/main.go
Lines 21 to 25 in fb51ebf
The text was updated successfully, but these errors were encountered: