Main Content

Library loaded from externally controlled path

Using a library argument from an externally controlled path

Description

This defect occurs when libraries are loaded from fixed or externally controlled unsecure paths and unintended actors can control one or more locations on the paths.

Risk

If an attacker knows or controls the path that you use to load a library, the attacker can change:

  • The library that the program loads, replacing the intended library and commands.

  • The environment in which the library executes, giving unintended permissions and capabilities to the attacker.

Fix

When possible, use hard-coded or fully qualified path names to load libraries. It is possible the hard-coded paths do not work on other systems. Use a centralized location for hard-coded paths, so that you can easily modify the path within the source code.

Another solution is to use functions that require explicit paths. For example, system() does not require a full path because it can use the PATH environment variable. However, execl() and execv() do require the full path.

Extend Checker

By default, Polyspace® assumes that data from external sources are tainted. See Sources of Tainting in a Polyspace Analysis. To consider any data that does not originate in the current scope of Polyspace analysis as tainted, use the command line option -consider-analysis-perimeter-as-trust-boundary.

Examples

expand all

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <limits.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

void* taintedpathlib() {
    void* libhandle = NULL;
    char lib[SIZE128] = "";
    char* userpath = getenv("LD_LIBRARY_PATH");
    strncpy(lib, userpath, SIZE128);//Noncompliant- userpath is tainted
    strcat(lib, "/libX.so");
    libhandle = dlopen(lib, 0x00001);//Noncompliant
    return libhandle;
}

This example loads the library libX.so from an environment variable LD_LIBRARY_PATH. An attacker can change the library path in this environment variable. The actual library you load could be a different library from the one that you intend.

Correction — Change and Check Path

One possible correction is to change how you get the library path and check the path of the library before opening the library. This example receives the path as an input argument but then performs the following checks on the path:

  • The function sanitize_str protects against possible buffer overflows.

  • The function identified_safe_libX_folder checks if the path belongs to a list of allowed paths.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <limits.h>

enum {
    SIZE10  =  10,
    SIZE100 = 100,
    SIZE128 = 128
};

/* Use allowlist */
static const char *libX_safe_folder[] = {
  "/usr/",
  "/usr/lib",
  "/lib"
};

/* Return the index if the input is in the allowlist */
int identified_safe_libX_folder(const char* path)
{
  for (int i = 0; i < sizeof(libX_safe_folder) / sizeof(libX_safe_folder[0]); i ++)
    {
      if (strcmp(path, libX_safe_folder[i]) == 0)
      return i;
    }
  return -1;    
}

/* Function to sanitize a string */
char *sanitize_str(char* s, size_t n) {
  /* strlen is used here as a kind of firewall for tainted string errors */
  if (strlen(s) > 0 && strlen(s) < n)
    return s;
  else
    return NULL;
}

void* taintedpathlib(char* userpath) {
  void* libhandle = NULL;
  const char *const checked_userpath = sanitize_str(userpath, SIZE128);
  if (checked_userpath != NULL) {
    int index = identified_safe_libX_folder(checked_userpath);
    if (index > 0) {
      char lib[SIZE128] = "";
      strncpy(lib, libX_safe_folder[index], SIZE128);
      strcat(lib, "/libX.so");
      libhandle = dlopen(lib, RTLD_LAZY);    
    }
  }
  return libhandle;
}

Result Information

Group: Tainted Data
Language: C | C++
Default: Off
Command-Line Syntax: TAINTED_PATH_LIB
Impact: Medium

Version History

Introduced in R2015b