Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home› NTFSD

Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


What is the "Correct" way of blocking external usb connection (flash drive, WPD, etc) in 7+?

brad_Hbrad_H Member Posts: 187
edited February 4 in NTFSD

I have seen many different open source projects out there to block usb connection (other than the whitelisted deviceIDs) :

  1. An UpperFilter for different classes (wpd, disk, etc) to detect the connection of an external device in the AddDevice callback, and block it either in the arrival pnp callback or the IRP_MJ_READ, etc
  2. Minifilter drivers that detect USB connection in the instance setup callback that block it by blocking the read/write to it after attaching
  3. Some projects even use IoRegisterPlugPlayNotification to get notified when a usb device arrives and block it using IoRequestDeviceEject!

And perhaps there are even more approaches..

So my question is, what the "correct" way of doing it? I know that there will be always different approaches,
but in terms of being a stable and standard approach, what is the most optimal solution to blocking external USB devices such WPD devices and flash drives, in Windows 7+ using a kernel mode driver?

Basically, if you were given a task of creating such a driver that blocks all external USB connections, other than the whitelist devices (based on deviceid, etc), how would you implement it?

Comments

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    Hello,

    There isn't one approach that fits all, unfortunately :( I found that
    Upper/Lower filters approach will simply fail some devices, even if that is
    not your intention (i.e. devices cannot be attached if your filter is
    present). I did not have sufficient access (or customer interest :D) to
    figure if some information query is the reason, and perhaps not querying
    that works... but for some USB devices Upper filters work, for others Lower
    filters... and at the time others recommended not to filter USB devices in
    kernel mode at all.

    I found that for companies, InTune seems to be the best solution (not
    what a developer wants to hear :)). But a single solution will not work :(
    Unless your desire is to block all devices, and not allow any, in which
    case - Upper/Lower filters works.

    Kind regards, Dejan Maksimovic.
    FS Lead: http://www.alfasp.com
  • brad_Hbrad_H Member Posts: 187
    edited February 4

    @Dejan_Maksimovic said:
    Hello,

    I found that
    Upper/Lower filters approach will simply fail some devices, even if that is
    not your intention (i.e. devices cannot be attached if your filter is
    present).

    So are you saying there was a situation where you couldn't attach to the device in your AddDevice? If so, why? What was the error? Or was it because the device failed a query (such as properties query) during AddDevice callback? Because In that case I guess you can still attach and do the query during arrival pnp right?

    Also what about the other two approaches that I mentioned?

    And is there any other kernel mode approach?

    and at the time others recommended not to filter USB devices in kernel mode at all.

    So are you saying the best approach is to have a device notification callback in user mode and disable the device when it arrives? If so, which usermode APIs do I need to use to register a callback and to block the device properly?

  • brad_Hbrad_H Member Posts: 187

    @Dejan_Maksimovic said:
    Hello,

    There isn't one approach that fits all, unfortunately :( I found that
    Upper/Lower filters approach will simply fail some devices, even if that is
    not your intention (i.e. devices cannot be attached if your filter is
    present). I did not have sufficient access (or customer interest :D) to
    figure if some information query is the reason, and perhaps not querying
    that works... but for some USB devices Upper filters work, for others Lower
    filters... and at the time others recommended not to filter USB devices in
    kernel mode at all.

    Also a side question regarding the UpperFilter approach:
    Which classes do I need to register as a UpperFilter if I want to block external USB devices such as WPD (tablet, phones, etc) and flash drives? I guess only WPD class and Disk class is enough right?

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    The device just failed to start, it didm't return an error to my filter.

    I said for USB, user mode approach was suggested, but I did not try it.

    You need to filter more than NPD and Disk class. We added at least 10 in
    Win7 times.
  • brad_Hbrad_H Member Posts: 187
    edited February 5

    @Dejan_Maksimovic said:
    You need to filter more than NPD and Disk class. We added at least 10 in
    Win7 times.

    What else is there? Because I'm asking about external usb devices that can be used to copy files from the computer to them. Shouldn't they all fall into either disk or WPD?

    Also, in the AddDevice I would send a query IOCTL to the pdo asking if its a External device or not, my question is, is this guaranteed to be true? Or the driver developer for the flash drive can just send a invalid response back and tell me its not external?
    For example can a malicious USB device with a rouge driver bypass this check that I'm doing? Because I am only attaching to external devices in my AddDevice.
    Basically for example can any flash drive have a custom driver of its own that gets loaded when the flash drive is inserted, and that is the one which is responsible for responding to these type of queries, or this pdo is sent to a Microsoft driver that validates whether its actually a external device or not?

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    Yes, there is more, if you mean USB, but not as much if you mean USB
    Storage.
    E.g. Bluetooth can be used to copy files to it, as can NFC, Smart Cards,
    FOBs, etc., even though they aren't USB storage.

    Apple devices have non MTP devices in some gadgets at least, so just MTP
    protection isn't enough.

    I won't list all (that is your job :), plus it changed simce Win 7 times
    most likely).

    Dejan



    What else is there? Are you talking about webcam class, etc? Because I'm
  • brad_Hbrad_H Member Posts: 187

    @Dejan_Maksimovic said:
    Yes, there is more, if you mean USB, but not as much if you mean USB
    Storage.
    E.g. Bluetooth can be used to copy files to it, as can NFC, Smart Cards,
    FOBs, etc., even though they aren't USB storage.

    Apple devices have non MTP devices in some gadgets at least, so just MTP
    protection isn't enough.

    I won't list all (that is your job :), plus it changed simce Win 7 times
    most likely).

    Dejan

    What else is there? Are you talking about webcam class, etc? Because I'm

    Have you ever tried the IoRegisterPlugPlayNotification method? Can I catch everything that UpperFilter can (webcam, apple phones, WPD devices, flash drives, etc) with IoRegisterPlugPlayNotification? If so, then why not just use IoRegisterPlugPlayNotification, considering this one doesn't have the headaches of an UpperFilter and the decision of which classes I need to filter

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    IIRC, it didn't do enough, but I may not remember that right, it was long
    ago.

    Dejan.
  • Scott_Noone_(OSR)Scott_Noone_(OSR) Administrator Posts: 3,631
    edited February 8

    Having done a LOT of work in this space (c.f. US20180365397A1) I can say it's annoyingly complicated 😂

    If you're up at the file system level you're "too high" because you'll miss things like MTP. If you're down at the bus level you're "too low" because it's very difficult to know exactly how Windows is going to present an externally attached device to the user (i.e. just because the USB descriptors don't say it's mass storage doesn't mean it isn't). Then you add in things like eSATA and Thunderbolt and the problem space grows.

    I personally wouldn't trust a solution based on IoRegisterPlugPlayNotification because the eject can fail if the drive is in use. I've never tried to design one of these, but you could probably get around that solution by just plugging and unplugging the drive over and over and waiting for the one time the eject fails because some application is touching the drive. Though whether or not that's OK really depends on your threat model.

    Overall it's pretty easy to come up with a simple solution that makes a cute demo but falls over in a security review.

    -scott
    OSR

  • brad_Hbrad_H Member Posts: 187
    edited February 9

    @Scott_Noone_(OSR) said:
    Having done a LOT of work in this space (c.f. US20180365397A1) I can say it's annoyingly complicated 😂

    If you're up at the file system level you're "too high" because you'll miss things like MTP. If you're down at the bus level you're "too low" because it's very difficult to know exactly how Windows is going to present an externally attached device to the user (i.e. just because the USB descriptors don't say it's mass storage doesn't mean it isn't). Then you add in things like eSATA and Thunderbolt and the problem space grows.

    I personally wouldn't trust a solution based on IoRegisterPlugPlayNotification because the eject can fail if the drive is in use. I've never tried to design one of these, but you could probably get around that solution by just plugging and unplugging the drive over and over and waiting for the one time the eject fails because some application is touching the drive. Though whether or not that's OK really depends on your threat model.

    Overall it's pretty easy to come up with a simple solution that makes a cute demo but falls over in a security review.

    So if you had to implement a device control solution right now that blocks USB devices (Storage, flash drives, webcams, WPD, etc) and allow some based on DeviceId, I assume you would use an UpperFilter, correct?

    But in that case, is there any other class that I need to attach to, other than the DiskDrive class and WPD? Note that for now I don't care about other devices such as cd/dvd-roms, for now I just need to focus on USB devices.
    For example do I also need to attach to Camera class? I have tested two different webcams, but weirdly enough both of them were registered as WPD so my AddDevice got called for them.

    Is there any rule, or it's up to the manufacturers of these devices to decide which class this device belongs to? For example, can a webcam manufacturer register its device as any class that it wants, and register it in a weird class like Battery or Modem and thus bypass this UpperFilter implementation? (Because I obviously cannot attach to every class)

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    Yes, manufacturers can use any clas they want.
    Apple does, so you're already not covering the second most common device
    you want to cover for sure.

    You will have to test whether you cover enough.

    And again, both Upper and Lower filter approach will fail different devices
    (prevent them from starting). E.g., IIRC, Apple devices fail with Upper and
    Samsung with Lower filters.
    And querying the name might be why it fails.. querying properties surely is.
    It obviously differs by (device) OS version.

    Dejan.
  • brad_Hbrad_H Member Posts: 187
    edited February 9

    @Dejan_Maksimovic said:
    Apple does, so you're already not covering the second most common device
    you want to cover for sure.

    That's weird because I Have already tested iPhones (Although the older 7 version) and they were all registered as WPD, so my UpperFilter caught them. Which of their devices don't fall under WPD or DiskDriver? And what's the solution? Because I Can't just register as a upper or lower filter in every class?

    @Dejan_Maksimovic said:
    Yes, manufacturers can use any clas they want.

    So if this is the case that the device manufacturers can use any class they want, doesn't that make the UpperFilter or LowerFilter approach useless? Because then a malicious actor can easily bypass this by creating a USB device that registers itself in a weird class that no one filters, therefore bypassing every device control app? How can I defend against this then? IoRegisterPlugPlayNotification approach is also useless based on what scott said which I agree with (Because I have seen device eject requests fail before, any driver on the stack can Fail it), So what approach is left?

    @Dejan_Maksimovic said:
    IIRC, Apple devices fail with Upper and Samsung with Lower filters.

    Which apple device have you tested that failed the query and what class did it register in? Did you send the query in your AddDevice? I have tried iPhone 7 and it was a WPD device and there was no problem querying its deviceID and properties in my AddDevice?

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    Did you test 12 different iPhone,iPad and iPod generations?
    Remember, none of them need a driver on Windows and if you don't filter ONE
    then security is broken.

    Iirc, iPhone 7 was tested and it had 3 different classes, not just one.

    Dejan.
  • brad_Hbrad_H Member Posts: 187
    edited February 9

    @Dejan_Maksimovic said:
    Did you test 12 different iPhone,iPad and iPod generations?

    Not really, I am at the early stages of R&D so I only tested with an Iphone 7, but the thing is, my method of using an UpperFilter to block the connection worked without any problem when i tested it with an Iphone 7? I didn't see any 3 classes, I was an UpperFilter at WPD class, and after attaching to the device, blocking it worked like a charm, no matter what mode of transfer i tried, the iphone could not get connected.

    But I guess I will have to test it with other iPhones as well now.

    But back to the real question:

    Doesn't this mean that using an UpperFilter approach is basically a useless approach, considering that the class that a device is in is up to the manufacturer, and considering that I can't attach to everything, then this means that I can get easily bypassed?
    So what's the solution?

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    My solution was to change each system's Upper vs Lower filters based on the
    user :(

    Did you try Lower filters and does it work also for you?

    Look up my posts from around 12 years back (just search Upper/LowerFilter
    and my name on NTDEV), I think there is some trace of it and what didm't
    work and suggested alternatives for USB filtering.

    Dejan
  • brad_Hbrad_H Member Posts: 187

    @Dejan_Maksimovic said:
    My solution was to change each system's Upper vs Lower filters based on the
    user :(

    Did you try Lower filters and does it work also for you?

    Look up my posts from around 12 years back (just search Upper/LowerFilter
    and my name on NTDEV), I think there is some trace of it and what didm't
    work and suggested alternatives for USB filtering.

    Dejan

    But the thing is, even the Lower vs Upper filters based on user approach still doesn't solve the problem of a malicious USB device which registers it self in a class that we are not filtering. So what's the solution to that? Because if any device manufacturer can register its USB devices as anything they want, then they can use a random class that no one is filtering (lower or upper).

  • Dejan_MaksimovicDejan_Maksimovic Member - All Emails Posts: 589
    via Email
    True :)
    Bur it has to have drivers present already. So you still don't need to
    filter unknown classes.

    Remember the USB stick that has a keyboard device ID? Think around that,
    and you have a product.
  • brad_Hbrad_H Member Posts: 187
    edited February 10

    @Dejan_Maksimovic said:
    True :)
    Bur it has to have drivers present already. So you still don't need to
    filter unknown classes.

    Remember the USB stick that has a keyboard device ID? Think around that,
    and you have a product.

    I apologize in advance for rookie questions, as I am still learning, but I have three of them:

    1. Considering that there is a USB class {36fc9e60-c465-11cf-8056-444553540000}, also a USBDevice class {88bae032-5a81-49f0-bc3d-a4ff138216d6}, What is their difference, and also why can't I just monitor every USB device by registering as an UpperFilter for the USB class? Aren't all the USB devices no matter what they do (printer, mouse, webcam, etc), at the end a USB device, thus an UpperFilter for USB class should catch them all? If not, why?

    2. Is my understanding correct that when you connect a USB device, the Windows USB bus driver will detect the connection, and create a corresponding PDO for that new device, therefore even if a malicious USB device registers itself as something that its not, for example an Ethernet or keyboard (instead of what it actually is, which is a USB flash drive), then its limited to the functionality of that class right? I mean if it registers only as a keyboard, then it surely cannot act as a flash drive, right?!

    3. Is my understanding correct that when you connect a new USB device, the Windows will search for the corresponding driver file in its driverStore based on the deviceID, therefore a malicious USB device cannot load arbitrary drivers for its functionality, and windows will only load approved drivers from reliable sources, and will not load a driver that is sent to it from the USB device, right?

    Sorry it got way too long, would you mind recommending me a Book or a blogpost that delves into these topics? Non of the Windows kernel programming that I found go into these topics in detail so I can understand the "big picture" that how all of these are connected to each other..

  • OleksandrOleksandr Member Posts: 4

    @brad_H said:

    @Dejan_Maksimovic said:
    True :)
    Bur it has to have drivers present already. So you still don't need to
    filter unknown classes.

    Remember the USB stick that has a keyboard device ID? Think around that,
    and you have a product.

    I apologize in advance for rookie questions, as I am still learning, but I have three of them:

    1. Considering that there is a USB class {36fc9e60-c465-11cf-8056-444553540000}, also a USBDevice class {88bae032-5a81-49f0-bc3d-a4ff138216d6}, What is their difference, and also why can't I just monitor every USB device by registering as an UpperFilter for the USB class? Aren't all the USB devices no matter what they do (printer, mouse, webcam, etc), at the end a USB device, thus an UpperFilter for USB class should catch them all? If not, why?

    2. Is my understanding correct that when you connect a USB device, the Windows USB bus driver will detect the connection, and create a corresponding PDO for that new device, therefore even if a malicious USB device registers itself as something that its not, for example an Ethernet or keyboard (instead of what it actually is, which is a USB flash drive), then its limited to the functionality of that class right? I mean if it registers only as a keyboard, then it surely cannot act as a flash drive, right?!

    3. Is my understanding correct that when you connect a new USB device, the Windows will search for the corresponding driver file in its driverStore based on the deviceID, therefore a malicious USB device cannot load arbitrary drivers for its functionality, and windows will only load approved drivers from reliable sources, and will not load a driver that is sent to it from the USB device, right?

    Sorry it got way too long, would you mind recommending me a Book or a blogpost that delves into these topics? Non of the Windows kernel programming that I found go into these topics in detail so I can understand the "big picture" that how all of these are connected to each other..

    Hi, I'm also in this issue, any progress on this topic?

  • brad_Hbrad_H Member Posts: 187
    edited June 11

    @Oleksandr said:

    @brad_H said:

    @Dejan_Maksimovic said:
    True :)
    Bur it has to have drivers present already. So you still don't need to
    filter unknown classes.

    Remember the USB stick that has a keyboard device ID? Think around that,
    and you have a product.

    I apologize in advance for rookie questions, as I am still learning, but I have three of them:

    1. Considering that there is a USB class {36fc9e60-c465-11cf-8056-444553540000}, also a USBDevice class {88bae032-5a81-49f0-bc3d-a4ff138216d6}, What is their difference, and also why can't I just monitor every USB device by registering as an UpperFilter for the USB class? Aren't all the USB devices no matter what they do (printer, mouse, webcam, etc), at the end a USB device, thus an UpperFilter for USB class should catch them all? If not, why?

    2. Is my understanding correct that when you connect a USB device, the Windows USB bus driver will detect the connection, and create a corresponding PDO for that new device, therefore even if a malicious USB device registers itself as something that its not, for example an Ethernet or keyboard (instead of what it actually is, which is a USB flash drive), then its limited to the functionality of that class right? I mean if it registers only as a keyboard, then it surely cannot act as a flash drive, right?!

    3. Is my understanding correct that when you connect a new USB device, the Windows will search for the corresponding driver file in its driverStore based on the deviceID, therefore a malicious USB device cannot load arbitrary drivers for its functionality, and windows will only load approved drivers from reliable sources, and will not load a driver that is sent to it from the USB device, right?

    Sorry it got way too long, would you mind recommending me a Book or a blogpost that delves into these topics? Non of the Windows kernel programming that I found go into these topics in detail so I can understand the "big picture" that how all of these are connected to each other..

    Hi, I'm also in this issue, any progress on this topic?

    Unfortunately no :(

    But I am very sure (not 100%) that the answer to the third question is true. Windows will only load the approved drivers (WQHL signed) from its driver store when a USB is connected, and if not found, from Microsoft online sources, and loads the driver based on that deviceID, so its not possible to make a malicious USB device that loads a malicious driver. But the experts here can correct me If I'm wrong.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Kernel Debugging 16-20 October 2023 Live, Online
Developing Minifilters 13-17 November 2023 Live, Online
Internals & Software Drivers 4-8 Dec 2023 Live, Online
Writing WDF Drivers 10-14 July 2023 Live, Online