CWE Rule 426
Description
Rule Description
The product searches for critical resources using an externally-supplied search path that can point to resources that are not under the product's direct control.
Polyspace Implementation
The rule checker checks for these issues:
Command executed from externally controlled path
Library loaded from externally controlled path
Examples
Command executed from externally controlled path
This issue occurs when the path to a command executed in the program is constructed from external sources.
An attacker can:
Change the command that the program executes, possibly to a command that only the attack can control.
Change the environment in which the command executes, by which the attacker controls what the command means and does.
Before calling the command, validate the path to make sure that it is the intended location.
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
.
#include <stdlib.h> #include <stdio.h> #include <string.h> enum { SIZE10 = 10, SIZE100 = 100, SIZE128 = 128 }; void bug_taintedpathcmd() { char cmd[SIZE128] = ""; char* userpath = getenv("MYAPP_PATH"); strncpy(cmd, userpath, SIZE100); strcat(cmd, "/ls *"); /* Launching command */ system(cmd);//Noncompliant }
This example obtains a path from an environment variable
MYAPP_PATH
. The path string is tainted.
system
runs a command from the tainted path without
checking the value of the path. If the path is not the intended path, your
program executes in the wrong location.
One possible correction is to use a list of allowed paths to match against the environment variable path.
#include <stdlib.h> #include <stdio.h> #include <string.h> enum { SIZE10 = 10, SIZE100 = 100, SIZE128 = 128 }; /* Function to sanitize a string */ int sanitize_str(char* s, size_t n) { int res = 0; /* String is ok if */ if (s && n>0 && n<SIZE128) { /* - string is not null */ /* - string has a positive and limited size */ s[n-1] = '\0'; /* Add a security \0 char at end of string */ /* Tainted pointer detected above, used as "firewall" */ res = 1; } return res; } /* Authorized path ids */ enum { PATH0=1, PATH1, PATH2 }; void taintedpathcmd() { char cmd[SIZE128] = ""; char* userpathid = getenv("MYAPP_PATH_ID"); if (sanitize_str(userpathid, SIZE100)) { int pathid = atoi(userpathid); char path[SIZE128] = ""; switch(pathid) { case PATH0: strcpy(path, "/usr/local/my_app0"); break; case PATH1: strcpy(path, "/usr/local/my_app1"); break; case PATH2: strcpy(path, "/usr/local/my_app2"); break; default: /* do nothing */ break; } if (strlen(path)>0) { strncpy(cmd, path, SIZE100); strcat(cmd, "/ls *"); system(cmd); } } }
Library loaded from externally controlled path
This issue occurs when libraries are loaded from fixed or externally controlled unsecure paths and unintended actors can control one or more locations on the paths.
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.
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.
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
.
#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); 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.
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; }
Check Information
Category: File Handling Issues |
Version History
Introduced in R2024a
See Also
External Websites
MATLAB Command
You clicked a link that corresponds to this MATLAB command:
Run the command by entering it in the MATLAB Command Window. Web browsers do not support MATLAB commands.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom (English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- 中国
- 日本Japanese (日本語)
- 한국Korean (한국어)