Java or C: Is One More Secure?
bluefoxlucid writes "Security has been a hot topic lately, and we've seen everything from changes to how memory is managed to compiler hardening to "secure" programming languages. Java is considered more secure than C in general; but this guy seems to disagree, and thinks hardening the system itself is the way to go. Are we really approaching the problem the wrong way, or is he just insane?"
Apparently there will be a port of IBMs stack protector in GCC 4.1. Might be interesting to see how that changes matters.
AFAIK, Java is considered a "strongly typed" language, so even if there is a gets(), it has an implied length.
By design C allows you to access memory at your own descretion. I beleive Java does also (It's been a while), which means neither is a 'secure' programing language. This would be like asking if Fords or Chevys are safer because one uses tig welding and the other uses mig welding. It completely matters on how the code is used. You can write your own memory editor in C (and I beleive Java). Which would make them fundamentally unsecure. C has the advantage that you have to write your own code, so you can make sure it is bug and security flaw free (cha right, and monkeys might fly from my ass!) where as Java comes with libraries. No need to recreate the string. Which saves you tons of dev time, but now you depend on someone else's code review. With that in mind, I'd say Java has a slight edge, just because more people are testing the Java libraries then your custom made objects.
-Rick
"Most people in the U.S. wouldn't know they live in a tyrannical state if it walked up and grabbed their junk." - MyFirs
The author points out there's some tools and run-time environment features you could use to help secure C/C++ binaries. Nothing new there. Then based on some FUD and hand-waving arguments he predicts that with all these extra bits that C can be made more secure than standard Java.
The thing is though, C is still insecure as standard, while Java is still secure by design (and has shown to be in practice). Not that there's an idiot proof general purpose programing language/environment out there - being "secure by design" doesn't make something 100% secure.
TFA talks about C being just as secure with protection bits, claiming that use of stack-protection stuff is going to increase programmer and company awareness and willingness to fix bugs. They can fix the bugs, it's going to make it easier, but the inverse is what will happen. Instead of better software coming out, less time is spent on fixing that kind of bugs "since the protector will catch it anyway". Why bother fixing something that doesn't crash the program?
On the other hand, if you convert all these soft errors to hard errors (instead of a program doing something softly off-balance to a rigorous crash) they'll be fixed faster. Yet still, just teach the programmers to program.
Oh, and please do give all books about programming you have left to EA. They appear to be hiring kids between 12 and 16 since they're cheaper, judging by the quality of their software. I can't even run NFS3 in opengl mode since my video card isn't supported... no, the pre-pre-pre-pre-pre-predecessor was.
The major source of security bugs in C and C++ is lazy programmers.
Our company has an in-house rule - "if it returns an error status, you check it". Why? Because most really nasty bugs arise from failure to check this. If you're lucky, this will just result in unexpected crashes. If you're unlucky, you get buffer overruns and remote code execution.
Why do programmers not check this? I'm convinced it comes down to how you're taught. I went through a good dozen C and C++ tutorials when I was learning them. I've been through a few more since, teaching other people. And I've *never* seen a textbook that includes a check on the results of a malloc() call being NULL. Yes I know the argument is "it'll make the examples harder to read". That's a fair point, in a hello-world program. But by the time you get to using malloc(), you should know enough to handle a little complexity. The books just don't cover it though. Not only do they simplify the examples, but they don't mention that they're simplifying. As a result, it's an issue that too many coders don't realise exists.
If coders get some good mentors at work, to show them how this *should* be done, then fine. But I don't think that happens either - code review is not a way of life for most companies. So they just go their merry way until their code falls over in a heap, and then wonder what to do about it.
Python is generally quicker to write than Java, and Java is generally quicker to write than C++, and C++ is generally quicker to write than C, simply because each step along the line does most of that work for you. But that generally comes at the cost of increased overhead (code size, execution time or both). And even then it's worth knowing what's happening underneath, because if you don't then it *will* bite you sometime. Neither of these is more secure than the other though, assuming the coder knows what they're doing.
Grab.
Yes, fancy tricks as PaX and ProPolice can turn remote root attacks into 'only' a denial of service (your daemon gets killed). That's definitely an improvement.
I'm no fan of Java, but at least it gives your program a chance to recover (exceptions and stuff).
Isn't the best way to go to program in a language one is experienced in?
People who can't spell words in the English language like "aggravate" might not be the best people to look for deep and insightful attacks on what everybody else agrees on. I'm not saying that having good spelling would make his point any more valid, but it should at least be a rule of thumb for those who can't bother to think about his point on their own (as the poster of this article can't).
To get more into it, yes, the C runtime is smaller than the Java runtime, and there is a certain trustworthiness in having your code small. However, languages like C where the basic type system requires a lot of care to avoid bugs starts you off considerably behind just having a large runtime. In C, it requires almost no thought at all to write insecure code, and to do some things securely requires chunks of wrapper code around most things involving IO layers, wrapper code that is not program logic and can have bugs. In higher-level languages, the user won't be writing that code -- the engineers at Sun will, and because that code gets exercised by the entire world, its bugs will be found and removed very quickly.
Of course, in both cases, we're not really talking about the language being secure, we're talking about how likely it is that, given equivalent tasks, people using the different languages will end up writing secure code. To weigh that, we all use rules of thumb based on what we know causes errors -- he invokes bulk of code, but doesn't think about how the used code in that bulk will need to be written anyway and will be reused by every Java programmer. As I said before, I think a caveat-emptor type system is another major factor to be considered. Other (generally obvious) rules of thumb that go against this guy are left as an exercise for the reader.
For every problem, there is at least one solution that is simple, neat, and wrong.
This is a run-time check, not something that is checked statically by the type system. Though helpful, this behavior does not rely on Java being strongly typed.
What about the fact that a java file can be de-compiled? There is software available that will let you decolpile/reverse engineer a java file back to the cource code! It's the ultimeate in open source, because it carries the source with it!
v a
See the google...
http://www.google.com/search?hl=en&q=decompile+ja
Using the Freedom of Speech while I still have it.
The reason he claims that the bugs are more likely to get
fixed is because in the hardened environment, these bugs
result in crashes rather than transient misbehavior. These
types of bugs will be much easier to detect and fix since
they will no longer be hard to reproduce.
Sounds reasonable to me. In my experience, no bug is hard
to find and fix if it is easy to reproduce.
*sigh* back to work...
This more pertains to yesterday's article on performance, but it relates to Java in general.
I see lots of articles saying how garbage collection prevents memory leaks and provides security improvements. That is a slight misunderstanding: The automatic memory management is what makes it secure, not the garbage collection. The garbage collector is merely HOW the memory is freed. If Java eliminated the garbage collector and freed the memory immediately the language would be equally secure. What matters is that you don't have access to pointers.
For example, take Visual Basic 6: This language does not have garbage collection, but it is about as safe as Java. It frees memory/objects that aren't used, uses bounds checking, doesn't allow bad casts, and doesn't use pointers. The only time VB6 is a problem is when you call an outside library (which is the same problem you have in Java). So it isn't the garbage collector that matters.
Inherently, a language with access to pointers is always going to be less secure than a language that does not have them, and uses automatic memory management. None of the security enhancements to the compiler can change code that assigns a pointer to the wrong object and overwrites the memory for it. None of them can prevent a bad cast from screwing things up.
Stack protection really is the next big step and like ports from WIndows typically the difficulties is broken code that is just allowed. Stack protection is going to cost developers dearly and it is likely that it will be disabled if there is an option rather than paying the cost on the very software that needs it the most.
I have used valgrind on production code that has been working 8 years. I found multiple protections, uninitialised variables in this code. Anyone coding C and not using valgrind in the testing cycle is not using their head.
I switched to Perl because there were no memory allocation problems like this.
Lots of FUD and hand-waving here as the author compares the JVM to a C application, and implies that (1) the C runtime is bug-free and/or any C application can avoid C runtime bugs; and (2) all programmers can make their C programs more bug-free than a JVM.
A better comparison would be the C compiler, runtime and automated protection extensions versus the JVM, as those are the components of C and Java respectively that define the boundaries of what code written in the language can accomplish. Note in particular that a buggy C compiler can generate exploitable code, whereas a Java compiler cannot (because the JVM restricts what the code can do).
It must also be said that ultimately the JVM is a C program, so the system can protect itself just as much from a JVM as from any other C program.
i-name =twylite [http://public.xdi.org/=twylite], see idcommons.net
You can't prevent bad/malicious programming of course but you can prevent the vast majority of bugs that are typically exploited by hackers, like buffer overflows or dangling pointers. Java is immune to both these issues. Therefore, Java is a much more secure environment to program in and therefore the use of C/C++ is nearly non existent in the web application domain.
:-). Besides, fixing performance issues in Java is not that hard, if you know what you are doing. But then if you didn't, you shouldn't be trusted with C either.
Infrastructure is a different matter. That too will become the domain of java like languages in the future but for the moment we will need to continue to patch the endless stream of buffer overflow issues in such fine products as apache, iis, bind, openssh, etc. These packages have two things in common: 1) they are written in c/c++ and 2) despite years of security audits and bug fixing, new security issues directly related to C's inherent insecureness continue to be found in them on a regular basis.
True, Java depends on native stuff. In fact most known java exploits are indirectly exploits of bugs in this native stuff. The rest consists of genuine design flaws in the program at hand. However, exploiting bugs in native code from Java is actually quite hard since it involves making a lot of assumptions to the run-time memory usage and garbage collecting. Consequently, there have been relatively few incidents of Java bugs being actually exploited.
In short, if security is important to you, don't even think about using C. Even if you (the programmer) do your work properly, there is no guarantee the developer of the libraries you depend on did. There will no doubt be some in this thread to point out that if performance is important, you should choose C. IMHO these people overrate performance and underrate other important quality attributes like maintainability, security, flexibility, reusability. But who am I to judge these folks
Jilles
This article deals with 3 compilers or systems for C++, NOT C++ in general. sorry, gcc is a C++ compiler, not c++ itself. If I use another compiler those issues will return. And many people do use other systems...
.net isn't worth the pain, though we have the option. Though 6 or .net I don't believe use any "auto" update feature, just makes them very hard to keep "current") People will always use outdated compilers because they are faster to use that way, and as such we'll always have issues.
C++ CAN be made more secure of course but it's the programmer's job not the compiler's job to keep it secure. You want to compare security? You need to start with the core C++ stuff and the core java stuff, the stuff that is in every version of it. This of course gives Java the advantage because sun makes it very standard (and has to be) and c++ has many versions (we all know Microsoft's attempt to take C++ in their direction). Then You take GCC, and the Java Compiler head to head, if you have stuff before gcc 4.1 you're weaker on gcc, but it appears his point is that with 4.1 they have made gcc stronger. Then take notable IDEs for both and compare them (Visual Studio vs Eclipse would be the two I use) and see what they do extra, if your using visual studio, Java will likely run the ball on that play. But fact that c++ by itself is less secure than java. The extras that one compiler adds doesn't matter if not every system uses that compiler. Java at least keeps very strict guidelines on their compilers so it does make it a bit more standardized.
Now with a good programmer/compiler C++ is as secure if not more so than java, but the fact is the language has an inherent security issue. In that issue alone it means that a good programmer is going to take time to fix C++ issues rather than relying on inherent java stuff. That doesn't mean it's not good in other ways, but for security you need to rely on the programmer a bit more than java.
Of course this all being said a good programmer can make C++ more secure, and use some of these things that can create the security problems in other ways to write better, faster, or more interesting code. But as always it's a matter of choice the problem with the article is he's pointing out only 3 different versions of c++ that have had upgrades, but in corporate life many people have people use Microsoft Visual studio (hell we use 6, because
So in the long run, C++ can try to catch up but because of the unstandardized nature of C++, and the fact that Java has had the security from the begining we'll always have a difference.
First, I am happy to see these stackguard-like systems be integrated into C compilers and runtimes. I think they can go a long way towards solving common security problems, and I am dumbfounded that distributions aren't clamoring to have these installed by default. The only explanation I can think of is this bizarre obsession with performance in the Linux world, as if a few percentage points of performance are worth living in constant fear of being hacked. However, it's not really fair to say that C "has" these security features, since hardly any of the C programs that are out there are running with them enabled. (On the other hand, basically every Java program runs with array bounds checks!) The day that my linux system comes pre-installed with OpenSSH running with heap and stack protection, I will happily change my tune. Unfortunately I think that day is sadly a lot further off then the author seems to suggest.
.NET. SML compilers simply compile in the runtime checks as regular old machine instructions, and this code is so simple that it's pretty unlikely that they would get it wrong. (About as likely as a particular aspect of your C compiler having a bug, basically.)
I expected to be really angered by this article, but I actually thought it was pretty reasonable. Basically his argument comes down to this: given two systems with indistinguishable security features, the one with the smaller trusted computing base is more trustworthy. I totally agree, and it's clear that the Java+javac+JVM+OS TCB is larger than C+GCC+CRT+Proguard+PaX+OS. What I don't agree with is that these languages provide equivalent security features. For one thing, unless I am mistaken, C running with these protections does not provide array bounds checking, unless the out-of-bounds writes happen to hit certain places identified as dangerous. Although this unarguably closes a lot of common attack vectors, it is not the same kind of automatic and absolute protection that a safe language whose semantics includes array bounds checking offers. Any time an attacker can compromise your data structures in an unexpected way, he is going to have more access than you intended. Language-based memory protection is a security feature that C does not offer, even extended with these systems.
The point I really want to make, though, is that the author presents a false dichotomy: Choose either the lean dangerous language C with some OS-style protections, or choose the bloated safe language Java with a lot of stuff you have to trust. Fortunately, there is a middle ground that I think provides better security than both; any of the compiled safe languages. A great example is Standard ML; its performance is somewhere between C and C++, it compiles to native code (plus a modest runtime, implementing for instance garbage collection; surely smaller than PaX and Proguard), and has none of the "undefined behavior" that causes security problems in C. Since it's also a higher-level language, programmers get the benefit of writing shorter and more concise code, which gives them more time to both look for high-level security problems that can never be caught by a program, and to optimize the algorithms in their code for better performance. (For a data point: my FTP server written in SML is 2200 lines; wu_ftpd is just under 20,000!) There is no reason why safe languages need a "platform" like the JVM or Mono or
So, it's great to make C more secure by adding features to its runtime. I really hope this happens soon so that I don't need to patch my linux box so often. But the Java methodology is not the only alternative. Lightweight compiled languages with built in language security mechanisms do better than both.
I can't reply on the blog so I'll reply here:
/exception/ to the rule. Besides Eclipse and Azureus, I don't know of ANY other Java desktop applications that use SWT. Those other 99% are most likely using Swing. That is not to mention the server side, in which it is even more ridiculous to suggest a reliance on native code. The Java middleware market is huge and there are some really large, complex applications, none of which rely on native code (sure, some of them /offer/ some extra integration, but you will be laughed out of your marketing pitch if you tell us your Java software has native dependencies).
I'd have to agree that the notion that doing "useful" things in Java requires that "a vast amount of a complex java application's base code is glue to external C and C++ libraries" is ridiculous. Eclipse is the
It's 10 PM. Do you know if you're un-American?
I had a problem with Azureus crashing the OS, it wasn't the Jave it was some brain damaged swt OpenGL JNI code in a plugin, because the idiots insisted on unsafe swt code instead of safe fast well tested Java 3D code, which uses the faster Direct 3D API on windows! So I will never allow that POS swt code and plugin on my PC again!
the exploits in `c`
"C" (capitalized, and not surrounded by quotes).
With Java, some of the most complicated and historically bug-ridden code is encapsulated in the JVM and re-used by every single program, rather than spread throughout the code, doomed to be reimplemented by every software intern. It's about isolating the parts that people historically are bad at programming, auditing them, and heavily re-using the highly audited implementations.
If you don't trust your virtual machine and/or runtime, then the solution is to use a FOSS (or at least source-available) VM/runtime and audit the security critical portions yourself. On the other hand, very few people would fault you for using the JVM and Java runtime from the EAL-4 version of Solaris (if it contains a JVM and Java runtime... I'm not sure on that part) and just assuming that a Department of Defense EAL-4 audit is more rigorous that the audit you would perform yourself.
C and C++ use manual array bounds checking. Every line of code that uses arrays or pointers must be audited in order to assure reads and writes are in bounds. Once you've audited the (very few) lines of code in the bytecode interpreter and the JIT responsible for inserting bounds checks, you can be sure that out-of-bounds reads and writes will fail in all of your Java code.
C and C++ are weakly statically typed languages. In other words, you can completely bend the type systems by upcasting to (void *) and then perform uchecked downcasts. After you've audited the class loader, you can be sure your Java code is free from such manglings of the type system. The same sort of assurances in C/C++ require auditing all of your code. The author of TFA says that Java loses the strict data-code seperation of PAX. However, the JVMs strict enforcement of type safey already creates strict data-code seperation.
C and C++ use manual allocation and freeing of memory. In very complicated cases, engineers may have no choice but to use third-party automatic memory managers, or implement their own reference counting or other memory management systems. Proving that code does not perform double-frees can be very complicated. On the other hand, with Java code, only an audit of the JVM's garbage collector is required. (Depending on the exact type of garbage collector used, some other code may need to be audited to ensure that some of the representational invariants of the internal object representation are not violated.)
Copyright Violation:"theft, piracy"::Anti-Trust Violation:"thermonuclear price terrorism"<-Overly dramatic language.