Opened 6 years ago

Last modified 5 years ago

#12837 assigned Bugs

Binary serialization: crash that may allow jump to attacker-controlled address

Reported by: jepler@… Owned by: Robert Ramey
Milestone: To Be Determined Component: serialization
Version: Boost Development Trunk Severity: Problem
Keywords: security Cc: jepler@…

Description

Using afl-fuzz on some simple programs that use boost binary and xml serialization, I have found a number of crashes and assertion failures.

To test the waters, I am beginning by filing a single bug which may allow a jump to an attacker-controlled address (i.e., the most exploitable-looking crash that has turned up so far). On my test system, it crashes on the instruction shown:

=> 0x000000000044849c <+524>:   mov    (%r12),%rax
   0x00000000004484a0 <+528>:   mov    0x20(%rbp),%r15d
   0x00000000004484a4 <+532>:   mov    %r12,%rdi
   0x00000000004484a7 <+535>:   callq  *0x10(%rax)

Notice that the value loaded at instruction <+524> is used to determine the address to call at instruction <+535>. The value of %r12 interpreted as bytes is "\0\0hive\0\0", which makes me strongly suspect that it is data from the input file (part of the 'serialization::archive' signature, masked off). Generally, the whole text of the input file would be considered under the control of the adversary.

I ran my tests on Debian Jessie amd64 with gcc version 4.9.2 (Debian 4.9.2-10). The following revisions of modularized boost were used (the tip of each master branch at the time of writing, as described by 'git describe --tags --always):

config: boost-1.62.0-57-g1abc59c
core: boost-1.61.0-59-gd753d9a
move: boost-1.63.0
serialization: boost-1.61.0-57-g62bf8fc

The commandline to compile the (non-fuzzing) version of the input test program is:

g++-4.9 -std=c++11 -Os -I serialization/include -I core/include -I move/include -I config/include -o pvec_in pvec_in.cc serialization/src/extended_type_info.cpp serialization/src/extended_type_info_typeid.cpp serialization/src/archive_exception.cpp serialization/src/basic_archive.cpp serialization/src/basic_serializer_map.cpp serialization/src/void_cast.cpp serialization/src/singleton.cpp serialization/src/basic_iarchive.cpp serialization/src/binary_iarchive.cpp serialization/src/basic_iserializer.cpp serialization/src/basic_pointer_iserializer.cpp

The breaking input file is (base-64 encoded):

FgAAAAAAAABzZXJpYWxpemF0aW9uOjphcmNoaXZlDwAECAQIAQAAAAAAAAAAAwAAAAAAAAABAAAA
AAEAAAD0/wEAAAAAAAAAAAEAAAACAAEAAAACAAAAAgAAAAAA

The source for the test harness program (pvec_in.cc) is

#include <fstream>
#include <vector>

#include <boost/shared_ptr.hpp>
#include <boost/archive/binary_iarchive.hpp>
#include <boost/serialization/nvp.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>

struct boxed_int
{
    boxed_int() : i(0) {}
    boxed_int(int i) : i(i) {}
    int i;
    template<class Archive>
    void serialize(Archive &ar, unsigned version)
    {
        ar & BOOST_SERIALIZATION_NVP(i);
    }
};
typedef boost::shared_ptr<boxed_int> pi;

void go(std::istream &is) {
    std::vector<pi> vv;
    try
    {
        boost::archive::binary_iarchive ia(is);
        ia & vv;
    }
    catch(std::exception &e) {}
}

int main(int argc, char **argv) {
    if(argc > 1) {
        std::ifstream is(argv[1]);
        go(is);
    } else {
        go(std::cin);
    }

    return 0;
}

The test harness program either takes the input file on stdin or the name of the input file as the first positional argument.

I can share details about the fuzzing setup if you like.

Thank you for taking the time to consider this issue.

--Jeff

Change History (1)

comment:1 by Robert Ramey, 5 years ago

Status: newassigned

This is pretty interesting. I'm curious about the fuzz testing setup. But I'm not sure what to do about it without undertaking a huge effort - which I'm not prepared to do. But you're issue is legitimate and I'm going to accept and leave open this issue in case someone wants to take it on.

Thanks for your efforts here. I'm sorry I can't be more helpful.

Robert Ramey

Note: See TracTickets for help on using tickets.