The Artima Developer Community
Sponsored Link

Weblogs Forum
Security and the 'Final' Dilemma

23 replies on 2 pages. Most recent reply: Jan 16, 2008 11:05 AM by Vesa Karvonen

Welcome Guest
  Sign In

Go back to the topic listing  Back to Topic List Click to reply to this topic  Reply to this Topic Click to search messages in this forum  Search Forum Click for a threaded view of the topic  Threaded View   
Previous Topic   Next Topic
Flat View: This topic has 23 replies on 2 pages [ 1 2 | » ]
Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Security and the 'Final' Dilemma (View in Weblogs)
Posted: May 21, 2006 5:47 AM
Reply to this message Reply
Summary
Many people imply that 'final' in Java aids security. I don't think I buy that.
Advertisement

If you know me, you know my perspective on testing. I like to have unit tests for code and I try to write them whenever I can. At times, though, it becomes pretty obvious to me that library designers don't share that interest because they seem to do everything that they can to make testing impossible. Their most common approach is to make classes and methods final or sealed.

Why would this be a problem? Well it's not a problem for the classes that use final, but try to unit test a class which uses one of those classes and you'll see what the trouble is. If the test for your class needs to mock out the use of that final class, your back is against the wall. All you can really do is wrap the final class in some non-final adapter. And, if you do that, well, how's security going? If you use your wrapper pervasively it's the vulnerable point now.

No, there's a measure of security when you use final but only if you imagine that your users aren't really writing unit tests for their code.

Isn't it ironic that we may be able to have secure software, but only if we can't be sure that it actually works?

I have more thoughts on this topic here.


Vesa Karvonen

Posts: 116
Nickname: vkarvone
Registered: Jun, 2004

The problem is with nominal typing not final Posted: May 21, 2006 12:41 PM
Reply to this message Reply
I think that this is a problem with nominal typing - not final. The problem is that if you are given just a final class (and nothing else) then you can't easily parameterize the client, because you need an interface for that. (This is in the context of Java.)

With structural typing the problem doesn't exist. Type abstraction doesn't prevent parameterization of clients with test stubs.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Security and the 'Final' Dilemma Posted: May 21, 2006 7:01 PM
Reply to this message Reply
I think the case for final and private are similar:

1. They stop mistakes, e.g. accessing/overriding something you shouldn't

2. They help software security

3. They help the compiler to optimize the software

Taking each point in turn:

1. Everyone makes mistakes, therefore it is useful to prevent them. However this could be a warning rather than an error.

2. This is probably reason enough for these features alone; I cannot think of an alternative

3. Poor idea to build in features for optimization; not a good enough reason

This leaves 1 and 2, is it possible to have final and private be warnings and introduce strictly final and strictly private for the security use?

With regard to testing, which was the thrust of the original post, I have found that it is unproductive to attempt to test third party stuff; I rely on the supplers testing.

For my own code I find that you can add in testing hooks for both final and private. For final I introduce a public interface that I program to and which I can subclass. For private I use package inner classes to give access for testing.

As an aside: I find final is overused in Java. In particular, final for arguments/fields/variables does not seem that close a concept to final for classes/methods.

Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Re: Security and the 'Final' Dilemma Posted: May 22, 2006 12:46 AM
Reply to this message Reply
> With regard to testing, which was the thrust of the
> original post, I have found that it is unproductive to
> attempt to test third party stuff; I rely on the supplers
> testing.

It can be very handy to write tests for 3rd party code. Whenever you get a new version, you can find out definitively, what has changed. That narrows the scope of debugging significantly, and it can be a lifesaver on large projects with large dependencies on external vendors.

But, that's not the problem. The problem isn't testing someone else's API. Final doesn't interfere with that. The problem is testing your own code when it uses someone else's API. If, for instance, there is some vendor class that talks to a third party tool and you have to use it pervasively and it's final: you're in trouble. You can't write unit tests for any class that uses it without really running that tool. Your only choice is to wrap the API. And, as I pointed out above, if you wrap it the security argument doesn't hold water.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Security and the 'Final' Dilemma Posted: May 22, 2006 1:22 AM
Reply to this message Reply
I have written test code that tests my software and my software uses third party libraries, e.g.:

https://pec.dev.java.net/nonav/frontpage.html

which uses the Jassist API and also runs a Java compiler programatically, both third party to me. The project referenced is a modified Java compiler that enforces patterns: Singleton etc.

I was able to test my code using a black box testing approach: I wrote test source code, ran my compiler from my test suite (which called both third party products), and compared the actual results with the expected results. I didn't have a great deal of difficulty with either final or private; because I adopted a black box approach and I run the whole of the third party stuff. I didn't attempt to test, emulate, or log calls to the third party stuff.

Maybe the problems you are seeing are specific to your application.

James Watson

Posts: 2024
Nickname: watson
Registered: Sep, 2005

Re: Security and the 'Final' Dilemma Posted: May 22, 2006 10:19 AM
Reply to this message Reply
>> Many people imply that 'final' in Java aids security. I
>> don't think I buy that.

I don't really buy it either. If you don't control the environment the code is running in, you don't control the
security. If someone has access to the environment, there's innumerable ways they can violate your application. Making classes final provides only a false sense of security.

However, I think you need to be more specific because making variables final whenever appropriate is a very good practice and if the language designers had really been thinking, they would have made method parameters final by default.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Security and the 'Final' Dilemma Posted: May 22, 2006 8:42 PM
Reply to this message Reply
The general mechanism that final protects against is substituting one class for another in a manor that the bytecode verifier cannot detect.

EG if you use a security manager and ask for permissions using a String then it is necessary to ensure that the security manager really got a String, otherwise the class derived from String and passed to the security manager could possibly be used as the basis of an attack to trick the security manager. Because String is final and the String loaded in the JVM is bytecode verified you know that you are getting a java.lang.String and therefore the security manager is protected.

However Sun could have had a public final class SecureString implements String { ... } and made String an interface (or purely abstract class), that way people who want to extend String can and you can still get the benifits for security. (The security manager would accept a SecureString and not a String and a String literal would be an instance of SecureString. However String was in Java before interfaces and all this advanced stuff :( .)

Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Re: Security and the 'Final' Dilemma Posted: May 23, 2006 5:03 AM
Reply to this message Reply
> I have written test code that tests my software and my
> software uses third party libraries, e.g.:
>
> https://pec.dev.java.net/nonav/frontpage.html
>
> which uses the Jassist API and also runs a Java compiler
> programatically, both third party to me. The project
> referenced is a modified Java compiler that enforces
> patterns: Singleton etc.
>
> I was able to test my code using a black box testing
> approach: I wrote test source code, ran my compiler from
> my test suite (which called both third party products),
> and compared the actual results with the expected results.
> I didn't have a great deal of difficulty with either
> final or private; because I
> adopted a black box approach and I run the whole of the
> third party stuff. I didn't attempt to test, emulate, or
> log calls to the third party stuff.
>
> Maybe the problems you are seeing are specific to your
> application.

I visit a lot of teams. Many of them aren't lucky enough to have third party components that they can run in their tests. Sometimes the runs just take too long; at other times, there is no programmatic interface to get back the results of some call for testing, so the mocking really becomes necessary. And if the API designer made the calls final..

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Security and the 'Final' Dilemma Posted: May 23, 2006 8:28 PM
Reply to this message Reply
> I visit a lot of teams. Many of them aren't lucky enough
> to have third party components that they can run in their
> tests. Sometimes the runs just take too long; at other
> times, there is no programmatic interface to get back the
> results of some call for testing, so the mocking really
> becomes necessary. And if the API designer made the calls
> final..

This is advanced stuff: but for these two issues you raise, takes too long and can't get results, I would:

1. Use a toolkit like Javassist or AOP to modify the final class :) . OK so long as you aren't using a security manager. I use Javassist to modify the class before it is loaded and then load the modified class from Javassist. For example replacing or modifying a method.

2. To pick up the results I often run a seperate process and intercept the output: std. out, std. err, files, etc. I do this for the standard Java compiler for example in the PEC project referenced above.

Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Re: Security and the 'Final' Dilemma Posted: May 24, 2006 1:34 AM
Reply to this message Reply
> > I visit a lot of teams. Many of them aren't lucky
> enough
> > to have third party components that they can run in
> their
> > tests. Sometimes the runs just take too long; at other
> > times, there is no programmatic interface to get back
> the
> > results of some call for testing, so the mocking really
> > becomes necessary. And if the API designer made the
> calls
> > final..
>
> This is advanced stuff: but for these two issues you
> raise, takes too long and can't get results, I would:
>
> 1. Use a toolkit like Javassist or AOP to modify the final
> class :) . OK so long as you aren't using a security
> manager. I use Javassist to modify the class before it is
> loaded and then load the modified class from Javassist.
> For example replacing or modifying a method.

There's the rub. Doing something as ostensibly normal as unit testing your code should not require "advanced stuff." "Advanced Stuff" means the model is broken.

> 2. To pick up the results I often run a seperate process
> and intercept the output: std. out, std. err, files, etc.
> I do this for the standard Java compiler for example in
> the PEC project referenced above.

If you're lucky enough to even have those as outputs.

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Security and the 'Final' Dilemma Posted: May 24, 2006 2:05 AM
Reply to this message Reply
> There's the rub. Doing something as ostensibly normal as
> unit testing your code should not require "advanced
> stuff." "Advanced Stuff" means the model is broken.

But designing an API that is secure and easy to use is also normal stuff, as well as unit testing. You need to look at the whole picture and asses which is the most important. For final the whole picture, starting with the for case, is:

F1. Ease of use; you can't accidently override something you shouldn't (if you do the compiler catches the error)

F2. Security; final and a bytecode verifier stop Trojan Horse type attacks

Against:

A1. You can't mock a class for testing purposes easily (advanced stuff necessary)

There are two options:

1. Come up with something that satisfies F1, F2, & A1

2. Make a call about the relative importance of F1 & F2 vs. A1

