-
Notifications
You must be signed in to change notification settings - Fork 259
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
File operations do not defend against symlink traversal, permitting trivial escape from read-write mounts #2321
Comments
We need to decide if the issue is traversing the root at all, or if the issue is creating new symlinks that do. What does WASI specify? W.r.t. security, I don't speak for the team, but I'd like to say that I consider (1) sandboxing WASI a much (much!) harder effort than (2) sandboxing Wasm. And I feel that the level of effort that was put into (1) is lower than (2), both within wazero development, but also in terms of WASI and Wasm design to begin with. So if you really care about security, yeah, you maybe shouldn't be using WASI preview 1. |
Note that simply preventing creating symlinks that traverse the root isn't going to suffice: An attacker can create a symlink that doesn't traverse the root (a/b/c/d/../../../etc/passwd), and then rename the containing directory (rename a/b/c/d => d). Preventing creation of symlinks with any .. elements might suffice to prevent creating new escapes. |
Just leaving the code pointer here: wazero/internal/sysfs/dirfs_supported.go Lines 36 to 42 in dc058c0
We can probably enforce some minimal rules here, like that running It's likely that these checks should be inside wazero/internal/sysfs/dirfs.go Lines 87 to 99 in dc058c0
I mean: do we even need symlinks to evade the "root" at this point (the same |
if we do I think we might have to skip some wasi tests (but that might be ok) |
Signed-off-by: Nuno Cruces <[email protected]>
Would you mind testing b36a8c8, @neild, @evacchi? I think all our current tests pass. This only allows creating symlinks that go down, not up (returns EFAULT otherwise, which seems appropriate). Please discuss. This is just food for thought, not even a PR. |
Having slept through this (not much admittedly), b36a8c8 has two issues with it.
For Lexically cleaning the path with Not lexically cleaning the path, however, is a security issue if (e.g.) BTW, unless I'm missing something, I don't think the The only complete solution ISTM would be for our file system to implement path resolution all by itself. |
So, our options seem to be:
I'm inclined to go with 1, b36a8c8 is a very close start. |
I'm starting to think I jumped the gun on this. We explicitly document that escaping the mount point via relative path lookups is allowed: Lines 64 to 88 in 111c51a
If you have any suggestions on how we could make this more clear, I'm happy to hear them. #2322 will remain a draft a little longer as we think about this, but I'm now inclined to just withdraw it. You can use Or you can type assert |
In general the doc we should be reading about path resolution semantics we should be reading is: I hate it that I didn't find it sooner, but I hadn't worked on WASI filesystem directly myself before. |
Bit tangential perhaps but if you know ahead of time what your filenames will be, and what permissions you want to give your wasm application on them, you can implement quite a strict filesystem like this: And then give a config like this: Or like this: That's how we locked this down as much as possible in GtS anyway, though it may not apply for your use-case. |
Yep. I have this extreme example I used for a tool that reads from a single file (because it wants to seek, so doesn't like |
As discussed above, this is working as specified in the documentation. I opened #2323 to track implementing path resolution, which would fix this. |
(I have been asked to report this bug via the public issue tracker.)
wazero does not appear to defend against symlink traversal in its filesystem APIs.
Since the WASI filesystem API permits creating symlinks, this allows for trivial access to the full filesystem from any program with a read-write mount. For example:
Run this program with read-write access to some directory:
It prints out the contents of /etc/passwd. /etc/passwd hasn't been exciting for a couple decades, admittedly, but this can be used to read or write any file anywhere on the filesystem that the account running wazero has access to.
The text was updated successfully, but these errors were encountered: