Need Clarification about TOCTOU attack

Hello,

we are writing a filesystem minifilter to encrypt and decrypt the data which is going to and coming from the file system. We are intercepting the read and write IRPs in both pre and post callbacks. And applying encryption/decryption operations as necessary.

Should we be using direct-IO (rather than buffered-IO) for minifilter encryption where we encrypt the userland buffer directly? If so, we are concerned about Time of Check Time of Use vulnerabilities where we use the function ‘MmGetSystemAddressForMdlSafe’ to get the virtual address from the MDL in both pre and post callbacks. The risk is that the user process could have called VirtualFree on the Virtual Address we are trying to encrypt data at. Please let us know whether we need to take any action to handle the TOCTOU attack. If the solution is to use ProbeForRead/ProbeForWrite/Exception Handling, should we be locking the memory pages in memory?

Another attack we envision is that a userland application could ask us to encrypt something in a heap managed by ntdll (like Low Fragmentation Heap) and free and realloc the heap buffer before we start encrypting and we end up either encrypting a realloced data or heap metadata. This is not as dangerous though because it would essentially be the userland application freeing and reallocing the buffer and crashing itself.

Thanks,
S Ramakrishnan

When you encrypt data you shouldn’t encrypt it in user passed buffer
directly. You copy it first in your allocated buffer

21 окт. 2016 г. 10:20 AM пользователь написал:

> Hello,
>
> we are writing a filesystem minifilter to encrypt and decrypt the data
> which is going to and coming from the file system. We are intercepting the
> read and write IRPs in both pre and post callbacks. And applying
> encryption/decryption operations as necessary.
>
> Should we be using direct-IO (rather than buffered-IO) for minifilter
> encryption where we encrypt the userland buffer directly? If so, we are
> concerned about Time of Check Time of Use vulnerabilities where we use the
> function ‘MmGetSystemAddressForMdlSafe’ to get the virtual address from the
> MDL in both pre and post callbacks. The risk is that the user process could
> have called VirtualFree on the Virtual Address we are trying to encrypt
> data at. Please let us know whether we need to take any action to handle
> the TOCTOU attack. If the solution is to use ProbeForRead/ProbeForWrite/Exception
> Handling, should we be locking the memory pages in memory?
>
> Another attack we envision is that a userland application could ask us to
> encrypt something in a heap managed by ntdll (like Low Fragmentation Heap)
> and free and realloc the heap buffer before we start encrypting and we end
> up either encrypting a realloced data or heap metadata. This is not as
> dangerous though because it would essentially be the userland application
> freeing and reallocing the buffer and crashing itself.
>
> Thanks,
> S Ramakrishnan
>
> —
> NTFSD is sponsored by OSR
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

Why do you care about user data validity? If a user wants to **** himself let him do this.

If MM provides MDL then pages have been locked and it is safe to map them. A user process can free the related virtual address range but this doesn’t invalidate MDL, the pages still valid.

MmGetSystemAddressForMdlSafe maps MDL pages in the system space, i.e. it allocates new system PTEs to map pages and these PTEs can’t be manipulated from a user application, these PTEs don’t depend on user space virtual address range validity.

Imagine to yourself some thread of the user app access the data it writes
to file simultaneously. What happens to the app if the data it owns changes
without its knowledge about it.

21 окт. 2016 г. 3:53 PM пользователь написал:
>
> Why do you care about user data validity? If a user wants to **** himself
let him do this.
>
> If MM provides MDL then pages have been locked and it is safe to map
them. A user process can free the related virtual address range but this
doesn’t invalidate MDL, the pages still valid.
>
> MmGetSystemAddressForMdlSafe maps MDL pages in the system space, i.e. it
allocates new system PTEs to map pages and these PTEs can’t be manipulated
from a user application, these PTEs don’t depend on user space virtual
address range validity.
>
> —
> NTFSD is sponsored by OSR
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
http://www.osronline.com/page.cfm?name=ListServer&gt;</http:>

What are you talking about? I don’t believe that the question was about encrypting data in a buffer that shares pages with a user visible virtual address range. This can’t work from the beginning.

With direct I/O, the memory manager builds an MDL that describes the
underlying physical pages that comprise the user data buffer. These pages
are probed for access (i.e. “can the user write to this page?”) and then
locked in memory for the duration of the I/O operation. The user may free on
change the protection on their virtual address, but the underlying physical
pages remain locked in memory. It has to work this way, otherwise we’d be
doomed if we allowed devices to DMA into these addresses.

When you call MmGetSystemAddressForMdlSafe, you map a kernel mode address to
the same set of underlying physical pages as the user data buffer. The user
can invalidate their mapping, but they can’t invalidate yours.

The problem with TOCTOU is that the *content* of the buffer can change, so
you can’t do things like this:

inputStruct = (PMY_STRUCT)MmGetSystemAddressForMdlSafe();

  1. if (inputStruct->Length <= MAX_TX_LEN) {
  2. RtlCopyMemory(myBuf, inputStruct->Buffer, inputStruct->Length)
  3. }

Because the Length field value can change between 1 & 2 above.

All that being said: you can’t encrypt or decrypt directly into the user
data buffer anyway. On write you would scamble the application’s data buffer
(potentially while they are still using it). Read is a bit more subtle, but
the problem there is with the OS use of “dummy pages” to generate large I/Os
to the storage subsystem in order to read fragmented file chunks (this has
been discussed here previously, Google is the best index of the lists)

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntfsd…

Hello,

we are writing a filesystem minifilter to encrypt and decrypt the data which
is going to and coming from the file system. We are intercepting the read
and write IRPs in both pre and post callbacks. And applying
encryption/decryption operations as necessary.

Should we be using direct-IO (rather than buffered-IO) for minifilter
encryption where we encrypt the userland buffer directly? If so, we are
concerned about Time of Check Time of Use vulnerabilities where we use the
function ‘MmGetSystemAddressForMdlSafe’ to get the virtual address from the
MDL in both pre and post callbacks. The risk is that the user process could
have called VirtualFree on the Virtual Address we are trying to encrypt data
at. Please let us know whether we need to take any action to handle the
TOCTOU attack. If the solution is to use
ProbeForRead/ProbeForWrite/Exception Handling, should we be locking the
memory pages in memory?

Another attack we envision is that a userland application could ask us to
encrypt something in a heap managed by ntdll (like Low Fragmentation Heap)
and free and realloc the heap buffer before we start encrypting and we end
up either encrypting a realloced data or heap metadata. This is not as
dangerous though because it would essentially be the userland application
freeing and reallocing the buffer and crashing itself.

Thanks,
S Ramakrishnan

[quote]
The problem with TOCTOU is that the *content* of the buffer can change

[quote]

If a user application changes a virtual address range backed by a file then PTEs that maps this buffer into a user space are marked as dirty and MM will transfer this flag to related PFN( page descriptor ) and flush data again, i.e. there will be a second paging write. In most cases a user application will not notice that data on a drive and in cache/mapped file doesn’t match if the application is consistent in file access.

If a user application employs some funny technique with writing a buffer to a file and changes data in the buffer concurrently before write completes then the application must not expect that the following read returns the most recent data. FSD never accounts for such behavior.

Correct.

I should have prefaced my statement with “TOCTOU is a different category of
problem.” Generally we don’t care about TOCTOU when dealing with data
streams, it shows up more in IOCTL processing when the buffers have a known
structure.

-scott
OSR
@OSRDrivers

wrote in message news:xxxxx@ntfsd…

[quote]
The problem with TOCTOU is that the *content* of the buffer can change

[quote]

If a user application changes a virtual address range backed by a file then
PTEs that maps this buffer into a user space are marked as dirty and MM will
transfer this flag to related PFN( page descriptor ) and flush data again,
i.e. there will be a second paging write. In most cases a user application
will not notice that data on a drive and in cache/mapped file doesn’t match
if the application is consistent in file access.

If a user application employs some funny technique with writing a buffer to
a file and changes data in the buffer concurrently before write completes
then the application must not expect that the following read returns the
most recent data. FSD never accounts for such behavior.