In September last year I received a programming question regarding multi-level multiple same-base inheritance in C++, under one of my video tutorials on YouTube. I started playing with some tests and went a little too extreme for the likings of Microsoft 32-bit C/C++ Optimizing Compiler (aka Visual C++), which crashed while trying to compile some of the test cases. After some debugging, it turned out that it crashed on a rather nasty memory write operation, which could be potentially exploitable. Given that I was occupied with other work at the time, I decided to report it immediately to Microsoft with just a DoS proof of concept exploit. After 9 months the condition was confirmed to be exploitable and potentially useful in an attack against a build service, but was not considered a security vulnerability by Microsoft on the basis that only trusted parties should be allowed to access a build service, because such access enables one to run arbitrary code anyway (and the documentation has been updated to explicitly state this).

Heads up!

If you are running a build service (Team Foundation Build Service), you might be interested in the following security note in this MSDN article:

Installing Team Foundation Build Service increases the attack surface of the computer. Because developers are treated as trusted entities in the build system, a malicious user could, for example, construct a build definition to run arbitrary code that is designed to take control of the server and steal data from Team Foundation Server. Customers are encouraged to follow security best practices as well as deploy defense in-depth measures to ensure that their build environment is secure. This includes developer workstations. For more information regarding security best practices, see the TechNet Article Security Guidance.
In other words (keep in mind I'm not a build service expert, but this is how I understand it):
  • Having access to a build service is equivalent to being able to execute arbitrary code with its privileges on the build server.
  • It is best to lock down the build service, so that a potential compromise of a developer's machine doesn't grant the attacker an instant "Administrator" on the build server.
  • You should make sure that the machines used by the programmers are fully trusted and secure (this is an obvious weak spot). Owning one dev's machine allows rapid propagation to both the build server and other programmers' machines that use the same build service (e.g. by hijacking the build process and generating "evil" DLLs/EXEs/OBJs/LIBs instead of what really was supposed to be built), not to mention the testers machines, etc.

To sum up, a vulnerability in a compiler doesn't really change the picture that much, since even without exploiting the compiler a person having access to the build service can execute arbitrary code with its privileges.

The code that crashes

The C++ code snippet capable of crashing the Microsoft C/C++ Optimizing compiler is shown below, with most details included in the comments (note: this bug is scheduled to be fixed in the future):

#include <stdio.h>

class A { public: int alot[1024]; };
class B : public A { public: int more[1024]; };
class C : public A { public: int more[1024]; };
class DA : public B,C { public: int much[1024]; };
class DB : public B,C { public: int much[1024]; };

#define X(a) \
 class a ## AA : public a ## A, a ## B { public: int a ## AA_more[1024]; }; \
 class a ## AB : public a ## A, a ## B { public: int a ## AB_more[1024]; }

#define Y(a) \
 X(a); X(a ## A); X(a ## AA); X(a ## AAA); X(a ## AAAA); \
 X(a ## AAAAA); X(a ## AAAAAA); X(a ## AAAAAAA)

Y(D);
Y(DAAAAAAAA);
Y(DAAAAAAAAAAAAAAAA);
X(DAAAAAAAAAAAAAAAAAAAAAAAA);

// Funny story. Without global it doesn't compile (LNK1248).
// But with global it seems to overflow, and it compiles OK.
int global[0x12348];
DAAAAAAAAAAAAAAAAAAAAAAAAAA x;

int main(void) {

 printf("%p\n", &x);
 printf("%p\n", &x.DAAAAAAAAA_more[0]); // <--- customize this with changing
                                        //      DAA...AA_more to different
                                        //      amount of 'A'

 // Funny story no. 2. This above crashes the compiler (MSVC 16.00.30319.01):
 // test.cpp(61) : fatal error C1001: An internal error has occurred in the compiler.
 // (compiler file 'msc1.cpp', line 1420)
 // To work around this problem, try simplifying or changing the program near the locations listed above.
 // Please choose the Technical Support command on the Visual C++
 //  Help menu, or open the Technical Support help file for more information
 // Internal Compiler Error in cl.exe.  You will be prompted to send an error report to Microsoft later.
 //
 // (2154.dd4): Access violation - code c0000005 (first chance)
 // First chance exceptions are reported before any exception handling.
 // This exception may be expected and handled.
 // eax=00000000 ebx=0044dd34 ecx=0000006c edx=00000766 esi=049a8890 edi=049f3fc0
 // eip=73170bb7 esp=0044cd38 ebp=0044cd44 iopl=0         nv up ei pl nz na pe cy
 // cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00010207
 // MSVCR100!_VEC_memcpy+0x5a:
 // 73170bb7 660f7f6740      movdqa  xmmword ptr [edi+40h],xmm4 ds:002b:049f4000=????????????????????????????????
 //

 return 0;
}

As previously mentioned, I didn't really have the time to delve into the details, but it seems the immediate reason of the crash is an invocation of memcpy() with a semi-controlled destination address (EDI is influenced by the source code).

If you manage to prove that the bug is exploitable, let me know!

Vendor communication timeline

2012-09-30: Report sent to Microsoft (DoS only PoC).
2012-10-01: Received ACK + request for further clarification.
2012-10-03: Received information that the crash appears to be exploitable.
2012-10-03: Sent clarification.
2012-11-01: Received confirmation that the issue is exploitable, and that it will not be treated as a security issue, but as a reliability issue.
2012-11-01: Sent description of a potential attack on a build server as a counterargument for it not being a security bug.
2012-11-06: Received ACK + information that the bug will be discussed again with the product team.
2012-12-18: Received "we are still working on it".
2013-01-31: Sent a ping.
2013-06-03: Sent a ping.
2013-06-15: Received information that the bug will be considered as a reliability issue. The build server documentation is updated with a security note.
2013-06-21: Sent a heads up with this blog post.
2013-06-24: Published this blog post.

Update

A pretty awesome blog post with a gathering of compiler crashes (thx goes to Meredith for pointing this out):
57 Small Programs that Crash Compilers

Comments:

2013-06-24 20:11:38 = Dan Kaminsky
{
It's not a security vulnerability, unless you want to define Makefiles as being remote code execution.
}
2013-06-24 21:01:53 = Gynvael Coldwind
{
For the record: We've chatted about this with Dan, et al., on twitter - https://twitter.com/gynvael/status/349241340338507776

To sum up - yep, this isn't a security vulnerability of course, just as the blog post says.

However there might be some scenarios (this bug isn't about one of them) where an attacker could compile code on another server - think SPOJ, different C++-riddle-wargames, online compilers, etc.

As said, I'm not an expert on build systems, though I can imagine one which would not execute a Makefile, but only offer compiling/linking remotely. In such case this might also be considered a security problem.

Another case (as mentioned by Stefan Esser - https://twitter.com/i0n1c/status/349261764321484800) is committing code vs being able to execute code.
However imo this is a deeper problem - being able to commit code to a project by an untrusted entity sounds bad even without crashing a compiler.
}
2013-06-27 09:07:43 = impuls23
{
What about online compiling services and "cloud" based compiling? The most of these services use gcc, but maybe some of them also use the CLI of VC++. This could be an exploitable scenario.
}
2013-06-27 09:58:51 = Gynvael Coldwind
{
@impuls23
Agreed!

I sincerely hope that anyone setting up a limited build service for outright untrusted input understands the risks and uses a proper defense-in-depth approach (basically a sandbox).
Btw, I don't think a compiler code exec bug is the only problem - I'm pretty sure there would be some legitimate compiler features that could be used in some potentially malicious way (like #linclude <somefile> for information disclosure, or .rc file compilation to include certain files on the disk in the output, etc).
}
2013-07-01 09:56:32 = Yuhong Bao
{
Here is real exploit code for a bug in VC6 resource compiler:
http://www.exploit-db.com/exploits/3176/
}
2013-07-05 10:34:56 = Yuhong Bao
{
Here is another one that affects the latest VS2012 Update 3:
http://stackoverflow.com/questions/4290351/why-does-vc-2010-compiler-crash-when-compiling-simple-code
}
2014-01-04 20:36:02 = asd
{
<script>alert('hi');</script>
}

Add a comment:

Nick:
URL (optional):
Math captcha: 5 ∗ 1 + 3 =