Friday, November 23, 2012

Know Your Tools!

There are several mantras when it comes to developing secure software. The most important and therefore the number one is: "Never ever trust the users input!" The second one would be: "Use as much privileges as necessary and as little as possible!" aka "Least Privileges". There are many more, but usually these two rules can be seen as "Catch-All" rules. As soon as you start to design, implement and test according to these rules, all the other rules seem to be commons sense. You don't start to argue why you should use prepared statements -> Rule 1! Always check buffer sizes? -> Rule 1! Use different users during installation and production? -> Rule 2!

Still, during my secure development classes I add one more: "Know your tools!" With tools I do not mean your favorite IDE or a text editor, but the programming language and frameworks in use.

While modern IDEs and frameworks suggest how easy programming nowadays is this easiness lulls the developer into a false sense of knowledge and security. This starts by not knowing which output methods are XSS safe (and why) and doesn’t stop at the ignorance against LINQ-Injections. This is security by luck. Sure, frameworks are complex and as a real hard-core programmer you write your own frameworks which you know by heart. This leads to the equally important question: “How good do you know the programming language you wrote your framework in?” Without excellent knowledge of the programming language you are bound to make mistakes because of assumptions. Assumptions you don’t even know you make.

Assumptions


Can you predict the result of the following statement?

Integer var1 = 0;
Integer var2 = 0;
System.out.println(“var1 == var2?+ (var1 == var2));
System.out.println(“var1.equals(var2)?+ (var1.equals(var2)));

Easy, isn’t it? Both times we get a “true” as result.

But what happens if we replace 0 with 128?

Integer var1 = 128;
Integer var2 = 128;
System.out.println(“var1 == var2?+ (var1 == var2));
System.out.println(“var1.equals(var2)?+ (var1.equals(var2)));

Now the world looks different. While the “equals” method still returns “true”, the “==” now returns “false”. Can you imagine how long it will take to find a bug which only occurs if a certain value is higher than 127?

While we are on it:

Integer var1 = 128;
long var2 = 128L;
System.out.println("var1 == var2? " + (var1 == var2));
System.out.println("var1.equals(var2)? " + (var1.equals(var2)));

This time “==” returns “true” while “.equals” returns “false”

There is always a reason why Java behaves like this. It might not always be a good one and some reasons are obsolete now, but these features are still there. It’s not only Java, other languages have features like this too.
With the introduction of reflection in modern languages it gets even weirder. In my whitepaper “The Source Is A Lie” I point out how to manipulate seemingly constant strings. This technique isn't only working for strings, it can be applied to almost any type which is auto-boxed. Can you imagine what happens if you change the value of the constant “Boolean.TRUE” to “false”?

The point is…


As captain obvious would say: “We are living in a fast paced world” For IT this world is blazingly fast. There is a new programming language popping up almost every month. Keeping up with the hype is required if you want to stay on top of the hiring pool (or learn ancient languages like Fortran and Cobol).  Yet, to write secure and bug free code one has to learn and understand the programming language and its environment. This isn't done within one month, or one year. Like everywhere and especially in security, you have to make some compromise and set your priorities to fit your needs.

No comments:

Post a Comment