Archive for the ‘SDL’ Category

Getting Around Conditionally Banned APIs When Using Microsoft’s banned.h Header File

December 8th, 2009 by Ramsey Dow

This code sample makes use of banned.h, a Microsoft-supplied header file that deprecates dangerous CRT functions. Microsoft also poisons these functions on UNIX if you include banned.h there. This is a Good Thing, but what about the fact that they banned strlen? The banned API page states:

For critical functions, such as those accepting anonymous Internet connections, strlen must also be replaced.

That’s good advice for cases where you want to operate on untrusted data. In those cases they tell you that you should use strnlen_s. The problem is, banned.h straight out bans strlen. There is no way to tell it that hey, this particular invocation is safe because I control the buffer in all aspects. Nope, sorry. You can’t use strlen. Or can you?

Here is a code sample that uses banned.h to deprecate unsafe APIs, yet still manages to invoke strlen when necessary. The sample works in both Visual Studio on Windows and GCC on UNIX.

 
//
 
//  banned_test.c
//  20091208 ramsey@casabasecurity.com
//
//  A sample program that illustrates how to "grandfather in" banned APIs
//  for use when they are marked deprecated (Windows) or poisoned (UNIX)
//  by the compiler.
//
//  to compile on Windows:
//  cl /GS /W4 /WX banned_test.c
//
//  to compile on UNIX:
//  gcc -Wall -Werror banned_test.c
 
#if defined _WIN32
 
#include <windows.h>
#endif    // _WIN32
 
#include <stdio.h>
#include <string.h>
#if defined _WIN32
 
size_t my_strlen(const char *string)
{
  size_t len;
  #pragma warning(push)
  #pragma warning(disable:4995)
  len = strlen(string);
  #pragma warning(pop)
  return len;
}
 
#else
#define my_strlen strlen
#endif    // _WIN32
 
#include "banned.h"
 
int main(int ac, char **av)
{
  char *str = "foo";
  #if defined _WIN32
  UNREFERENCED_PARAMETER(ac);
  UNREFERENCED_PARAMETER(av);
  #endif    // _WIN32
  #if defined _WIN32
  (void)printf("len is %Id\n", strlen(str));
  #else
  (void)printf("len is %zd\n", strlen(str));
  #endif    // _WIN32
  return 0;
}

Note that this code requires the use of Microsoft’s banned.h header file, which can be downloaded here. Stick it in the same directory as the above source file.

To compile the sample in Windows from a Visual Studio Command Prompt:


cl banned_test.c /GS /W4 /WX

As expected, this program will generate an error when run:


banned_test.c

banned_test.c(50) : error C2220: warning treated as error - no 'object' file generated

banned_test.c(50) : warning C4995: 'strlen': name was marked as #pragma deprecated

Now edit banned_test.c and change the strlen on line 50 to my_strlen and recompile:


cl banned_test.c /GS /W4 /WX

It should compile without error. Now run it and you should see:


len is 3

Nifty.

The same code works without change on UNIX (tested on NetBSD):


gcc -Wall -Werror banned_test.c

As with the Windows example, running the program will generate an error, as expected:


banned_test.c:52:31: error: attempt to use poisoned "strlen"

Again, change the occurrence of strlen (this time on line 52) to my_strlen and recompile. It will work and when run, it will say:


len is 3

What’s going on here is simple. While we are banning use of the strlen function, we are still allowing its use selectively through a wrapper that we have “grandfathered in.” This is easy to accomplish in UNIX: we simply

#define my_strlen strlen

prior to including banned.h and use that function call entry point instead. Problem solved. This is not as easy to accomplish with Windows, however, as cl.exe has no notion of “grandfathering in” deprecated APIs. So what we do is wrap strlen in another function. We ignore the deprecation warning that occurs where we make the call to strlen through the judicious application of some Visual Studio-specific pragma instructions. Now all need to do is call in to our new function entry point. We’re good to go. The Windows solution requires a little more work up front, but turns out to be not so hard to accomplish after all.

On the Importance of Good Developer Documentation

November 20th, 2009 by Ramsey Dow

Programmers rely on documentation. It's how we learn to use APIs. Misusing APIs is a leading source of vulnerability. You might think that documentation is a cure to this ailment. Unfortunately, as someone who has been in software development for a long time, I can tell you that documentation quality is not always what it should be. API documentation serves as a reference. I have yet to meet the programmer who can recall every nuance about every API for all the languages they program in. (Were such a programmer to exist, its name might well be Robby the Robot.)

Recently I was converting strings using the mbstowcs_s and wcstombs_s functions. (These are from from the bounds checking extensions to the C Library specified in ISO/IEC TR 24731-1.) These functions allow you to convert multibyte character sequences to and from wide character sequences. These functions are available to C and C++ programmers using Microsoft's Visual Studio compiler. (I am not yet aware of any UNIX compatible compiler that supports the draft TR 24731-1 standard.)

