Bugtraq mailing list archives

In response to alleged vulnerabilities in Microsoft Visual C++ security checks feature


From: "Brandon Bray" <branbray () microsoft com>
Date: Thu, 14 Feb 2002 16:50:07 -0800

To be clear, the security check feature introduced in the Microsoft
Visual C++ .NET compiler is NOT vulnerable. The allegation that
applications compiled with Visual C++'s /GS switch some how expose
themselves to more attacks is unfounded and patently false.

The Cigital press release itself says it, "This security feature is
meant to protect potentially vulnerable source code automatically from
_some_ forms of buffer overflow attacks." The expectation is right
there, some forms of buffer overflow attacks can evade the compiler
injected security checks. This understanding makes the following
statement in the Cigital press release questionable:

    The protection afforded by the new feature allows
    developers to continue to use vulnerable string
    functions such as strcpy() as usual and still be
    "protected" against some forms of stack smashing.

No where that I know of has Microsoft suggested this is a wise strategy
for writing secure applications. So far, the only place I have seen such
a statement has been in the Cigital press release. In fact, in the book,
"Writing Secure Code"[1] by Michael Howard and David LeBlanc, we see the
explicit warning the "The /GS option is a significant advancement for
security in Windows-based C and C++ applications, but simply setting
this option does not fix buffer overruns." 

What is quite distressing though is that the Cigital press release
strays from a solid understanding of /GS and changes its position, later
saying "Note that the new feature is meant to protect any program
compiled with the 'protected' compiler feature." Unfortunately, this is
far from the truth and never the intention of the /GS feature.

When the Visual C++ compiler team invented the /GS switch[2], there were
several challenges.  First, the feature had to perform well enough for
developers to consider using it. If the security checks perturbed the
code such that it was noticeably slower, I truly doubt anyone would use
this. Secondly, we had to consider how many possible buffer overrun
attacks these security checks would detect. Certainly, trying to detect
all buffer overruns was out of the question for several reasons: (1) C
and C++ are inherently dangerous and not all attacks are buffer
overruns, (2) in many cases the operating system and hardware support
are needed to capture attacks.

Notably, it is encouraging to be part of a team that is doing something
to address buffer overrun problems. While the rest of Microsoft is
focused on auditing source code making our way to having the most secure
products in the world, we in the compiler team are focusing on what we
can do to go after the holy grail, "Ferret out and possibly neutralize
the buffer overruns." To that end, not only is there /GS but there is
/RTCsu which can find other devastating code flaws. Most other compilers
offer nothing near these advantages, and if they do they are often
unusable due to heavy performance degradation. I'm glad to know that
everyone at Microsoft is at least doing something towards the goal of
secure code.

We maintain the opinion that fixing source code to eliminate buffer
overruns is the best and only solid approach to securing software. The
compiler team believes that security checks should be in optimized
builds as an insurance policy for the vulnerabilities you did not know
about. Critics might claim that all vulnerabilities are easy to find;
however, any experienced security expert should know that buffer
overruns are not always simple to find. In fact, they can be incredibly
difficult as evidenced by most third generation attacks[3]. Thus anyone
truly interested in writing secure code would not hesitate to use /GS
for their builds.

Now, for those who want some nitty-gritty details: /GS, as said earlier,
was not designed to catch all buffer overrun attacks. So what attacks
does it catch?  It catches overruns that overwrite the return address in
a one-stage attack. Since this attack is always available to an
attacker, it was the most obvious one to preclude. From Microsoft tests,
this has shown it would "protect" anywhere between 40% and 60% of
vulnerable functions. The attack Cigital shows is a two-stage, which is
statistically rare but obviously not impossible.

The Cigital report alleges that the presence of a user defined handler
or a globally predetermined location for the security cookie weakens the
security check architecture and introduces vulnerabilities to
applications. This position is patently false. In order to exploit
either of these pieces of the /GS architecture, a two-stage attack is
required. Thus, if we were to remove or protect either the user defined
handler or the global cookie value, an attacker would still be able to
use the two stage attack to hijack any other value on the stack and
completely evade the stack cookie[4]. Secondly, claiming that the
presence of /GS introduces vulnerabilities into the code is pure
non-sense. The buffer overrun is the vulnerability, and /GS is not
introducing any overruns.

We could easily change the /GS architecture to thwart the attack
demonstrated by Cigital, but it would do no good. Besides simply making
the security check architecture slower, many other targets of the same
attack exist.

When it comes down to it, the only problem I see with the /GS feature is
that our documentation explicitly states what the security checks do
catch, but omits what /GS do not detect. The architecture for /GS does
not expose vulnerabilities in a program, and therefore does *not*
warrant being fixed.

Regards,
Brandon Bray
Visual C++ Compiler Team

[1] "Writing Secure Code" is the prescriptive guide to Microsoft
developers for, oddly enough, writing secure code.

[2] Cigital alleges that the /GS security check feature was a port of
StackGuard. This happens to be untrue, as both technologies were
invented independently.

[3]
http://www.blackhat.com/presentations/bh-europe-01/halvar-flake/halvar.p
pt

[4] Products such as StackGuard are unable to truly protect against this
situation either. Eventually, hardware support is the only way to
address this particular problem.


Current thread: