Skip to content

Latest commit

 

History

History
227 lines (187 loc) · 9.2 KB

File metadata and controls

227 lines (187 loc) · 9.2 KB

Mitigation Strategies Analysis for tencent/rapidjson

  1. Locate all instances where rapidjson::Document::Parse() or similar parsing functions (e.g., ParseStream()) are called.
  2. Modify the parsing call to include the kParseIterativeFlag. This flag changes the parsing algorithm from recursive descent to an iterative approach, eliminating stack overflow risk from deep nesting.
  3. Example: Change document.Parse(json_string); to document.Parse<rapidjson::kParseIterativeFlag>(json_string);.
  4. Thoroughly test the application after this change.
  • Threats Mitigated:

    • Stack Exhaustion (Denial of Service) due to Deeply Nested JSON: (Severity: High) - Prevents application crashes from deeply nested JSON.
    • Resource Exhaustion (Denial of Service): (Severity: High) - Reduces memory footprint and processing time for deeply nested JSON.
  • Impact:

    • Stack Exhaustion: Risk reduced from High to Negligible.
    • Resource Exhaustion: Risk reduced from High to Low.
  • Currently Implemented:

    • Yes/No/Partially: (Replace with the actual status)
    • Location(s): (e.g., src/json_parser.cpp:123, src/api/handler.cpp:456)
  • Missing Implementation:

    • Location(s): (e.g., src/legacy_parser.cpp:789)
  1. Identify locations where integer values are retrieved using RapidJSON.
  2. Use the largest appropriate integer type accessor (e.g., GetInt64(), GetUint64()) instead of GetInt() if large numbers are possible.
  3. After retrieving the integer with RapidJSON, perform explicit bounds checking against application-defined MIN_ALLOWED_VALUE and MAX_ALLOWED_VALUE.
  4. Handle out-of-bounds errors appropriately.
  5. Example:
    if (value.IsInt()) { // Or IsInt64(), IsUint64()
        long long num = value.GetInt64(); // Use appropriate type
        if (num < MIN_ALLOWED_VALUE || num > MAX_ALLOWED_VALUE) {
            // Handle the error
        } else {
            // Use 'num'
        }
    }
  • Threats Mitigated:

    • Integer Overflow/Underflow: (Severity: High)
    • Unexpected Behavior: (Severity: Medium)
  • Impact:

    • Integer Overflow/Underflow: Risk reduced from High to Negligible.
    • Unexpected Behavior: Risk reduced from Medium to Low.
  • Currently Implemented:

    • Yes/No/Partially: (Replace with the actual status)
    • Location(s): (e.g., src/data_processor.cpp:200)
  • Missing Implementation:

    • Location(s): (e.g., src/legacy_module.cpp:110)
  1. Identify locations where floating-point values are retrieved.
  2. Use IsDouble() to check the type.
  3. After retrieving with GetDouble(), check for NaN and Inf using std::isnan() and std::isinf().
  4. Check if the value is within application-defined MIN_ALLOWED_VALUE and MAX_ALLOWED_VALUE.
  5. Handle errors (NaN, Inf, out-of-bounds) appropriately.
  6. Example:
    if (value.IsDouble()) {
        double num = value.GetDouble();
        if (std::isnan(num) || std::isinf(num) || num < MIN_ALLOWED_VALUE || num > MAX_ALLOWED_VALUE) {
            // Handle the error
        } else {
            // Use 'num'
        }
    }
  • Threats Mitigated:

    • Floating-Point Parsing Issues: (Severity: Medium)
    • Denial of Service (DoS): (Severity: Medium)
    • Unexpected Behavior: (Severity: Medium)
  • Impact:

    • Floating-Point Parsing Issues: Risk reduced from Medium to Low.
    • Denial of Service: Risk reduced from Medium to Low.
    • Unexpected Behavior: Risk reduced from Medium to Low.
  • Currently Implemented:

    • Yes/No/Partially: (Replace with the actual status)
    • Location(s): (e.g., src/calculation_engine.cpp:80)
  • Missing Implementation:

    • Location(s): (e.g., src/old_data_format.cpp:45)