Since these two functions convert strings, it is worth looking at the parameters they expect. (Not doing so is a sure fire way to do something stupid, like enable a buffer overflow.) Looking at the relevant parameters for these two functions, we see:

mbstowcs_s:
[in] sizeInWords
      The size of the wcstr buffer in words.
[in] count
      The maximum number of wide characters to store in the wcstr buffer, not including the terminating null, or _TRUNCATE.

wcstombs_s:
[in] sizeInBytes
      The size in bytes of the mbstr buffer.
[in] count
      The maximum number of bytes to be stored in the mbstr buffer, or _TRUNCATE.

Does count in wcstombs_s account for the terminating NULL or not? Failure to account for this could introduce an off-by-one error which, in turn, may lead to an exploitable condition, such as a buffer overflow. How can we determine this from the documentation? Well, in its current state, we can't. This is what we call a “doc bug.”

Luckily, Microsoft includes the source code for the C Runtime with most Visual Studio SKUs. Assuming you installed Visual Studio in Program Files, you should be able to find the CRT source code in Program Files\Microsoft Visual Studio 9.0\VC\crt\src. CRT source code is included with all Visual Studio SKUs except for the Express Editions. Luckily for Express Edition users, the forthcoming Visual Studio 2010 release finally opens up the CRT sources to Express Edition users. If you are using an Express Edition of VS2008 or earlier, consider grabbing the VS2010 Express beta from here.

In any case, if you have the CRT source code, it is easy to track down the source for wcstombs_s and check to see if the terminating NULL is intended to be accounted for or not. Looking into wcstombs.c we discover this bit of text in the comment for the wcstombs_s function:

size_t n = maximum number of bytes to store in s (not including the terminating NULL)

Clearly, the terminating NULL is not meant to be included. This is as we suspected, but now we have verified it instead of blindly assuming that it would be the case. As security practitioners we should be careful not to make assumptions. Verify instead!

This documentation bug has been reported to Microsoft. With any luck it will get addressed prior to the VS 2010 release on March 22, 2010.

Use the Source, Luke!

October 20th, 2009 by Ramsey Dow

If there's one thing that I've learned throughout the years as a programmer, it is not always safe to trust the documentation. In fact, there is an old saying, “Use the source, Luke!” When possible, you should do just that.

While looking over the CERT Secure C Coding Standard I noticed the following recommendation: ERR30-C. Set errno to zero before calling a library function known to set errno, and check errno only after the function returns a value indicating failure. CERT goes on to write, “[s]ome functions lack documentation regarding errno in the C99 standard.” They follow this up with an example for Windows: “[i]n this compliant solution, errno is not checked because fopen() makes no promise of setting it.” This would be fine, were it true. However, it is false. Let us take a closer look.

It is true that the symbol, errno, appears nowhere in the MSDN documentation for fopen. However, one need only look to fopen.c (included with all commercial Visual C implementations) to see that errno.h is #include'd and errno is indeed set for locked streams, bad names (e.g., empty string), et al.

The use of errno is not as robust in the case of Microsoft's fopen implementation as it is in the implementation on my NetBSD box, but that's not the point. The point is that CERT stated something was true based on documentation when in fact, it was not true. The lesson here is that one cannot simply rely on assumptions based on documentation, one must also look to the source to see what is happening.

In the case of Microsoft's C and secure C runtimes, the source code is available for you to look at, provided you have Visual Studio installed. (Caveat: you don't get the CRT source code if you install Visual C++ Express.) I found the code living on my box under Program Files at Microsoft Visual Studio 9.0\VC\crt\src.

Of course, if you're programming on Windows you should prefer fopen_s to fopen anyway. For the record, the MSDN documentation for fopen_s clearly states that it returns an errno_t, which is the Secure CRT's answer to errno.

Update: I just found out from a source inside the Visual Studio team at Microsoft that Visual Studio 2010 Beta 2's Express Edition SKU contains the CRT source code. That's good news. You can get more information on Visual Studio 2010 Beta 2 here, and you can download it here.

A Vim plugin for highlighting APIs banned by the Microsoft SDL

August 23rd, 2009 by Ramsey Dow

I do a lot of programming, so I live in my editor. I use Vim. If you also use Vim then I've got something to share with you: a new syntax plugin that highlights function calls banned by Microsoft's Security Development Lifecycle (SDL). You can obtain the banned.vim syntax plugin from the Vim script archive.

