Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

Developers should take steps to prevent sensitive information such as passwords, cryptographic keys, and other secrets from being inadvertently written out to disk or other auxiliary storageleaked. Preventive measures include attempting to keep such data from being written to disk.

Two common mechanisms by which data can is 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 also called 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 it's 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 , which prevents an attacker with the ability to halt the program from gaining access to sensitive data that may might be contained in the dump.

...

Noncompliant Code Example

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

Code Block
bgColor#FFcccc
langc

/* ... */
char *secret;

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

/* Perform operations using secret... */

memset_s(secret, '\0', size+1);
free(secret);
/* ... */secret = NULL;

Compliant Solution (POSIX)

To prevent the information from 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().:

Code Block
bgColor#ccccff
langc

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

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

char *secret;

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

/* Perform operations using secret... */

char *secret;
size_t size = strlen(inputmemset_s(secret, '\0', size+1);
free(secret);
secret = NULL;

Compliant Solution (Privileged Process, POSIX)

The added security from using mlock() is limited. (See the sidebar by Nick Stoughton.)

Processes with elevated privileges can disable paging by locking memory in place using the POSIX mlock() function [IEEE Std 1003.1:2013]. Disabling paging ensures that memory is never copied to the hard drive, where it may be retained indefinitely in nonvolatile storage.

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

Code Block
bgColor#CCCCFF
langc
#include <sys/resource.h>
/* ... */
struct rlimit limit;
limit.rlim_cur = 0;
limit.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &limit) != 0) {
    /* Handle error */
}

long pagesize = sysconf(_SC_PAGESIZE);
if (sizepagesize == SIZE_MAX-1) {
  /* Handle Errorerror */
}

char *secret_buf;
char *secret;

secret_buf = (char *)malloc(size+1+pagesize);
if (!secret_buf) {
  /* Handle Errorerror */
}
strcpy(secret, input);

/* mlock() may require that address be a multiple of PAGESIZE */
secret = (char *)((((intptr_t)secret_buf + pagesize - 1) / pagesize) * pagesize);

if (mlock(secret, size+1) != 0) {
    /* Handle error */
}

/* Perform operations using secret... */

if (munlock(secret, size+1) != 0) {
    /* Handle error */
}
secret = NULL;

memset_s(secret_buf, '\0', size+1+pagesize);
free(secret_buf);
secret_buf = NULL;

Compliant Solution (Windows)

Windows processes can disable paging by locking memory in place using VirtualLock()[MSDN]:

Code Block
bgColor#CCCCFF
langc
char *secret;

secret = (char *)VirtualAlloc(0, size + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if (!secret) {
  /* Handle error */
}

if (!VirtualLock(secret, size+1)) {
    /* Handle error */
}

/* Perform operations using secret... */

SecureZeroMemory(secret, size + 1);
VirtualUnlock(secret, size + 1);

Exceptions

Risk Assessment

VirtualFree(secret, 0, MEM_RELEASE);
secret = NULL;

Note that locking pages of memory on Windows may fail because the operating system allows the process to lock only a small number of pages. If an application requires additional locked pages, the SetProcessWorkingSetSize() API can be used to increase the application's minimum working set size. Locking pages has severe performance consequences and should be used sparingly.

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 programProgram stacks are frequently used for convenient temporary storage, because allocated memory is automatically freed when the function returns. Generally, the operating system will grow the stack as needed. However, growing the stack can fail due to a lack of memory or collision with other allocated areas of the address space (depending on the architecture). When the stack is exhausted, the operating system may terminate the program abnormally. This behavior can be exploited by an attacker to cause a denial-of-service attack in situations where the attacker can control or influence the amount of stack memory allocated.

Recommendation

Severity

Likelihood

Remediation Cost

Priority

Level

MEM06-

A

1 (low)

1 (unlikely)

2 (medium)

C

Medium

Unlikely

High

P2

L3

Automated Detection

Tool

Version

Checker

Description

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C: Rec. MEM06-C

Checks for sensitive data printed out (rec. partially covered)

Related Vulnerabilities

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

References

Related Guidelines

SEI CERT C++ Coding StandardVOID MEM06-CPP. Ensure that sensitive data is not written out to disk
ISO/IEC TR 24772:2013Memory Locking [XZX]
MITRE CWECWE-591, Sensitive data storage in improperly locked memory
CWE-528, Information leak through core dump files

Bibliography

[IEEE Std 1003.1:2013]XSH, System Interface, mlock
XSH, System Interface, setrlimit
[Wheeler 2003]Section 7.14
Section 11.4


...

Image Added Image Added Image AddedMEM05-A. Avoid large stack allocations      08. Memory Management (MEM)       MEM07-A. Ensure that size arguments to calloc() do not result in an integer overflow