Main Content

Resource injection

Data input is not properly restricted before being used as a resource identifier

Since R2024a

Description

This defect occurs when a user inputs information such as a port number, filename, or a URL, and the input is not restricted or the input data is not validated or sanitized before being used as an identifier for a resource. This can allow a malicious user to access sensitive or restricted data outside the intended resources.

This defect checker detects the input of data from an untrusted source. Untrusted sources include strings read from stdin using the fread() or fgets() function or from files opened with fopen(). Unlike other Bug Finder checkers, this checker does not check functions that the main() function does not call directly or indirectly (if there is a main() function).

This defect checker is not available in the Polyspace® user interface and is disabled even if you select the value all for the option Find defects (-checkers). To detect the defect, enable the checker explicitly by using the option -checkers RESOURCE_INJECTION.

Risk

If your code allows users to input an identifier used to access a system resource and uses the input without any validation or sanitization, your code is vulnerable to resource injection. A malicious user can inject resource identifiers to access restricted or out-of-scope system resources, which can compromise secure information.

For example, if your code prompts the user to enter a filename, a malicious user could use special characters or directory traversal sequences such as ../ to move to a different folder structure or to specify and access out-of-scope information or system files.

char userInput[256];
printf("Enter the filename: ");
fgets(userInput, sizeof(userInput), stdin);
std::ifstream file(std::string("user_data/") + userInput);
In this case, the user could use a relative path as input to the fgets() function:
../../etc/passwd
This particular user input attempts to access the /etc/passwd file on a Unix-based system by traversing from the location of user_data.

Fix

Validate or sanitize user input before you use it. For example, validating filename inputs can include denying the use of the / character or multiple uses of the . character. If you expect a certain string input, you can check properties such as length and input type.

Extend Checker

If you validate user inputs by using dedicated functions, you can make the resource injection checker aware of your validation and sanitization functions. Suppose that the function resource_validate_inputs() checks user inputs for malicious entries.

int resource_validate_inputs(
     char *,    /* String to check */
     int);      /* Length of string */
Suppose that the nth parameter of this function is the user input to validate. For instance, the first argument in the above signature could be the string to validate.

To make the resource injection checker aware of this function:

  1. Specify this code in a file with extension .dl:

    .include "models/interfaces/resource_injection.dl"
    
    Resource.Basic.validating("resource_validate_inputs", $OutParameterDeref(n-1)).
    
    If n is 1 (that is, the first parameter of the function is the parameter of interest), then the code to include becomes:
    .include "models/interfaces/resource_injection.dl"
    
    Resource.Basic.validating("resource_validate_inputs", $OutParameterDeref(0)).
    

  2. Specify this file using the option -code-behavior-specifications when running a Polyspace Bug Finder™ analysis at the command line. For instance, if the file is named ResourceAdditionalFunctions.dl, use this analysis option:

    -code-behavior-specifications ResourceAdditionalFunctions.dl

Examples

expand all

#include <cstdio>
#include <cstring>

int main() {
    char userInputFilename[256];
    FILE *file;
    const size_t bufferSize = 1024;
    char buffer[bufferSize];

    printf("Enter the filename: ");
    fgets(userInputFilename, sizeof(userInputFilename), stdin);

    userInputFilename[strcspn(userInputFilename, "\n")] = 0;

    file = fopen(userInputFilename, "rb");     // Defect                   
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    size_t bytesRead = fread(buffer, 1, bufferSize - 1, file);
    buffer[bytesRead] = '\0'; // Null-terminate the string

    printf("Data read from the file:\n%s\n", buffer);
    fclose(file);
    return 0;
}

In this example, the code prompts the user to enter a filename and then uses it to navigate to a file. The code then opens, reads, and prints the data from the specified file. However, the code never sanitizes or validates the user input, allowing the potential for a malicious user to navigate to and read the contents of out-of-scope information.

Correction — Validate and sanitize user input before use

You can write your own functions to validate or sanitize the input before using the input to navigate to the resource. In this example, the validation function isValidFilename() validates the user input by preventing the use of characters that could lead to path traversal.

#include <cstdio>
#include <cstring>

bool isValidFilename(const char *filename) {
    //Check for invalid characters or patterns that could lead to path traversal
    for (const char *p = filename; *p; ++p) {
        if (*p == '/' || *p == '\\' || (*p == '.' && *(p + 1) == '.')) {
            return false;
        }
    }
    return true;
}



int main() {
    char userInputFilename[256];
    FILE *file;
    const size_t bufferSize = 1024;
    char buffer[bufferSize];

    // Ask user for the filename
    printf("Enter the filename: ");
    fgets(userInputFilename, sizeof(userInputFilename), stdin);

    // Remove the newline character if present
    userInputFilename[strcspn(userInputFilename, "\n")] = 0;

    // Validate the filename
    if (!isValidFilename(userInputFilename)) {
        printf("Invalid filename.\n");
        return 1;
    }

    
    // Open the file using the safe file path
    file = fopen(userInputFilename, "rb");    // No defect
    if (file == NULL) {
        perror("Error opening file");
        return 1;
    }

    return 0;
}

To make the Polyspace analysis aware of a validation or sanitation function such as isValidFilename() from the example:

  1. Specify this code in a file with extension .dl (for example, sanitizeFunctions.dl):

    .include "models/interfaces/resource_injection.dl"
    
    Resource.Basic.sanitizing("isValidFilename", $OutParameterDeref(0)).
    

  2. Specify this file using the option -code-behavior-specifications when running a Polyspace Bug Finder analysis at the command line.

    -code-behavior-specifications sanitizeFunctions.dl

    See also -code-behavior-specifications.

Result Information

Group: Security
Language: C | C++
Default: Off
Command-Line Syntax: RESOURCE_INJECTION
Impact: High

Version History

Introduced in R2024a