In one of my previous posts about the IRP_MJ_CREATE operation I mentioned that there is a structure, the _OPEN_PACKET (discussed in this post), that stores what the original IopCreateFile request looked like and I also mentioned how the IRP_MJ_CREATE IRP is populated based on that information. Of course, when STATUS_REPARSE is returned, the new IRP will have to take that into account as all as the contents of the _OPEN_PACKET. In particular the Options for the IRP come from the OPEN_PACKET while the file name comes from the buffer in FILE_OBJECT->FileName when STATUS_REPARSE was returned. In this case it's easy to make an error when the IRP_MJ_CREATE has the FILE_OPEN_BY_FILE_ID and the mini-filter blindly calls FltGetFileNameInformation() and gets a file name back. Behind the scenes FltMgr deals with the fact that the file is opened by ID, and this is transparent to the minifilter. So a minifilter might in fact be completely oblivious that the had the FILE_OPEN_BY_FILE_ID flag set and it will do what it normally does, calculate the new path based on the original file path, put it in the FILE_OBJECT->FileName and return STATUS_REPARSE. Unfortunately, when the IO manager issues the new IRP_MJ_CREATE, it will take the Options from the OPEN_PACKET (including the FILE_OPEN_BY_FILE_ID flag) and use the name supplied by the user and so the IRP_MJ_CREATE will now be broken and it will either fail or end up opening the wrong file if the new FileName is exactly of the right length and it happens to correspond to a file ID or object ID on the volume. This is rather unlikely but can happen and even worse, it can easily be exploited by an unprivileged user that only has to send a properly formatted name to NtCreateFile and trick a minifilter into opening the wrong file. Of course, the system will still perform ACL checks and so if the minifilter doesn't do break the NT security model then the user will not get access to files it doesn't already have access to, but this might be exploited to break out of a sandbox for example…
So now let's look at a code example of how this happens. There is a sample in the WDK that shows how to perform a reparse from a minifilter, SimRep. By default SimRep reparses any request for a path that starts with \x\y to a path that starts with \a\b. For my little experiment I've created two files:
- C:\x\y\foo.txt
- C:\a\b\foo.txt
No comments:
Post a Comment