Slashdot Mirror


Gosling Claims Huge Security Hole in .NET

renai42 writes "Java creator James Gosling this week called Microsoft's decision to support C and C++ in the common language runtime in .NET one of the 'biggest and most offensive mistakes that they could have made.' Gosling further commented that by including the two languages into Microsoft's software development platform, the company 'has left open a security hole large enough to drive many, many large trucks through.'" Note that this isn't a particular vulnerability, just a system of typing that makes it easy to introduce vulnerabilities, which last time I checked, all C programmers deal with.

33 of 687 comments (clear)

  1. Phew! by rackhamh · · Score: 5, Funny

    Good thing Linux isn't written in...

    Oh. Never mind!

    1. Re:Phew! by andreyw · · Score: 5, Insightful

      No offense, but give a fool a hammer and he'll crack his skull. C is not inherently insecure. C++ is not inherently insecure. If you don't know how to program, please step aside and let others through. I am not some sort of anti-managed-language zealot, I love Python, but to claim that C *as a language* has a terrible security track record is ridiculous. The applications, not the language, might have a terrible track record due to the ineptness of the programmer.

      I mean seriously, this is like claiming ASSEMBLY is a worthless insecure language because you can hang the system while in supervisor mode, due to ineptness? Sheesh.

    2. Re:Phew! by pivo · · Score: 4, Interesting

      I think the point is that it's much easier to inadvertently create security holes when you write code in lower level languages like C. Lots of excellent programmers have written code with security problems, simply because they're focusing on making their code work and not thinking about security. It's an extremely common problem, and while it may be a problem with the developer's focus, it's not generally a problem of low skill levels.

    3. Re:Phew! by owlstead · · Score: 4, Insightful

      Pffft, I am working with a couple of high grade C++ programmers. When they go down using pointers etc. you can be sure they introduce some overflow errors. You need at least a code checker to make sure that the most common mistakes are avoided. This is like saying that Internet Explorer is not insecure, as long as you visit the right web-sites.

      For most applications assembly is a worthless insecure language, and you should stick to a higher level language if you don't want to introduce problems (for anything larger, but probably including "hello world").

    4. Re:Phew! by ArbitraryConstant · · Score: 5, Insightful

      "No offense, but give a fool a hammer and he'll crack his skull. C is not inherently insecure. C++ is not inherently insecure. If you don't know how to program, please step aside and let others through. I am not some sort of anti-managed-language zealot, I love Python, but to claim that C *as a language* has a terrible security track record is ridiculous. The applications, not the language, might have a terrible track record due to the ineptness of the programmer."

      That's just restating the question.

      If managed languages make a certain class of exploits impossible or very unlikely while C doesn't, then C is insecure relative to those languages.

      A good C programmer might be able to cut the exploit rate down to some very small value, but they're going to work pretty hard to get to that point while people in managed languages get it for free. And good C programmers still fuck up sometimes.

      Of course, there's other ways to screw up. No language is immune from security problems. Using a "managed" language is nothing more than risk management, but it's pretty effective.

      --
      I rarely criticize things I don't care about.
    5. Re:Phew! by timeOday · · Score: 5, Insightful
      No offense, but give a fool a hammer and he'll crack his skull. C is not inherently insecure. C++ is not inherently insecure. If you don't know how to program, please step aside and let others through.
      No, the programmer is irrelevant to this argument. Pick any programmer you like, any one in the world. He will make mistakes at some rate. In C, those bugs will translate directly to security holes, whereas in a typesafe language they will not. It's just that simple.

    6. Re:Phew! by Brandybuck · · Score: 4, Insightful

      Then they're not "high grade". If you need to use strings, you use the string class. If you need to use a bounded array you use the STL vector. If you can't use the STL, you guard your arrays. Those three things, which are normal "high grade" C++ coding style, avoids the vast majority of potential overflows.

      --
      Don't blame me, I didn't vote for either of them!
    7. Re:Phew! by jilles · · Score: 4, Insightful

      ASSEMBLY is a totally inappropriate language for the vast majority of applications, including operating system kernels, video card drivers and games. The complexity and security tradeoff simply doesn't justify the performance gains. That's why it isn't used anymore in most of the software industry. The same is true to a lesser extent for C and C++.

      These languages are inherently insecure because they allow for mistakes that other languages do not allow for. Combine this with the fact that it doesn't take a fool to make mistakes and you have the perfect proof that C is inherently insecure. Refute either of those arguments and you might have a point.

      The problem with C is that it takes the inhuman capability to not make mistakes to end up with secure software. That's why all of the long lived C software projects have to be constantly patched to correct mistakes. Buffer overflows are no accidents, they are the predictable result of using C. Use C -> expect to deal with buffer overflows, memory leaks, etc. Every good C programmer knows this.

      The difference between good C software and bad C software is that in the latter case the programmers are surprised whereas in the first case the programmers actually do some testing and prevention (because they expect things to go wrong). Mozilla Firefox comes with a talkback component because the developers know that the software will crash sometimes and want to be able to do a post mortem. The software crashes because the implementation language of some components is C. IMHO mozilla firefox is good software because it crashes less than internet explorer and offers nice features.

      Of course we have learned to work around C's limitations. Using custom memory allocation routines, code verifiers and checkers, extensive code reviews we can actually build pretty stable C software. The only problem is that C programmers are extremely reluctant to let go of their bad habits. Some actually think they are gods when they sit down behind their editors and do such stupid things as using string manipulation functions everyone recommends to avoid like the plague, trying to outsmart garbage collecting memory allocaters by not using them, etc. If you'd build in a switch in the compiler which enforces the use of the improvements listed above, most of the popular C software simply wouldn't compile. But then it wouldn't be C anymore because the whole point of C is to allow the programmer to do all the bad things listed above, even accidentally.

      IMHO programmer reeducation is an inherently bad solution to inherent security problems of the C language. You can't teach people not to make mistakes. You need to actively prevent them from making mistakes. You can make mistakes in other languages but they are a subset of the mistakes you can make in C. Therefore you should use those languages rather than C unless you have a good reason not to. Any other reason than performance is not good enough.

      --

      Jilles
  2. Advertisement? by nuclear305 · · Score: 4, Insightful

    I actually RTFA since it included a sensationalistic phrase like "biggest and most offensive mistakes that they could have made."

    To me, it sounded like a big advertisement for Java.

    It's the developers decision to use unsafe code in the .NET platform. I certainly wouldn't call this a huge mistake made by MS.

    A hunting rifle can be used to kill people. Does that mean the trigger should only work after inserting a valid and current hunting license?

    1. Re:Advertisement? by TWX · · Score: 5, Insightful

      As much as I think his presentation method is tacky, I can agree with some of what he says.

      C and C++ allow for buffer overflows. They allow for improper or intentional coding to cause software to try to violate memory space of other functions or programs. They allow for memory allocation without necessarily providing any cleanup later. In the hands of bad, sloppy, lazy, or malicious programmers these traits have always proven to be a problem time and again on many different platforms. This doesn't mean that these languages are the wrong tool; I'd argue that part of Linux's success is because the kernel and most of the GNU-implemented services are written in these languages, which are flexible. Too much flexibility for the wrong purpose leads to problems though, just as too much rigidity leads to problems when things need to be flexible.

      --
      Do not look into laser with remaining eye.
    2. Re:Advertisement? by miu · · Score: 4, Insightful
      I think he is talking about the fact that the type system of managed code itself could potentially be subverted by unmanaged code added by other developers.

      The article is heavy on sensationalism and short on content so it is difficult to tell what is actually being debated here, but I think that Gosling is claiming that support of C type handling in itself creates a chink in the armor of the CLR, regardless of any particular project's use of that feature.

      --

      [Set Cain on fire and steal his lute.]
    3. Re:Advertisement? by n0-0p · · Score: 5, Insightful

      He's not wrong about the pitfalls of C/C++. It's just that his argument is downright silly when taken in the appropriate context. The .NET "unsafe" code segments are really no different than JNI, except that they integrate much more cleanly into the platform. As much as I dislike Microsoft in general, .NET is an extremely well designed and secure platform. I say this as someone who has spent almost a decade making a living performing software security assessments and developing secure architectures. If you take the time to research it you will find that .NET really feels like the next incremental step after Java, and it takes advantage of a decade's lessons learned in Java.

    4. Re:Advertisement? by Zeinfeld · · Score: 4, Insightful
      The problem here is that it will be very difficult to take Gosling seriously when he talks about anything in future. This does not make me think any better of Sun.

      Nobody is going to use C or C++ to write a completely new program under .NET. There are occasions where I might use C for something I wanted to make cross platform but no way would I ever go near C++.

      Most people who are going to use the new .NET support are people who have legacy C programs and want to gradually transition them to the .NET base in stages. The makes a good deal of sense.

      The other constituency is folk who are writing stuff that is almost but not quite at driver level.

      --
      Looking for an Information Security student project suggestion?
      Try http://dotcrimeManifesto.com/
    5. Re:Advertisement? by ndykman · · Score: 4, Insightful

      Not so. Well, unless you hacked the .Net type verification and loading code, managed to install it over the .Net Framework (not easy, really).

      All use of unsafe features in .Net are marked as such and can't be hidden. So, pointers, unsafe casts, etc. all stick out to the type loader. In fact, if an .Net assembly tries to mark itself as safe and it has unsafe features, the loader won't load it.

      As far as I know, there is no example of unmanaged code that can violate the managed code type system, and .Net was explicitly built to keep this from happening.

      Also, this ignores that C/C++ support is much more complicated in .Net. Yes, there is the IJW (It Just Works) stuff that allows unmodified code to compile to unsafe .Net assemblies, but there is also the C++/CLI stuff, which creates a CLS version of C++.

      Frankly, this seems like a bit of sour grapes to me. .Net does really improve on Java in lots of ways. Yes, James, Java isn't the last word on programming languages. .Net isn't either.

    6. Re:Advertisement? by gburgyan · · Score: 4, Interesting
      I have to agree -- and I'll try to extend your arguments even further.

      In my current job, which involves quite a bit of C#, I had the opportunity to port large chunks of our legacy application from C++ to Managed C++. We didn't gain security benefits, nor did we gain speed; we didn't loose any either. However we gained a lot of maintainability since we now have a single stack-trace to deal with that bridges all of the languages that we have (now reduced to C# and C++ -- down significantly from when we relied heavily on COM)

      The fact that MS gave us that choice is wonderful. If we wanted to be using JNI (which I had the unlucky opportunity to use), we'd not have made much progress at all.

  3. Woah by pHatidic · · Score: 5, Funny

    CowboyNeal is defending Microsoft. Someone take a screengrab, Slashdot's been hacked!

  4. So you mean to tell me by Anonymous Coward · · Score: 5, Insightful

    So you mean to tell me that the father of Java won't be slightly bias?

    C'mon now. There is no vulnerability. Don't post this sort of crap. Its strictly knee-jerk material meant to bend a few people out of shape and start flames. .NET is great (for its target area)
    J2EE is great (for its target area)

    Both are secure, stable and reasonably fast if you are a GOOD programmer. ANYONE who does ANY C or C++ code that will be used in industry needs to ENSURE that they just take a few extra precautions and are aware of secure coding techniques in both languages. Its rather quite simple.

    To sum it up: nothing to see here folks.

  5. Don't disagree with Microsoft... by BlueCup · · Score: 4, Insightful

    I don't disagree with Microsofts position. Yes errors are possible, but it's a programming language, and not Microsofts responsibility. With a case like programming it is the programmers responsibility to release code without exploits... c and c++ are fast, they have many advantages other languages don't have (such as Java) if a programmer decides to take advantage of that, with a slight bump in risk, then I say more power to them.

    --
    WANNAWIKI Wannawiki WannaWiki WANNAWIKI!
  6. What a surprise! by Anonymous Coward · · Score: 5, Insightful

    This could have just as easily read "Java Creator Disses Rival Product, Ignores Flaws in His Own."

    In Java, everything is an object! Oh...except for the basic types, you need to use object wrappers for those.

  7. A truck, eh? by Faust7 · · Score: 5, Funny

    the company 'has left open a security hole large enough to drive many, many large trucks through.'"

    Like, say, a truck about the size of Sun's Java runtime environment.

  8. Java is a type-safe language at the VM level... by patniemeyer · · Score: 5, Insightful

    This is what really distinguishes Java from other languages. The Java verifier is a sort of theorum prover that examines the byte-code and can guarantee that it does not violate certain rules such as forging the type of a reference or under/over-flowing the stack. Because this is done at the verify stage it is still possible to compile the bytecode down to machine level instructions after that and run at full speed. This is why Java is both safe and fast.

    To support C/C++ semantics (ad-hoc pointers) you'd have to throw all that out the window and I assume that's what he's talking about.

    Pat Niemeyer,
    Author of Learning Java, O'Reilly & Associates and the BeanShell Java Scripting language.

    1. Re:Java is a type-safe language at the VM level... by patniemeyer · · Score: 4, Informative

      Yes, actually, it does. Have you checked it recently? The only overhead that natively compiled Java code would have over comparable C++ is that it always does array bounds checking. Other than that you just have to ask yourself, what kind of optimization can a static compiler (C/C++) do that a dynamic, profiling runtime compiler (Java) can't do?

      Garbage collection in Java has been faster than free/malloc in C for years. This is in large part due to the fact that the runtime can recognize very short lived objects and put them on a special part of the heap.

      It's not necessary to use unsafe languages to get performance any more.

      Pat Niemeyer

    2. Re:Java is a type-safe language at the VM level... by hobuddy · · Score: 4, Informative

      You're quite right that Java's speed is excellent these days (for non-GUI code, at least). I've spent a lot of time recently working with a large system that was first implemented in Java (by highly skilled developers) and then ported to C++ (by greenhorns). The C++ port is only 50-100% faster, which isn't worth the price in developer time that's been wasted on memory leaks and other forms of memory corruption that were never a factor in Java. Besides that, supporting multiple platforms with the C++ version is the #definition of pain.

      However, the C++ version uses only about 1/4 or 1/5 as much memory as the Java version, and starts up far more quickly. If a *desktop* application needs to be deployed on older machines, or if the application is so memory-intensive it taxes the limits of today's server hardware, Java still falls flat.

      --
      Erlang.org: wow
    3. Re:Java is a type-safe language at the VM level... by cookd · · Score: 4, Interesting

      Free and malloc are NOT very simple algorithms. They have arbitrary complexity. malloc ranges from the normal case of about 100 instructions (when a block of memory of the correct size is available) to unbounded (when data must be paged out to make enough room for the new allocation and the data for tracking it). Free can also be arbitrarily slow, as releasing one block may trigger a coalesce operation.

      So you have to measure time per malloc and time per free, then total them up and compare it to GC's time per allocation and time spent in GC. In some cases, one will be significantly larger than the other, but in most nontrivial programs, using modern malloc/free and modern GC, it comes out pretty close to even.

      Some argue that the "pause" from GC is a problem. Maybe. Except that as mentioned before, malloc can also "pause" for arbitrarily long times. And a lot of work has been done on "concurrent" GC that doesn't pause. If you can afford paging in from disk (swap file), you can also afford GC's "pause".

      Finally, when you write a big program, you spend incredible effort in your program tracking memory. That takes cycles. "If x then save a copy cause we'll have to free it later, etc."

      The bottom line is that there are some cases where GC still won't work, but those cases are getting smaller and smaller. For most cases, the argument that GC is slow or inefficient just isn't true. Go do some real benchmarks, or go study up on the already published benchmarks. GC is pretty efficient, and malloc/free has no significant speed advantage anymore.

      --
      Time flies like an arrow. Fruit flies like a banana.
  9. What a well researched article! by apoplectic · · Score: 4, Insightful

    New languages such as C# and Visual Basic.NET only produce managed code.

    Hey, what about the keyword unsafe in C#? Sheesh.

  10. It's called unsafe code for a reason by jerometremblay · · Score: 4, Informative

    Unsafe code is not subject to security checks of the .NET virtual machine. To execute unsafe code, you have to specifically grant those rights to the executing program. It is not something automatic.

    Applications that require safety (for example running plugins downloaded from the net) simply don't allow those assemblies to be loaded.

    Where is the problem again?

  11. Why oh why by Anonymous Coward · · Score: 4, Insightful
    When elevators were first invented, people didn't want to use them because people thought they were not safe. They were right. Elevators were not safe. When Mr. Otis invented the safety elevator, which had a catch so that it would not fall even if the cable were cut, people started using elevators. It would be foolish to trust your life to an elevator without such a safety system. You could use it to lift bales of hay or cement powder or something but you wouldn't put a human being in it.

    It's the same with C. We should know by now "you cannot use C to handle untrusted data (ie, data from untrusted machines on the net)". All such data need to be handled in a sandboxed system, a system with safe memory access. This means something like Java or similar things.

    A lot of people will make posts that say things like "C doesn't cause the problems, it's incompetent or lazy programmers who cause the problems." Whatever. No excuse. That's like saying "we shouldn't need seat belts or airbags; all we need is to make sure that drivers don't make mistakes." Drivers and programmers do make mistakes and that's why we need safety mechanisms in both cases. C provides none. Programming in C is like driving around in a car from the fifties, with no seat belts, no airbags, no head rests, no ABS.

    So any decision to extend the use of C is just foolish. What is the purpose of doing this? If people must use horrible legacy code then just use it, but why drag that into new frameworks like .NET?

    It does not compute, for me at least.

  12. Homeowners!! Beware! by Stevyn · · Score: 4, Funny

    No longer should homes be built using nails. All new homes should be built with really strong glue. Even though nails are faster and easier to work with, a carpenter might accidentally smash his thumb with a hammer. Plus, nails contain metal which may warp your home in the event a huge magnet is placed near the house.

    --The Elmer's Glue Foundation for Strength and Security

  13. Re:JNI by patniemeyer · · Score: 4, Informative

    But JNI is not Java... It's an API. For that matter you might consider sockets and network connections to make Java unsafe because they could invoke unsafe applications.

    It is completely fair to point out that .NET allows you to choose safe vs. unsafe code... but it is a little different from the Java scenario in that this is unsafe code that is run through the VM. It's just an odd choice to make.

    Pat Niemeyer
    Author of Learning Java, O'Reilly & Associates

  14. Re:Rediculous by janoc · · Score: 4, Insightful
    Yeah, right - the same problem as with signed ActiveX - once a buffer overflow in the trusted code is found, your security is a fair game - the attacker has to only persuade e.g. your browser to load the buggy but trusted code. The managed languages like C# and Java were invented exactly with the purpose to prevent this kind of holes.

    To me this looks like a similar problem as allowing running native code via ActiveX. Yeah, we have permissions, signing and what ever - how much does it take for a trusted but buggy ActiveX applet to be exploited?

    Huge mistake, IMHO. And do not compare this to JNI - I am no Java expert, but AFAIK you simply cannot call JNI functions from something like web applet by design, whereas here it is on the discretion of the app developer.

  15. I believe Gosling is wrong by frovingslosh · · Score: 5, Funny
    James Gosling this week called Microsoft's decision to support C and C++ in the common language runtime in .NET one of the 'biggest and most offensive mistakes that they could have made.'

    Gosling is dead wrong. I believe that Microsoft will soon prove they are capable of even bigger and more offensive security mistakes.

    Also, the choice to actually use .NET is at least as big of a security error.

    --
    I'm an American. I love this country and the freedoms that we used to have.
  16. C programmer deals with it by Earlybird · · Score: 4, Insightful
    • Note that this isn't a particular vulnerability, just a system of typing that makes it easy to introduce vulnerabilities, which last time I checked, all C programmers deal with.

    Yes, CowboyNeal, but do they want to deal with it, and should they deal with it?

    For every programmer who reads security bulletins and keeps tabs on the latest string-copying buffer overflow issues and fundamental security principles, there are a hundred who don't know or care.

    C is a high-level language that:

    • Has direct access to every part of the operating system and executes instructions directly from memory. This means that malicious code can slip into its memory space through buffer overflow exploitations and the like.
    • Is, in almost all cases/operating systems, running with the same capabilities as the logged-in user, which means it has virtually endless power that ranges from formatting your hard drive to infecting other nodes with worms or looking through your email app's address book. It's not limited to the desktop computer of the hapless Windows user, either: Unix daemons running on servers as non-root users can cause serious havoc.

    Programmers want to be productive -- most want to make things make colourful stuff happen on the screen, not fiddle around with buffer guard code. So the more security can be built into the language and its running environment, the better.

    Many languages, such as Python or Ruby, provide security against what I mention in my first bullet, through a virtual machine. They're not impenetrable, and are of course, as dynamic languages, subject to a different class of security holes (eg., string evaluation of code), but they're a step up from the C level.

    Other languages, like Java, provide capability-based security models, allowing for sandbox environments with fine-grained control over what a program may or may not do. Java's security system is ambitious, but since most Java apps run on the server these days, it's not frequently used, and except for browser applets, Java code tend to run unchecked.

    In a way, Java tries to do what the OS should be doing. Programs run on behalf of its human user, and their destructive power is scary. Why should any given program running on my PC have full access to my documents or personal data? As we're entering an age where we have more and smaller programs, and the difference between "my PC" and "the net" is increasingly blurred. Operating systems need to evolve into being able to distinguish between different capabilities it can grant to programs, or processes -- we need to think about our programs as servants that are doing work for us by proxy.

    The same way you wouldn't let a personal servant manage your credit cards, you don't want to let your program do it -- unless, of course, it was a servant (or, following this metaphor, program) hired to deal with credit cards, which introduces the idea of trust. The personal accountant trusts the bank clerk, who trusts the people handling the vault, who trust the people who built the vault, and so on.

    In short, any modern computer system needs to support the notions of delegated powers, and trust.

    Programmers will certainly never stop having to consider vulnerabilities in code. But painstakingly working around pitfalls inherent in one's language, be it C or indeed .NET -- we need to evolve past that. The users, upon whom we exert so much power, certainly deserve it.

  17. malloc+free: fast, simple, and can be even faster by nothings · · Score: 4, Informative
    Malloc and free are simple algorithms, and whoever told you otherwise was wrong.

    I don't know where you got your understanding of malloc, and especially free, but it's severely out of date. Knuth published about "Boundary Tags" no later than 1973 (citeseer is down, so no link). Saying that a coalesce operation "can be arbirarily slow" is just FUD. A boundary tag makes free() a fast O(1) operation: check the previous block in memory to see if it's free and if so join, a fast O(1) operation; check the next block in memory to see if it's free and if so coalesce; add free block to free-list, done. Yes, it's not zero work like a GC implementation sort-of is, but "arbitrarily slow"? It's basically at least as fast as malloc().

    Allocation requests can hit disk, sure, but so can GC allocations even if they're just bumping a pointer: it all depends on the working set size. GC compaction can reduce fragmentation to reduce working set size, but that is only a big win if there's a lot of fragmentation, and most apps using a good malloc() don't exhibit that much. (It is also possible for a GC to rearrange memory so more in-working-set data is on pages together, reducing the working set page count without changing the total memory used. I don't know of any in-use implementations of this, since you need hardware support to know what objects are more-in-use; generally this is only available at the page level, where it's no help. I think maybe an early microde-based Smalltalk implementation might have done this.)

    If your malloc has to walk giant free lists to find an open block, then sure, that can be slow. That's why people use trees of free lists based on size and such to make it more O(log N), and O(1) for small allocations. (On large allocations, actually using the memory amortizes the cost.) Read about dlmalloc, for example.

    Furthermore, let's not misrepresent GC. Stop-and-collect GCs have obvious extra costs beyond the free-of-charge free (or lack of need for one). Incremental GCs that don't pause are usually slower overall and only preferred for interactive programs. For example, incremental GCs usually require "write barriers" or "read barriers" which require several extra instruction on every fetch from memory or every write of a pointer variable in memory. This can add up across the entire program. Incremental GCs also tend to be conservative, and only end up collecting things that, say, were garbage at the start of the most recent collection round, and generational collectors allow garbage to collect in later generations for some time, so they don't actually necessarily have a smaller working set than a non-leaky malloc()/free() program.

    Another big win in non-GC systems is that you can use pointers that don't come off the heap. That way you can avoid allocation and deallocation and GC entirely. (You can actually do some of this in a GC system too if it's a 'conservative' GC that copes with pointers into the middle of blocks. Those pretty much only get used for adding GC to C and C++, though.) Here are some common ways this happens:

    • statically allocated arrays
    • small arrays and strcts on the stack
    • structs that are components of other structs, or arrays at the end of structs
    • use of special allocators:
      • slab allocators (it's even possible to embed this entirely inside the default allocator for all small allocations)
      • pool allocators (allocate a large block of memory, suballocate from it, deallocate all at once)
      • "stack" allocators (allocate a large block of memory, suballocate from one end, only allow freeing from the same end, so allocation is a adding to a pointer and deallocation is reseting that pointer)

    Of course, doing all these things requires that you balance your different types of malloc()s with the correct, matching type of free(). In practice, GC proponents overestimate the diffi