Skip to content

Latest commit

 

History

History
127 lines (101 loc) · 9.86 KB

File metadata and controls

127 lines (101 loc) · 9.86 KB

Mitigation Strategies Analysis for open-source-parsers/jsoncpp

  1. Review jsoncpp Features: Examine the jsoncpp documentation (specifically the Json::Features class) and identify features that your application does not require. Common examples include:

    • allowComments: If you don't expect or allow comments in your JSON input, disable this.
    • strictRoot: Enforces that the JSON document has a single root element. Generally, this should be enabled.
    • allowDroppedNullPlaceholders: Controls how null placeholders are handled. Review if this is relevant to your use case.
    • allowNumericKeys: Controls whether object keys can be numeric strings. Review if this is relevant.
  2. Configure Json::Reader and Json::Writer: When creating Json::Reader and Json::Writer objects, use the Json::Features class to disable unnecessary features. For example:

    Json::Features features = Json::Features::strictMode(); // Enables strict mode
    features.allowComments_ = false; // Explicitly disable comments
    Json::Reader reader(features);
  3. Consistent Configuration: Ensure that you use the same configuration (features) consistently throughout your application wherever you create Json::Reader or Json::Writer instances.

    • Threats Mitigated:

      • Attacks Exploiting Parser Quirks (Medium Severity): Disabling unnecessary features reduces the attack surface by minimizing the amount of jsoncpp code that is exposed to potentially malicious input. This can prevent attacks that exploit specific parsing behaviors or edge cases related to those features.
    • Impact:

      • Attacks Exploiting Parser Quirks: Risk reduced moderately. The more features you disable (safely), the greater the reduction.
    • Currently Implemented:

      • Not Implemented.
    • Missing Implementation:

      • Missing across the entire project. Needs to be applied when configuring Json::Reader and Json::Writer instances.
  1. Never Assume Key Existence: Do not directly use Value::operator[] with a key that might come from untrusted input without first checking if the key exists.

  2. Use Value::isMember(): Before using operator[], always use Value::isMember(key) to check if the key exists within the Json::Value object.

  3. Handle Missing Keys: If isMember() returns false, handle the case appropriately. This might involve:

    • Returning an error.
    • Using a default value.
    • Logging a warning.
  4. Prefer Value::get(): Strongly consider using Value::get(key, defaultValue) instead of operator[]. This method allows you to specify a default value to be returned if the key does not exist, making your code more robust and concise. Example:

    Json::Value root;
    // ... (parse JSON into root) ...
    std::string name = root.get("name", "default_name").asString(); // Safe access
    • Threats Mitigated:

      • Unintended JSON Modification (Medium Severity): Prevents accidental creation of new keys in the JSON structure due to typos, unexpected input, or malicious attempts to inject data. operator[] on a non-existent key creates that key with a default value.
      • Potential Memory Issues (Low Severity): In some (less common) scenarios, repeatedly creating new keys with operator[] could contribute to memory fragmentation or other memory-related problems, although this is less of a primary concern than unintended modification.
    • Impact:

      • Unintended JSON Modification: Risk reduced significantly.
      • Potential Memory Issues: Risk reduced slightly.
    • Currently Implemented:

      • Partially Implemented: Some parts of the code use isMember(), but not consistently.
    • Missing Implementation:

      • Not consistently implemented across all code that accesses JSON values using keys. Needs a thorough code review and refactoring to ensure every use of operator[] with a potentially untrusted key is preceded by an isMember() check or replaced with get().
  1. try-catch Around Parsing: Enclose all calls to jsoncpp parsing functions (primarily Json::Reader::parse()) within try-catch blocks. jsoncpp can throw exceptions (like Json::RuntimeError or Json::LogicError) if parsing fails.

  2. Specific Exception Handling (If Possible): If jsoncpp provides specific exception types, catch them individually to handle different error conditions more precisely. However, catching the base std::exception is also acceptable as a fallback.

  3. Access Error Details: Within the catch block, access the exception's error message (usually via what()) to get details about the parsing failure.

  4. Log Errors (Carefully): Log the parsing error, including the error message and, if safe, a portion of the offending input. Be very careful about logging the entire input, as it might contain sensitive data. Consider logging only a truncated version or a hash of the input.

  5. Generic Error Responses: Never expose the raw jsoncpp error message (from what()) directly to the user or client. Return a generic error message (e.g., "Invalid JSON input," "Failed to process request").

  6. Fail Gracefully: Ensure that your application handles parsing errors gracefully. The application should not crash, enter an infinite loop, or become unstable due to a parsing error. Implement appropriate fallback mechanisms or error recovery procedures.

    • Threats Mitigated:

      • Denial-of-Service (DoS) via Crafted Input (Medium Severity): Prevents attackers from crashing your application by providing malformed JSON that triggers unhandled exceptions during parsing.
      • Information Leakage (Low Severity): Prevents internal details about your application or the jsoncpp library (potentially revealed in the exception message) from being exposed to attackers.
    • Impact:

      • DoS via Crafted Input: Risk reduced significantly.
      • Information Leakage: Risk reduced significantly.
    • Currently Implemented:

      • Partially Implemented: Some try-catch blocks are present, but not consistently around all parsing operations.
    • Missing Implementation:

      • Not consistently implemented. Needs a thorough review to ensure that all calls to Json::Reader::parse() are properly wrapped in try-catch blocks, that exceptions are handled correctly, and that error messages are sanitized before being exposed externally.
  1. Post-Parsing Type Checks: After parsing the JSON with jsoncpp and obtaining a Json::Value object, perform explicit type checks before using any extracted values. Use jsoncpp's built-in type-checking methods:

    • value.isNumeric(): Checks if the value is any numeric type.
    • value.isInt(), value.isUInt(), value.isDouble(): Checks for specific numeric types.
    • value.isString(): Checks if the value is a string.
    • value.isBool(): Checks if the value is a boolean.
    • value.isArray(): Checks if the value is an array.
    • value.isObject(): Checks if the value is an object.
    • value.isNull(): Checks if the value is null.
  2. Explicit Type Conversion: After verifying the type, use jsoncpp's corresponding conversion methods to get the value in the desired type:

    • value.asInt(), value.asUInt(), value.asDouble()
    • value.asString()
    • value.asBool()
  3. Handle Type Mismatches: If the type check (is...()) fails or the conversion (as...()) is not possible (e.g., trying to call asInt() on a string value), handle the error gracefully. This might involve:

    • Rejecting the entire input.
    • Using a predefined default value.
    • Logging an error and continuing (if appropriate).
    • Returning a specific error message to the user/client.
  4. Example:

    Json::Value root;
    // ... (parse JSON into root) ...
    
    if (root.isMember("age") && root["age"].isInt()) {
        int age = root["age"].asInt();
        // ... use age ...
    } else {
        // Handle the error: "age" is missing or not an integer
    }
    • Threats Mitigated:

      • Type Confusion Attacks (High Severity): Prevents attackers from providing a value of an unexpected type, which could lead to crashes, logic errors, or unexpected behavior in your application. This is a critical defense against a wide range of vulnerabilities.
      • Data Validation Bypass (Medium Severity): Ensures that values conform to the expected types, even if they are technically valid JSON according to the basic syntax.
    • Impact:

      • Type Confusion Attacks: Risk reduced significantly. This is one of the most important mitigations.
      • Data Validation Bypass: Risk reduced moderately.
    • Currently Implemented:

      • Partially Implemented: Some data type checks are performed in the data processing module.
    • Missing Implementation:

      • Not consistently implemented across all modules that use parsed JSON data. Needs to be applied systematically to every value extracted from the Json::Value object before that value is used in any further processing.