The banned.vim syntax plugin will highlight C function calls that have been banned by the SDL. It adds functionality to the existing C and C++ Vim syntax plugins. Banned APIs, such as strcpy and others, will appear visually in Vim as if they were errors. It is my hope that this extra attention will cause you to reconsider using the banned API and replace it instead with a safer alternative. Although many of these banned function calls are Windows-specific, there are quite a few that are also available in UNIX and should be avoided. Details on the APIs banned by Microsoft's SDL can be found on Microsoft's site.

Here's a screen shot of banned.vim in action. In this case we're editing str_cat.c, one of the entries from the 2008 SANS Awards for Finding Coding Books with Secure programming Flaws. Notice the banned APIs in the code below?

banned.vim in action

Installing banned.vim is easy. First, you need to know what your runtimepath is, which varies from operating system to operating system. If you don't know what your runtimepath is, check the Vim documentation. Second, create the directory structure after/syntax in your runtimepath directory if it doesn't already exist. Third, copy banned.vim into runtimepath/after/syntax as both c.vim and cpp.vim. That's all there is to installation. There is no need to edit your .vimrc or anything.

I would like to thank Rob Mooney for suggesting this plugin in the first place.

Microsoft SDL blog post about Watcher

April 18th, 2009 by Chris Weber

Microsoft mentioned Watcher's usefulness in Web-security testing and SDL requirements verification. We're working to make this tool better so please share your success stories, bugs or false positives with us.

Help talking to the non-security professionals

January 18th, 2009 by Samuel Bucholtz

Recently, I have been spending a lot of my time working with clients on SDL (Security Development Lifecycle). This is a new trend in the security industry and a welcome development in my opinion. In doing this SDL work, I spend a lot of my time working with developers, testers, and PMs who are not security professionals. Discussing concepts like threat modeling, fuzz testing, response planning, and even security training they can easily get overwhelmed with all the complexity the SDL and computer security in general can entail.

I have found a few techniques that I would like to share to help smooth communication and help the professionals and non- profesionals to get their respective jobs done.

  1. Talk slow. This one should be self evident. Discussing subject matter that is new or confusing to someone is only made more difficult if you talk fast. Listeners have no time to process the new ideas and are instead just trying to keep up.
  2. Be a dictionary. Computer Security contains a vast array of concepts and domain specific jargon. In security it is often difficult to adjust terminology to an audience, so instead, try to gauge the audience and go back and explain or define the words, acronyms, or concepts that they may not be familiar with. The critical point here is to do it immediately after use rather than waiting until the end of the conversation. By that point, it is usually too late and the definition may not be properly associated with the item.
  3. Ask questions. It is very important that you are constantly gauging your audiences comprehension. This does not mean using the Socratic method to lead them in their own exploration of ideas, but rather inquiry for the purposes of confirming that you have successfully conveyed meaning to them. Remember, that in almost all cases, incomprehension on their part is a failure on yours. Questions help to highlight to listeners what elements of the discussion you, yourself, consider important. Also, try asking questions from different angles. Asking oblique or tangentially related things can often spur a better understanding in the audience, just make sure it is not something that would appear out of left field to them.
  4. Do not accept nods. Similar to #3, you need to be able to tell when people really understand and can follow what you are saying. I have found many times when a person would nod as I explained a specific security concept to them or spit back the exact language I used, but when I try to get them to describe the implications or rephrase in their own words, it is evident that they are still confused.
  5. Reiterate. Repetition can be critical to ensuring that concepts "sink in". Note, though, that I used the word reiterate. The reason for this is that you should change the way you say it and words you use when repeating the concept or idea. This can be one of the trickiest techniques, because it is easy to over do it and cause more harm than help. I find it works best when sprinkled into a long conversation, especially if the conversation keeps getting sidetracked by definitions, clarifications, or completely external items.
  6. Make lists. This is probably the favorite for most PMs out there. PMs love lists. There is nothing they want more than to break all this complicated, confusing security stuff into small, easily managable chunks. Lists also help people to take notes by calling out concepts that can be grouped or ordered together. A list of bullet points (even in a conversation) are usually more important than the text before or after. I am not and have never really been a PM, but I think this is part of he genius that makes a good PM. PMs usually have too many things to do and items to keep track of, the only way they can handle it all is to be insanely organized and maintain lists. Helping them or any other detail oriented note taker to do this makes your job easier as much as it does theirs. 
  7. Clarify language. This is similar to #2, but is targeted at the way you discuss things rather that words you may use. Make sure relationsips between things are explicitly called out (ex. First a, second b rather than this…then that). Use active rather than passive forms of verbs and try to minimize wishy washy or otherwise indecisive language. Avoid implications, exaggerations, and make clear when somethin is a WAG (wild assed guess). This can be very challenging for people to do during a spoken conversation so I usually recommend you start by practicing over e-mail. Being careful and spending time picking out the right words and phrasing can double or triple the amount of time it takes to write an e-mail, however in the long run, the amount of time saved due to fewer misunderstandings and resulting errors will make it worth it.
  8. Anticipate. Finally, try to think ahead. As a security professional, you know the processes and outcomes far better that the people you are working with do. Try to divine what might confuse, hinder, or block the people you are working with and try to provide them answers or solutions before the need them. Remember that in most cases you are not a teacher and they are not working with you to learn by trial and error. Sending them off with a hint and letting them waste time trying to discover things on their own is not how tehy should be handled. Instead, inform them, point them at learning resources, or provide a solution and spend time explaining the reasoning behind it. Do you have any that I have missed?

