The %n Formatting Vulnerability
Another security pattern is "eliminate the
%n format." For the details, refer to Seacord and the original Rationale for the library that became Annex K. The basic problem with
%n is that the
printf family of functions are intuitively thought of as "output" functions, but the
%n format can be used to modify memory, and therefore provides an attack surface.
These, then, are the
_s versions of the formatted output functions:
fprintf_s, printf_s, snprintf_s, sprintf_s, vfprintf_s, vprintf_s, vsnprintf_s, vsprintf_s, fwprintf_s, snwprintf_s, swprintf_s, vfwprintf_s, vsnwprintf_s, vswprintf_s, vwprintf_s, wprintf_s.
The corresponding input functions implementing patterns I discussed earlier, notably handlers for null arguments, buffer sizes overflow,
RSIZE_MAX, and overlapping stores. The functions are the
_s versions of the formatted input functions; that is:
fscanf_s, scanf_s, sscanf_s, vfscanf_s, vscanf_s, vsscanf_s, fwscanf_s, swscanf_s, vfwscanf_s, vswscanf_s, vwscanf_s, wscanf_s.
Miscellaneous Security Improvements
The Annex contains several other security measures, which I'll summarize quickly.
Bounding Date Values
The following change applies to the time-and-date functions that produce a "year" value. It should be bounded to the interval [0, 9999]; added to the other patterns, this produces the time-and-date functions:
asctime_s, ctime_s, gmtime_s, localtime_s.
The standard guarantees that
memset_s will over-write the argument array, even if the optimizer thinks that those stores are "useless," such as when over-writing a password before leaving a function.
It also provides an extra argument to keep track of previous state information, to avoid static buffers that would prevent re-entrancy or use in a multi-threaded environment:
bsearch_s, qsort_s, strtok_s, wcstok_s.
Chopping and Zero-Fill
Another specified pattern is to chop (or zero-fill) the resulting string if a runtime-constraint error happens:
gets_s, getenv_s, wctomb_s, mbstowcs_s, wcstombs_s, memcpy_s, memmove_s, strcpy_s, strncpy_s, strcat_s, strncat_s, strerror_s, strnlen_s, wcscpy_s, wcsncpy_s, wmemcpy_s, wmemmove_s, wcscat_s, wcsncat_s, wcsnlen_s, wcrtomb_s, mbsrtowcs_s, wcsrtombs_s.
Bounds on buffer allocation
The document provides the bounds that will be needed to allocate buffers: The
strerrorlen_s function tells how many characters will be needed to store the locale-specific error message for one specific
Finally, I should point out a pattern illustrated in all the functions in Annex K: They permit a localized remediation of existing code, without global design changes. Each of the various
_s functions can replace its previous version by changing only one or two lines of the existing code.
The Annex K functions are widely available on Visual Studio and a few other places. Still, there's no reason why they shouldn't already be available on all platforms. Perhaps there is some degree of "not invented here" resistance; I hope this article and others will help create greater marketplace demand. Talk to your compiler/library providers.
Annex L and Undefined Behavior
There has been a tendency to approach the requirements for safety-critical, zero defects, and security with the same developmental methods, producing high-integrity applications at a correspondingly high cost. However, cybercriminal exploits tend to focus on the most popular apps, which are often produced under less-than-ideal schedule and budget constraints. The languages chosen for popular apps are frequently C and C++.
Within WG14 there have been several initiatives to improve software security without sacrificing the efficiency advantages of C or the developmental methodologies that organizations are already familiar with.
Within the world of safety-critical development methods, it is common to target the elimination of all undefined behaviors (UBs) in C, on the grounds that compilers are free to do anything whatever when an app produces UB. However, compiler developers are very influential within WG14, and they know that in almost all cases of UB, the hardware actually produces a benign result, and that often when some corner case is identified as UB, the standard is marking it as "non-portable," and not as "dangerous."
The Analyzability Annex of C11 (Annex L) identifies a small number of UBs as "critical UB," classifying all the others as "bounded UB," and imposes some implementation constraints on the resulting behavior. The net result is that when an implementation provides this analyzable behavior, and the app is subjected to static analysis, the actual app when executed does implement the source code of the program as analyzed.
With the benefit of hindsight, I have found one improvement that I will suggest for the Analyzability Annex: an implementation should be permitted by Annex L to generate code that violates the constraints in the Annex, provided that it produces a warning message when it does so. After all, "analyzability" relies on a project methodology that focuses attention upon the warnings generated by the static analyzer and the compiler, so guaranteeing the production of a warning is all that should be required by Annex L.
The New C Secure Coding Rules Project
ISO and IEC currently define a Technical Specification (TS) to have less than the official status of an International Standard (IS). WG14 has used this less-formal approach to several topic areas (including the Bounds-Checking Library TR 24731-1 mentioned above) for specifications that may benefit from experience in the marketplace before being standardized.
Further work is under way within WG14, a Technical Specification (TS 17961) for "C Secure Coding Rules" (CSCR). Most of the TSs (and ISs) produced by the programming language committees target the compiler-and-library marketplaces, but the CSCR TS primarily targets the static analyzers marketplace.
Since last month's article, C Finally Gets a New Standard, I've now learned that C++11 is available from the ANSI store: go to http://webstore.ansi.org, search for "14882," and select "INCITS/ISO/IEC 14882-2012." It costs US $30 for the PDF. The whole process takes only a few minutes. The C11 standard should be available soon; fill out the form at www.plumhall.com/stds-notify-form.html to be notified when ANSI C11 can be ordered.
Dr. Thomas Plum is Vice President of Technology and Engineering at Plum Hall, Inc., and is a member of the C and C++ committees that developed C11 and C++11. He gratefully acknowledges helpful suggestions from Robert Seacord of CERT and David Keaton, chairman of the US committee for C language.