COMMAND

    quota

SYSTEMS AFFECTED

    Win2000

PROBLEM

    Dave  Tarbatt  found  following.   He  has  been looking into disk
    quotas under Windows 2000 and have uncovered a few anomalies.   On
    top of a few peculiarities there appears to be a bug which  allows
    a user to exceed their disk quota  by as much as they wish.   This
    was  tested  with  Windows  2000  Professional build 2195 (release
    version).  Existing files can be  extended even if a user is  over
    quota.   If exploited  by a  malicious user  then at  best it is a
    nuisance at worst it may act as a DoS if the disk if filled.

    After  playing  around  with  the  newly introduced disk quotas in
    Windows  2000  he  soon  uncovered  a  bug  which  would  allow an
    ordinary, unprivileged user to  exceed their allocated disk  quota
    and fill a disk/partition.  Under normal circumstances when a user
    is under quota he discovered  by experiment that new files  can be
    created upto a size  of (Quota - UsedSpace   + 2KB - 1byte),  i.e.
    they can  go overquota  by up  to 2047  bytes.   Not too much of a
    problem.  Extending existing files can be up to (Quota - UsedSpace
    +1KB -1byte) i.e. up to 1023 bytes overquota - nothing much to  be
    worried about.

    However, if you are overquota  new file creation is only  possible
    upto 728 bytes  if (UsedSpace <  Quota+1KB), i.e. you  havn't gone
    more than 1KB overquota.  Exisiting files can be extended by up to
    736 bytes  up until  (UsedSpace >=  Quota+1KB).   Using this point
    alone, Dave  created a  lot of  files with  "echo.>file0000" at  2
    bytes each  to use  up the  user allocated  diskquota and extended
    them up  to the  736 byte  limit per  file -  he was  now way over
    quota.  The limit  of how far over  quota he could go  depended on
    his initial quota and how many tiny files he could create up until
    he hit the  quota then extending  them all.   What if we  create 0
    byte files?.

    Oh dear!   If you are  under quota you  can create as  many 0 byte
    files as you wish.  They count towards nothing.  Then extend these
    files by 736 bytes and your disk starts filling up and up and up...

    How to recreate?   Create an ordinary  unprivileged user and  give
    them a diskquota of,  say, 1MB.  Open  a command prompt and  using
    whatever  means  you  wish,  create  a  lot  of 0 byte files (e.g.
    SHIFT>FILE0000).   Then  append/extend  those  files  by up to 736
    bytes (e.g. ECHO 736-characters-here>>FILE0000).   If you try  and
    extend beyond 736 bytes the file and it's contents get chopped off
    at 674 bytes so for speed disk filling with fewer files don't  try
    and go beyond  736 bytes.   See below for  a batch file  to create
    10,000 of 0 byte files then extend them all to 736 bytes.

    OverQuota.BAT:

    @echo off
    echo Windows 2000 disk (over)quota exploit
    echo Dave Tarbatt 26/02/2000 http://redirect.to/null/
    rem
    rem Create 10,000 zero byte files ('REM>filename' used to work but not any more)
    echo Creating 10,000 zero byte files...
    for %%i in (0 1 2 3 4 5 6 7 8 9) do for %%j in (0 1 2 3 4 5 6 7 8 9) do for %%k in (0 1 2 3 4 5 6 7 8 9) do for %%l in (0 1 2 3 4 5 6 7 8 9) do shift>FILE%%i%%j%%k%%l
    rem
    rem Create a 736 byte file (the largest extent that works)
    echo Creating 736 byte file...
    shift>736.txt
    for %%i in (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22) do for %%j in (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15) do echo.>>736.txt
    rem
    rem Appending the 736 byte file to all the empty ones (extend them)
    echo Appending 736 bytes to all 10,000 files...
    for %%i in (0 1 2 3 4 5 6 7 8 9) do for %%j in (0 1 2 3 4 5 6 7 8 9) do for %%k in (0 1 2 3 4 5 6 7 8 9) do for %%l in (0 1 2 3 4 5 6 7 8 9) do type 736.txt>>FILE%%i%%j%%k%%l
    rem
    echo.
    echo Done. Massively over quota!

    After  some  experiments  Frank  Heyne  thinks he found the reason
    for this behaviour;  there is a  large flaw in  the implementation
    of disk quotas in W2K.

    When you create a file, at  least one cluster on disk is  used for
    this  file.   Even  when  you  create  a  file with a content of 0
    bytes, a directory entry, a file header and a security  descriptor
    are created for this file, using some disk space.

    The only reason we  can imagine is to  stop users from occupy  too
    much disk  space.   Disk space  used by  the current  user is  not
    available for other users.

    How should it  be done?   Obviously, the only  way to do  this, is
    decreasing  the  space  available  for  the  user  every  time  he
    occupies a new chunk on disk by the size of this chunk.  When this
    is done correctly, the sum of  the bytes used by the current  user
    and the free  bytes available for  all users should  always result
    in the same  number (as long  as only this  one user is  using the
    machine).

    How is  it done?   The current  implementation works  as  follows.
    When  the  user  creates  a  new  file,  only the size of the data
    stream  of  this  file  is  subtracted  from  the  number of bytes
    available for the user!  File header, security descriptor,  unused
    space of the  disk sector behind  the data -  all these bytes  are
    lost  for  other  users,  but  are  not taken into account for the
    current user!

    So we have  the result Dave  Tarbatt reported here  - despite disk
    quotas every  user can  fill up  the disk  with files  of 0  bytes
    content.   There is  the bug,  not in  the possibility  to fill up
    these files with some hundred bytes after they are created!   What
    is filled up here is the  space in the sectors reserved for  these
    files - it is lost for other users anyway, even when not filled by
    the curent user!

    Testing?   There  is  an  API  function  GetDiskFreeSpaceEx  which
    reports:

        - the total space available for the current user
        - the free space available for the current user
        - the free space available for all users

    Frank made the  tests on a  2 GB partition  with clusters of  2048
    bytes.  There were  already files deleted by  that user.  What  he
    did repeatedly was creating a file with 100 bytes data and running
    GetDiskFreeSpaceEx afterwards.  The results:

    1. Normally the free space available for the current user did  not
       decrease at  all after  creating a  new file.  But sometimes it
       decreased by 2048 bytes.

    2. The  free  space  available  for  all  users sometimes did  not
       decrease, but  sometimes it  decreased by  4096, 8192  or 16348
       bytes when a single file with 100 bytes data was created.

    3. The free  space available for  the current user  was decreasing
       significantly  slower  than  the  free  space available for all
       users, though no other user was logged on at the test machine.

    Frank did not test how disk quota products of third parties  work,
    but the way Microsoft's quota manager works is just broken.

SOLUTION

    None known.   However, to  prevent DoS  on servers  you should not
    permit people  to write  to the  same partiton  that the operating
    system resides on.

    A NTFS file system  isn't limited by the  number of clusters on  a
    disk.  The  various components of  a file are  called streams, and
    the $data stream is just one of them.  If a file has a small  data
    segment, then  the entire  file can  be stored  in the  MFT, along
    with  the  security  descriptor,  attributes,  name,  etc.  So the
    minimum amount of disk space that  a file can take up is  the size
    of  one  MFT  entry,  which  may  or may not involve an additional
    cluster.  If the file grows,  then the data stream within the  MFT
    is replaced by a pointer to the cluster where the data is  stored.
    Hence, the concept of inodes isn't germane to NTFS.