Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
642 views
in Technique[技术] by (71.8m points)

security - Can a secret be hidden in a 'safe' java class offering access credentials?

This is a brainstorming question about what's possible in Java (or not). I want to know if it is possible to hide a secret within a class and prevent anymore from accessing it using Java code or any of its feature only (security, reflexion, serialization, class loaders, you-name-it...).

Here is what I have in mind so far:

public final class Safe {

    private String secret;
    private HashMap<String, Credentials> validCertificates
            = new HashMap<String, Credentials>();

    public Safe(String aSecret) {
        this.secret = aSecret;
    }

    public final class Credentials {
        private String user;
        private Credentials(String user) {
            this.user = user;
        }
    }

    public final Credentials getCredential(String user) {
        // Following test is just for illustrating the intention...
        if ( "accepted".equals(user) ) {
            return new Credentials(user);
        } else {
            return null;
        }
    }

    public String gimmeTheSecret(Credentials cred) {
        if ( this.validCertificates.get(cred.user) == cred ) {
            return secret;
        } else {
            return null;
        }
    }

    private void writeObject(ObjectOutputStream stream) throws IOException {
        throw new RuntimeException("No no no no no no no!!!");
    }

}

Can it be improved? Should it be improved? Is the idea of locking a secret in a safe class impossible to achieve?

EDIT

Relevance:

Some people question the relevance of the issue I am raising here. Although I am asking a general question in order to trigger an open conversation, there is a very concrete application to this class:

  • If I want to decrypt some messages, I need to load a private key data into a class. If I can't prevent other Java code from accessing it, then it is impossible to create a secure system. Of course, if I want to decrypt a message, I should rather do it in the class than giving away the secret, but still, the safe has to remain unbreakable.

Clarification:

  • Instances of the class are only created at runtime, not at compile time
  • Code can run in web server applications or any desktop or device applications
  • The class is only used to store a secret at runtime, in memory, no plans to persist it (for persistence, one can/should use classic encryption techniques)

Facts:

  • To implement security in a Java application, one should set a SecurityManager instance where checking methods are overridden as needed
  • This application can load untrusted code with secure class loaders and assign a protection domain for the classes it loads. This domain should not include a RuntimePermission("setSecurityManager").
  • Untrusted code can try to change the SecurityManager, but since the Secure Class Loader did not grant the setSecurityManager permission, a SecurityException will be thrown.

Solved issues:

Regarding the execution environment, we need to distinguish two cases:

  • Controlled environment: We get to start the application that will use untrusted code trying to break our 'safe'.

If we set a proper SecurityManager disabling reflection and restricting permissions on any loaded untrusted code, then our secret is safe.

  • Uncontrolled environment: Hacker gets to start the application which uses untrusted code trying to break our 'safe'.

The hacker can create his own application with its own security manager and Secure Class loader. It could load our code from the classpath and execute it as if it were our own application. In this case, he could break the safe.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

This "security" is laughable.

Where does it run? On my desktop? I connect to the JVM with debugger and view all the secrets in clear text.

Or I place my code next to it and use reflection to dump the content.

Or I inject my own code modification via BCEL, and modify the constructor of Safe to dump the "secret" value to a file.

Or I simply replace the whole package with mine with the same name by placing it into bootstrap classloader.

Or I can even modify and compile java sources to get a modified JVM.

Or... my, one can list dozens of ways to extract a value from a runtime instance!

The real question in any security design is: who is a attacker? What is the threat model? Without answering this the topic is pointless.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...