It all comes back to the basics

April 29th, 2008 by Samuel Bucholtz

Recently there has been a lot of talk in the security community about the Flash ActionScript exploit written by Mark Dowd (http://documents.iss.net/whitepapers/IBM_X-Force_WP_final.pdf). I will not go into a breakdown of the exploit as others have already done a great job of blogging about it. What I would like to discuss is two big takeaways that even programmers who are not "uber-hackers" can appreciate.

The first takeaway is the importance of understanding and implementing the fundamentals. The exploit above occurs because of a NULL dereference triggered by an out of memory return by malloc(). I remember in my first C programming class when I was working with a partner an a project and he was trying to properly implement malloc(). I had already been using C for a few years and always checked the return of a function. I could not figure out why he was not checking to make sure sufficient memory had been allocated. He gave me the excuse that it would require a lot of code to check the return value and that since the data structure was small the allocation would fail. Nonsense, as I demonstrated by filling up the 640K of standard memory. He then argued that we would be better off implementing XMS or EMS to access the other 3MB of "high" memory, a silly argument if ever there was one.

When non-security professionals describe what hackers do they often say that hackers look for ways to bypass restrictions and go around roadblocks. This is a somewhat fair description, but what they may not know is that often hackers are merely taking advantage of mistakes or the faulty reasoning of programmers who tried to skip or work around something simple or basic that they felt would be too much work to implement properly. The original "hacks" were simply ways of getting things done quicker, easier, or more elegantly but sometimes there is a fundamental reason for doing things one way and the "hack" just gets you into hot water. Anyone who has ever picked up a C programming book and looked at the function info for malloc() knows that it is NOT guaranteed to return the memory requested. Obviously, it is a BAD idea to simply assume that it succeeded in allocating all the memory requested. Know your functions/methods and how to properly implement them.

The second takeaway for the average programmer is the need to integrate and leverage the latest in security functionality in your code from the ground up. What do I mean by this? Follow-up research on the exploit has shown that if DEP had been turned on and opted-in the exploit would not have worked. DEP marks portions of memory as NX (No Execute). Such areas in memory will trigger a processor fault if an attacker attempts to execute shellcode they have somehow loaded into such memory. Is DEP a panacea- No. But it provides a second layer of defense. Now you might say- DEP is a system setting that users or admins or Microsoft can turn on or off, there is nothing I can do as a programmer. This is not true. First of all, you need to write your application to make sure it works properly with DEP turned on. You need to test your application to verify this. You need to inform users so they know they can safely use DEP with your application.

A number of other features like ASLR (Address space layout randomization), /GS (canary based buffer overflow detection), etc. are provided now by Visual Studio and other compilers or by the latest versions of the Windows operating system. Developers should be building their code to use these basic security tools that are in most cases so easily integrated. None of these features can prevent all security threats, but there are many applications out there using outdated compilers or failing to implementeven the simplest of automated defenses for lack of awareness or a fear of performance degradation. To the former- browse through just a few of the numerous security respurce out there and then review your compiler/linkers security related flags; to the latter- given the massive code bloat in this object oriented development world compared with the (good) old days of hand tuned assembly in a COM file what is a one or two percent more overhead :) .

New Secure Coding Standards

January 22nd, 2008 by Samuel Bucholtz

This has probably been a long time coming, but CERT has announced that they will be hosting a wiki containing secure coding practices for C and C++. This codification of numerous industry best practices and rules of thumb into a single referable source will make the lives of consultants easier when performing code reviews. From Robert C. Seacord of CERT:

The CERT/Coordination Center at the Software Engineering Institute at Carnegie Mellon University has lead a community effort to develop secure coding standards for the C and C++ programming languages. This work is being performed on the secure coding wiki at
www.securecoding.cert.org. In particular, we have made significant
progress on the CERT C Programming Language Secure Coding Standard since work first begun over a year and half ago and our progress as been reviewed by the ISO/IEC WG14 international standardization working group for the programming language C at both the London and Kona meetings.

This has probably been a long time coming, and I will be interested to see what, if any, review tools come out to compare a code base against the standard.

Links:

C – https://www.securecoding.cert.org/confluence/display/seccode/CERT+C+Secu…

C++ – https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageI…