• Show log

    Commit

  • Hash : 12bcc7a9
    Author : Patrick Steinhardt
    Date : 2019-06-21T15:53:54

    commit_list: fix possible buffer overflow in `commit_quick_parse`
    
    The function `commit_quick_parse` provides a way to quickly parse
    parts of a commit without storing or verifying most of its
    metadata. The first thing it does is calculating the number of
    parents by skipping "parent " lines until it finds the first
    non-parent line. Afterwards, this parent count is passed to
    `alloc_parents`, which will allocate an array to store all the
    parent.
    
    To calculate the amount of storage required for the parents
    array, `alloc_parents` simply multiplicates the number of parents
    with the respective elements's size. This already screams "buffer
    overflow", and in fact this problem is getting worse by the
    result being cast to an `uint32_t`.
    
    In fact, triggering this is possible: git-hash-object(1) will
    happily write a commit with multiple millions of parents for you.
    I've stopped at 67,108,864 parents as git-hash-object(1)
    unfortunately soaks up the complete object without streaming
    anything to disk and thus will cause an OOM situation at a later
    point. The point here is: this commit was about 4.1GB of size but
    compressed down to 24MB and thus easy to distribute.
    
    The above doesn't yet trigger the buffer overflow, thus. As the
    array's elements are all pointers which are 8 bytes on 64 bit, we
    need a total of 536,870,912 parents to trigger the overflow to
    `0`. The effect is that we're now underallocating the array
    and do an out-of-bound writes. As the buffer is kindly provided
    by the adversary, this may easily result in code execution.
    
    Extrapolating from the test file with 67m commits to the one with
    536m commits results in a factor of 8. Thus the uncompressed
    contents would be about 32GB in size and the compressed ones
    192MB. While still easily distributable via the network, only
    servers will have that amount of RAM and not cause an
    out-of-memory condition previous to triggering the overflow. This
    at least makes this attack not an easy vector for client-side use
    of libgit2.