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).
By the way...
On 22nd Nov'24 we're running a webinar called "CVEs of SSH" – it's free, but requires sign up: https://hexarcana.ch/workshops/cves-of-ssh (Dan from HexArcana is the speaker).
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:
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.
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).
http://www.exploit-db.com/exploits/3176/
http://stackoverflow.com/questions/4290351/why-does-vc-2010-compiler-crash-when-compiling-simple-code
Add a comment: