SV.TAINTED.DEREF
Dereference of an unvalidated pointer
Whenever input data is accepted from the user or the outside environment, it should be validated for type, length, format, and range before it is used. Until this data is properly validated, it is said to be tainted. The SV.TAINTED family of checkers look for the use of tainted data in code.
The SV.TAINTED.DEREF checker flags code that uses tainted data in a dereference operation.
Vulnerability and risk
When a pointer input to the code is not validated properly and is used in a dereference operation, the result can be an attempt to read or write a forbidden memory region, resulting in a program crash, or unintended reading or writing of a valid memory location that can contain sensitive data such as user passwords. This results in a potential security hole that could allow an attacker to:
- Provide unexpected values and cause a program crash
- Read confidential data
- Use malicious input to modify data or alter control flow
- Cause excessive resource consumption
- Execute arbitrary commands
Mitigation and prevention
To avoid tainted input errors:
- understand all the potential areas in which untrusted inputs could enter your software: parameters or arguments, cookies, input read from the network, environment variables, reverse DNS lookups, query results, filenames, databases, and any external systems;
- use a whitelist or 'known good' policy for inputs, rather than relying only on a blacklist or 'known bad' strategy;
- make sure all relevant properties of the input are validated, including length, type of input, ranges, missing or extra inputs, syntax, and consistency;
- if there are security checks on the client side of an applications, make sure they are duplicated on the server side;
- if the application combines inputs from multiple sources, perform the validation after the sources have been combined
Vulnerable code example 1
#include <sys/ipc.h>
#include <sys/shm.h>
#include <string.h>
#define SHMEM_SIZE 1024
typedef struct S_ {
int transaction_id;
int* id;
char* str;
} S;
void use_shared_mem_example(key_t shmem_key, int id) {
int shmem_id = shmget(shmem_key, SHMEM_SIZE, IPC_CREAT);
S* s = (S*) shmat(shmem_id, NULL, 0);
if (s != (S*) (-1)) {
*(s->id) = id; // dereference of untrusted pointer, flagged as SV.TAINTED.DEREF
strcpy (s->str, "Sample signal string" ); // dereference of untrusted pointer via call, flagged as SV.TAINTED.CALL.DEREF
}
shmdt(( void *) s);
}
In the above example, a pointer to a memory shared between processes is dereferenced directly and via a function call. Klocwork flags these operations by raising the SV.TAINTED.DEREF and SV.TAINTED.CALL.DEREF defects.
At line 17: [SV.TAINTED.DEREF] Unvalidated pointer 's->id' that is received from 'shmat' at line 15 is dereferenced at line 17. At line 18: [SV.TAINTED.CALL.DEREF] Unvalidated pointer 's->str' that is received from 'shmat' at line 15 is dereferenced via a call to 'strcpy' at line 18.
A developer of this code can be advised to either use a reliable pointer sanitation before the dereference operations, details of which are beyond this brief checker description, or refrain from dereferencing such pointers at all.
Vulnerable code example 2
#include <string.h>
typedef struct {
void *data;
} request_t;
#define MAGIC_ADDRESS ((void*)0xdeadbeef)
#define MAGIC_SIZE 1024
char* get_sensitive_data();
void* read_from_port() {
// a library function known to return pointer to untrusted data
// for example, read from a fixed memory location
return MAGIC_ADDRESS;
}
void unsafe_dereference() {
request_t* req = read_from_port();
char* data = get_sensitive_data();
memcpy(req->data, data, MAGIC_SIZE); // unsafe dereference inside the function, flagged by SV.TAINTED.CALL.DEREF
}
[SV.TAINTED.CALL.DEREF] Unvalidated pointer 'req->data' that is received from 'read_from_port' at line 18 is dereferenced via a call to 'memcpy' at line 20.
Related checkers
External guidance
Extension
This checker can be extended through the Klocwork knowledge base. See Tuning C/C++ analysis for more information.