github.com/dctrud/umoci@v0.4.3-0.20191016193643-05a1d37de015/doc/site/reference/security.md (about)

     1  +++
     2  title = "Security Considerations"
     3  weight = 25
     4  +++
     5  
     6  umoci is entrusted with taking a particular image and expanding it on the
     7  filesystem (as well as computing deltas of the expanded filesystem). As a
     8  result, umoci must be very careful about filesystem access to avoid
     9  vulnerabilities that may impact other components of the system. If you feel
    10  something is missing from this document, feel free to
    11  [contribute][contributing.md].
    12  
    13  If you've found a security flaw in umoci that comes from a security
    14  consideration we haven't considered before, please follow our instructions on
    15  [how to responsibly disclose a security issue][contributing.md]. Once it has
    16  been resolved, feel free to contribute to this document a description of the
    17  consideration that we were missing.
    18  
    19  [contributing.md]: /contributing
    20  
    21  ### Path Traversal ###
    22  
    23  The most obvious vulnerabilities that umoci has to protect against is path
    24  traversal vulnerabilities. However, path traversal vulnerabilities in umoci
    25  are even more dangerous because umoci has to emulate a `chroot` when
    26  interacting with the filesystem (as well as never mutating inodes in case it
    27  may be referenced by a path external to the root filesystem).
    28  
    29  > **NOTE**: Users are expected to appreciate the risks of interacting with a
    30  > foreign filesystem rootfs, if they intend to not use a virtualization system
    31  > such as `chroot` or containers when interacting with the rootfs umoci has
    32  > expanded.
    33  
    34  There are multiple ways that umoci defends against this. The first and most
    35  important is that all path computation of destination and source paths is done
    36  using the [`filepath-securejoin`][securejoin] library (which was written by the
    37  author of umoci<sup>[1](#foot1)</sup>). `filepath-securejoin` solves this
    38  problem by effectively implementing a variant of `filepath.EvalSymlinks` except
    39  that all symlink and lexical evaluation is done manually within a particular
    40  scope. We have extensive testing (in both projects) to show that a variety of
    41  attacks will not succeed against our implementation.
    42  
    43  In addition, umoci has a series of sanity checks that ensures that operations
    44  that involve modifying the filesystem based on arbitrary image input will not
    45  affect anything outside of the intended directory root. These additions are
    46  purely defensive in nature, as `filepath-securejoin` handles all known
    47  instances of path traversal attacks in this context.
    48  
    49  umoci **does not** attempt to be safe against shared filesystem access during
    50  an `unpack` or `repack` operation. This is because it is not possible with any
    51  modern Unix<sup>[2](#foot2)</sup> system to safely ensure that a particular
    52  user-space path evaluation will be atomic (nor that the returned result cannot
    53  later become unsafe given further filesystem manipulation). Once an `unpack` or
    54  `repack` operation has completed, arbitrary filesystem modification of the root
    55  filesystem will not cause umoci to act unsafely in future operations.
    56  
    57  umoci also defends against inode mutation by always replacing inodes. This
    58  actually makes the code simpler, but makes sure that hardlinks to inodes inside
    59  a root filesystem won't see any modifications because of umoci (not that
    60  umoci currently permits unpacking into existing directories).
    61  
    62  <a name="foot1">1</a>: The implementation linked is loosely based on Docker's
    63  implementation of a similar concept (to protect against similar path
    64  traversals). Interestingly, the security vulnerabilities that alerted Docker to
    65  this issue several years ago were discovered and fixed by this author as well.
    66  
    67  <a name="foot2">2</a>: Interestingly, Plan9 has effectively solved this problem
    68  by removing symlinks and instead using namespaces. However, umoci's main user
    69  demographic is not Plan9 so this tid-bit is not of much use to us.
    70  
    71  [securejoin]: https://github.com/cyphar/filepath-securejoin
    72  
    73  ### Arbitrary Inode and Mode Creation ###
    74  
    75  Note that this attack is only applicable if umoci is being executed as a
    76  **privileged user** (on GNU/Linux this means having `CAP_SYS_ADMIN` and a host
    77  of other capabilities). umoci running in rootless mode cannot create
    78  arbitrary inodes due to ordinary access control implemented by the operating
    79  system (umoci only uses standard VFS operations to implement rootless mode,
    80  which have very well-understood access control restrictions).
    81  
    82  Effectively this attack boils down to the fact that a `tar` archive (which is
    83  what makes up the layers in OCI images) contains inode information that can be
    84  used to cause umoci to create block devices with arbitrary major and minor
    85  numbers. In the absolute worst case, this could allow a user to create a
    86  world-writeable inode that corresponds to the host's hard-drive (or
    87  `/dev/kmem`). There are a variety of other possible attacks that can occur.
    88  Note that the default umoci runtime configuration defends against containers
    89  from being able to mess with such files, but this doesn't help against
    90  host-side attackers. This attack also could be used to provide an unprivileged
    91  user (in the host) access unsafe set-uid binaries, allowing for possible
    92  privilege escalation.
    93  
    94  umoci's defence against this attack is to make the `bundle` directory `chmod
    95  go-rwx` which will ensure that unprivileged users won't be able to resolve the
    96  dangerous inode or setuid binary (note that bind-mounts can circumvent this,
    97  but a user cannot create a bind-mount without being able to resolve the path).
    98  
    99  ### Compression Bomb Attacks ###
   100  
   101  OCI images specifically require implementations to support layers compressed
   102  with `gzip`. This results in [gzip bomb attacks][gzip-bomb] being potentially
   103  practical. In the worst cases this can result in denial-of-service attacks, if
   104  umoci is run in a context without any storage or I/O quotas.
   105  
   106  umoci uses the [Go standard library implementation of `gzip`][go-gzip], which
   107  *does not appear* to support multiple-round decompression. This somewhat
   108  reduces the amplification nature of this attack, but the attack is still
   109  present.
   110  
   111  **umoci currently has no specific defences against this attack.** There is a
   112  very trivial solution that we can add, which is a `--maximum-layer-size` flag
   113  that will abort an `unpack` operation if any single layer is deemed too large.
   114  Unfortunately, it does not seem reasonable to enable such an option for all
   115  `unpack` operations, and picking a reasonable default is an even more serious
   116  concern. There does not appear to be much analysis on heuristics that can be
   117  used to detect compression bombs, but I am under the impression that that would
   118  be the only reasonable way to detect this in the general case (a heuristic
   119  based on the Shannon entropy or the compression ratio would be very
   120  interesting).
   121  
   122  A workaround for this problem is to place umoci inside of the relevant
   123  cgroups so that it will not drain the system resources too heavily if
   124  encountering a compression bomb. As mentioned above, detecting generic
   125  compression bombs does not appear to be a solved problem, so this workaround
   126  only helps to reduce the impact and does not mitigate it.
   127  
   128  [gzip-bomb]: https://www.rapid7.com/db/modules/auxiliary/dos/http/gzip_bomb_dos
   129  [go-gzip]: https://golang.org/pkg/compress/gzip/