How does the code example in the python os module documentation create a security hole?
Asked Answered
J

1

8

The documentation for the os module makes the following assertion:


Note

Using access() to check if a user is authorized to e.g. open a file before actually doing so using open() creates a security hole, because the user might exploit the short time interval between checking and opening the file to manipulate it. It’s preferable to use EAFP techniques. For example:

if os.access("myfile", os.R_OK):
    with open("myfile") as fp:
    return fp.read()
return "some default data"`

is better written as:

try:
    fp = open("myfile")
except PermissionError:
    return "some default data"
else:
    with fp:
        return fp.read()

I don't understand how a user "might exploit" the interval. If open was going to raise an exception, I'm not sure how os.access would prevent that exception from being raised. Likewise, if the user manipulate the file somehow, why not perform the file manipulation prior to the EAFP version's open command?

I do understand that the second version may be more robust, since os.access may fail to correctly recognize a condition that could raise a PermissionError, but I don't see how the LBYL version is less secure. Can someone explain this?

Jaunitajaunt answered 5/12, 2018 at 23:2 Comment(0)
A
8

While the access-using code is unsafe, the second code snippet doesn't solve the security issues. These docs should be changed.

The purpose of os.access is to test whether the real user id has permission to access a file when the real and effective user ids are different. The danger with the os.access snippet is that the user could place a file access returns True for in the location being tested, then swap it out for a file access would have returned False for, bypassing the check. Since open uses the effective user id, the open call can still work, bypassing the access check.

The second snippet doesn't solve this problem. Now the user doesn't even need to go through the switcheroo. No part of the second snippet checks the real user id.

Arguseyed answered 5/12, 2018 at 23:15 Comment(2)
Thanks for the sanity check. Do you know if there is a recommended way (in python) to mitigate this risk? (Or is it as seemingly hopeless as validating file names?)Jaunitajaunt
@K.Nielson: I'm not sure. It mostly matters with setuid scripts, which are kind of a security/compatibility mess already, and I'm not sure what the best practices are for such scripts even when the OS supports them. I think you're probably supposed to use os.seteuid to temporarily set the effective user id to the real user id while opening and reading the file, then set it back afterwards. I don't know if that's fully secure, though.Arguseyed

© 2022 - 2024 — McMap. All rights reserved.