Mitigation Strategy: Always Check Data Types

  1. Before accessing any value, use RapidJSON's type-checking methods (e.g., IsString(), IsObject(), IsArray(), IsInt(), IsDouble(), IsNull(), IsBool()).
  2. Use the appropriate accessor method based on the expected type.
  3. Handle type mismatches appropriately.
  4. Example:
    if (value.HasMember("data") && value["data"].IsArray()) {
        const rapidjson::Value& dataArray = value["data"].GetArray();
        // Process the array
    } else {
        // Handle the error
    }
  • Threats Mitigated:

    • Unexpected Data Types: (Severity: High)
    • Type Confusion Vulnerabilities: (Severity: Medium)
  • Impact:

    • Unexpected Data Types: Risk reduced from High to Negligible.
    • Type Confusion Vulnerabilities: Risk reduced from Medium to Low.
  • Currently Implemented:

    • Yes/No/Partially: (Replace with the actual status)
    • Location(s): (e.g., src/json_utils.cpp:30)
  • Missing Implementation:

    • Location(s): (e.g., src/quick_and_dirty_parser.cpp:25)
  1. Identify locations where string values are retrieved.
  2. Use GetString() to get the string pointer and GetStringLength() to get the actual length.
  3. Use the returned length. Do not rely on strlen().
  4. For std::string, use: std::string(str, len);.
  5. Example:
    if (value.IsString()) {
        const char* str = value.GetString();
        rapidjson::SizeType len = value.GetStringLength();
        std::string safe_string(str, len); // Use the safe string
        // ... or work directly with 'str' and 'len' ...
    }
  • Threats Mitigated:

    • Null Character Injection: (Severity: High)
    • Buffer Overflows: (Severity: High)
  • Impact:

    • Null Character Injection: Risk reduced from High to Negligible.
    • Buffer Overflows: Risk reduced from High to Low.
  • Currently Implemented:

    • Yes/No/Partially: (Replace with the actual status)
    • Location(s): (e.g., src/string_processor.cpp:60)
  • Missing Implementation:

    • Location(s): (e.g., src/legacy_string_handling.cpp:85)

Mitigation Strategy: Use a Custom Allocator

  1. Create a custom allocator class inheriting from rapidjson::Allocator.
  2. Override Malloc and Realloc to track memory usage and enforce limits.
  3. In Malloc and Realloc, check if the requested allocation exceeds a limit. If so, return nullptr.
  4. When creating the rapidjson::Document, pass an instance of your custom allocator.
  5. Example:
    class MyAllocator : public rapidjson::Allocator {
    public:
        void* Malloc(size_t size) {
            if (totalAllocated + size > MAX_ALLOCATION_SIZE) {
                return nullptr; // Allocation failed
            }
            void* ptr = malloc(size);
            if (ptr) {
                totalAllocated += size;
            }
            return ptr;
        }
    
        void* Realloc(void* originalPtr, size_t originalSize, size_t newSize) {
            // Similar logic to Malloc, handling reallocation
            if (totalAllocated - originalSize + newSize > MAX_ALLOCATION_SIZE)
            {
                return nullptr;
            }
            void* ptr = realloc(originalPtr, newSize);
            if(ptr)
            {
                totalAllocated += (newSize - originalSize);
            }
            return ptr;
        }
    
        void Free(void* ptr) {
            // You might want to track the size here for more accurate accounting
            if (ptr)
            {
                //totalAllocated -= size; // Need to know the size of the allocated block
            }
            free(ptr);
        }
    private:
        size_t totalAllocated = 0;
        static constexpr size_t MAX_ALLOCATION_SIZE = 1024 * 1024 * 10; // 10MB limit
    };
    
    // ... later ...
    MyAllocator allocator;
    rapidjson::Document document(&allocator);
  6. Check for allocation errors after parsing:
    if (document.HasParseError() && document.GetParseError() == rapidjson::kParseErrorDocumentEmpty)
    {
        // Handle potential memory allocation failure
    }
  • Threats Mitigated:

    • Memory Exhaustion (Denial of Service): (Severity: High) - Limits memory RapidJSON can allocate.
  • Impact:

    • Memory Exhaustion: Risk reduced from High to Low.
  • Currently Implemented:

    • Yes/No/Partially: (Replace with the actual status)
    • Location(s): (e.g., src/memory_management.cpp, src/json_parser.cpp)
  • Missing Implementation:

    • Location(s): (If not implemented, describe where it should be implemented.)