You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 22 Next »

Developers should take steps to prevent sensitive information such as passwords, cryptographic keys, and other secrets from being inadvertently visible to other applications. This includes attempting to prevent such data from being written to disk.

Two common mechanisms by which data can inadvertently be written to disk are swapping and core dumps.

Paging/Swapping

Many general-purpose operating systems implement a virtual memory management technique called paging (also referred to as swapping) to transfer pages between main memory and an auxiliary store, such as a disk drive. This feature is typically implemented as a task running in the kernel of the operating system and its operation is invisible to the running program.

Core dumps

A core dump is the recorded state of process memory written to disk for later examination by a debugger. Core dumps are typically generated when a program has terminated abnormally, either through an error resulting in a crash or by receiving a signal that causes such a termination.

The POSIX standard system call for controlling resource limits, setrlimit(), can be used to disable the creation of core dumps. This prevents an attacker with the ability to halt the program from gaining access to sensitive data that might be contained in the dump.

Non-Compliant Code Example

In this example, sensitive information generated by create_secret() is stored in the dynamically allocated buffer, secret, which is processed and eventually deallocated by a call to free(). The memory page containing secret could be swapped out to disk. If the program crashes before the call to free(), the information stored in secret may be stored in the core dump.

char *secret;

secret = (char *)malloc(size+1);
if (!secret) {
  /* Handle Error */
}
secret = create_secret();

/* Perform operations using secret... */

free(secret);
secret = NULL;

Compliant Solution

To prevent the information being written to a core dump, the size of core dumps that the program will generate should be set to 0. This can accomplished by using setrlimit().

#include <sys/resource.h>
/* ... */
struct rlimit limit;

limit.rlim_cur = 0;
limit.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
    /* Handle Error */
}

/* Create or otherwise obtain some sensitive data */
fgets(secret, sizeof(secret), stdin);

Compliant Solution (privileged process on UNIX)

Additionally, processes with elevated privileges can disable paging by "locking" memory in place using either mlock() (POSIX) or VirtualLock() (Windows). This ensures that memory is never copied to the hard drive, where it may be retained indefinitely in non-volatile storage.

This compliant solution not only disables the creation of core files, but also ensures that the buffer is not swapped to hard disk.

#include <sys/resource.h>
/* ... */
struct rlimit limit;

limit.rlim_cur = 0;
limit.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
    /* Handle Error */
}

if (mlock(secret, sizeof(secret)) != 0) {
    /* Handle error */
}

/* Create or otherwise obtain some sensitive data */
fgets(secret, sizeof(secret), stdin);

Compliant Solution (privileged process on Windows)

if (VirtualLock(secret, sizeof(secret)) != 0) {
    /* Handle error */
}

/* Create or otherwise obtain some sensitive data */
fgets(secret, sizeof(secret), stdin);

Exceptions

Risk Assessment

Writing sensitive data to disk preserves it for future retrieval by an attacker, who may even be able to bypass the access restrictions of the operating system by using a disk maintenance program.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MEM06-A

medium

unlikely

high

P2

L3

Related Vulnerabilities

Search for vulnerabilities resulting from the violation of this rule on the CERT website.

References

[[Wheeler 03]] Sections 7.14 and 11.4


MEM05-A. Avoid large stack allocations      08. Memory Management (MEM)       MEM07-A. Ensure that the arguments to calloc() when multiplied can be represented as a size_t

  • No labels