I guess Sun went with option 2 and decided F1 & F2 were more important than A1.

Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Re: Security and the 'Final' Dilemma Posted: May 24, 2006 5:43 AM
Reply to this message Reply
> But designing an API that is secure and easy to use is
> also normal stuff, as well as unit testing. You need to
> look at the whole picture and assess which is the most
> important. For final the whole picture,
> starting with the for case, is:
>
> F1. Ease of use; you can't accidently override something
> you shouldn't (if you do the compiler catches the error)
>
> F2. Security; final and a bytecode verifier
> stop Trojan Horse type attacks
>
> Against:
>
> A1. You can't mock a class for testing purposes easily
> (advanced stuff necessary)

If unit testing is advanced stuff, our industry is far less mature than we may have imagined.

>
> There are two options:
>
> 1. Come up with something that satisfies F1, F2, & A1
>
> 2. Make a call about the relative importance of F1 & F2
> vs. A1
>
> I guess Sun went with option 2 and decided F1 & F2 were
> more important than A1.

I don't think they were even thinking about A1. And, as I pointed out in my blog entry, I think the security is an illusion.

In general, people who test will wrap the API and if they do, security is subverted. And people who don't test will have "secure" code that is buggy and far less maintainable than it could be. There have to be better options than "final."

Isaac Gouy

Posts: 527
Nickname: igouy
Registered: Jul, 2003

JMockit Posted: May 27, 2006 1:27 PM
Reply to this message Reply
JMockit has been mentioned on your object mentor blog, so let's mention it here as well.

https://jmockit.dev.java.net/

"JMockit consists of a single class with a small set of static methods, which allow arbitrary methods and constructors of any other class to be replaced by mock implementations at runtime. ... JMockit depends on the JVM class redefinition mechanism exposed by java.lang.instrumentation"

Howard Lovatt

Posts: 321
Nickname: hlovatt
Registered: Mar, 2003

Re: Security and the 'Final' Dilemma Posted: May 29, 2006 11:05 PM
Reply to this message Reply
A couple of people in this forum have said that security isn't helped by final classes. Below is an example of when final helps:
package trojanattack;
 
import java.util.*;
import static java.lang.System.*;
 
/* Check method would in practice grant something useful, like write permission.
 * But in the example it simply return true or false. */
class Security {
    /* The argument type is a mistake. Should have used String because String is
     * final and therefore can't be a trojan if run with a security manager. */
    static boolean check( final CharSequence pwd ) {
        return (pwd != null) && (pwd.length() == 3) &&
                (pwd.charAt( 0 ) == 'A') && (pwd.charAt( 1 ) == 'B') &&
                (pwd.charAt( 2 ) == 'C');
    }
}
 
/* Logs what the security check does, thus aiding cracking the password.
 * Reduces search from approx. O(27^n) to O(27 * n)! 27 because 26 letters
 * plus empty (password not that long). */
class Trojan implements CharSequence {
    final List< Character > pwd = new ArrayList< Character >();
    int charAtLog = 0;
    public CharSequence subSequence( final int notUsed, final int notUsed2 ) {
        throw new AssertionError();
    }
    public int length() { return pwd.size(); }
    public char charAt( final int index ) {
        charAtLog++;
        return pwd.get( index );
    }
}
 
public class Attack {
    static final char[] all = { 'A', 'B', 'C', 'D', 'E' }; // etc.
    public static void main( final String[] notUsed ) {
        final Trojan t = new Trojan();
        attack: {
            while ( t.charAtLog == 0 ) { // find pwd len
                t.pwd.add( '*' ); // lengthen pwd; any impossible char, it is over written!
                Security.check( t ); // spy on the security
            }
            for ( int index = 0; ; index++ ) { // find pwd
                for ( final char c : all ) {
                    t.pwd.set( index, c );
                    t.charAtLog = 0;
                    if ( Security.check( t ) ) { break attack; } // found pwd
                    if ( t.charAtLog == (index + 2) ) { break; } // found a character in pwd
                }
            }
        }
        out.println( "Cracked :), pwd = " + t.pwd );
    }
}

Michael Feathers

Posts: 448
Nickname: mfeathers
Registered: Jul, 2003

Re: Security and the 'Final' Dilemma Posted: May 30, 2006 12:05 AM
Reply to this message Reply
> A couple of people in this forum have said that security
> isn't helped by final classes. Below is an
> example of when final helps:

I hear you, but I'm not talking about String in particular. I'm talking about the fact that if your application has to use an arbitrary final class, and you have to wrap it to mock it for testing (which, btw, many people do) all you've done is introduce a new point of attack.

I've never had to mock String, I don't think I'll ever have to, but that doesn't detract from my opinion that final just may not be the best tool for the job. People use it because it is there, and in the process get in the way of testing.

I've been playing with JMockit (mentioned above) a bit, and it is nice, but still that does not convince me that people should use final whenever possible.

Flat View: This topic has 23 replies on 2 pages [ 1  2 | » ]
Topic: Security and the 'Final' Dilemma Previous Topic   Next Topic Topic: An Alternative to Closure Conversion and to Restricted Closures


Sponsored Links



Google
  Web Artima.com   

Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us