0

I'm trying to make a simple example of a user and bank program where you must guarantee that money cannot be cheated by someone who can add, inherit, implement current existing classes but cannot edit the initial ones. So I ask if you somehow can set someone's account's balance without the provided function for money transfer.

I've tried using reflection but you have to have public constructors to make an object on which you call the private methods but since everything is private I cant call it.

public class Bank {
    private static Bank ourInstance = new Bank();
    public static Bank getInstance() {
        return ourInstance;
    }

    private Bank() {}

    public boolean requestTransfer(User user1, User user2, double amount) {
        BankAccount ba1 = (BankAccount) user1.getBankAccount();
        BankAccount ba2 = (BankAccount) user2.getBankAccount();
        if (!(hasAccount(ba1) && hasAccount(ba2)))
            return false;

        if (ba1.getBalance() >= amount)
        {
            ba1.setBalance(ba1.getBalance() - amount);
            ba2.setBalance(ba2.getBalance() + amount);
            return true;
        }
        return false;
    }

    private class BankAccount implements BankAccountInterface {
        private double balance;
        private User user;

        private BankAccount(double balance) {
            this.balance = balance;
        }

        @Override
        public double getBalance() {
            return balance;
        }

        @Override
        public User getUser() {
            return user;
        }

        public void setUser(User user) {
            this.user = user;
        }

        private void setBalance(double balance) {
            this.balance = balance;
        }
    }
}

public interface BankAccountInterface {
    double getBalance();
    User getUser();
}

public class User {
    private String username;
    private String password;
    private Date created_at;
    private BankAccountInterface bankAccount;
    //constructor getters and setters etc..
}

If you can add your own classes inherit current ones, use reflection or anything at your disposal can you illegally give a user money.

The Cat
  • 11
  • 1
  • 6
  • you can make reflection a bit harder using a `SecurityManager`, but probably never make it impossible at all (as @curiosa just **also** answered, but deleted (and undeleted)) – user85421 Oct 23 '19 at 05:50
  • Depends on access to application, if you will block ALL reflections and unsafe code with security manager, and maybe use java modules to limit access between modules and such person does not have access to machine itself - then it should be safe. But you ale also very limited with libraries and they can't use reflections too. (otherwise it really hard to limit reflections, as some library might give access to reflections too) But with access to app itself you can always strip all security with few arguments added to start line. – GotoFinal Oct 23 '19 at 10:09
  • Bank setups always have maximum paranoia level, hard to imagine, they let you type that kind of jvm arguments anywhere. – Curiosa Globunznik Oct 27 '19 at 21:21

3 Answers3

6

That's a security question. You can use security manager settings preventing reflection, see this and this, interface changes by byte code manipulation is out of question after the class has loaded, see this. There are are other security vulnerabilities though, here's the official list, with the infamous deserialization vulnerability initially being there by design. Those are known issues without taking into consideration zero day exploits. Here's a more detailed discussion about the intricacies of security manager and certain APIs related to this exploit.

Curiosa Globunznik
  • 3,129
  • 1
  • 16
  • 24
  • It is possible to edit bytecode after class is loaded, but you need to have access to either reflections or to application starting arguments, as the provided links kinda suggest that bytecode is immutable after loading the class. – GotoFinal Oct 23 '19 at 10:13
  • Can you provide an example or reference for the claim? – Curiosa Globunznik Oct 23 '19 at 15:55
  • 1
    simplest way is to use ByteBuddyAgent library to get Instrumentation instance in runtime, and Instrumentation api allows you to change java classes at runtime as long as you don't add/remove/edit fields/method/class signature. But code inside every method can be edited. (before class is loaded everything can be edited, you can even relocate whole libraries at runtime as you can find in one of my answers). You can also see my method on jvm 8 that allows you to attach agent to yourself using only reflections on non-JDK JVM https://github.com/raphw/byte-buddy/issues/374#issuecomment-343786107 – GotoFinal Oct 23 '19 at 16:08
  • Instrumentation API https://docs.oracle.com/javase/7/docs/api/java/lang/instrument/Instrumentation.html – GotoFinal Oct 23 '19 at 16:09
2

Here is reflection code for giving a known user $1,000,000:

User user = /*assigned elsewhere*/;

// Get users bank account
Field bankAccountField = user.getClass().getDeclaredField("bankAccount");
bankAccountField.setAccessible(true); // Bypass 'private'
Object bankAccount = bankAccountField.get(user);

// Get bank account balance
Field balanceField = bankAccount.getClass().getDeclaredField("balance");
balanceField.setAccessible(true); // Bypass 'private'
double balance = (Double) balanceField.get(bankAccount);

// Add $1,000,000 to bank account
balance += 1_000_000;
balanceField.set(bankAccount, balance);
Andreas
  • 154,647
  • 11
  • 152
  • 247
0

Once you have an instance of the inner object, you can use reflection to invoke the method itself:

Method someMethod = innerObject.getClass().getDeclaredMethod("someMethod", Integer.class);
someMethod.setAccessible(true);
someMethod.invoke(innerObject, 5);

in this example you provided,you can still use reflection for getting methods in User Class.

If you can add your own classes inherit current ones, use reflection or anything at your disposal can you illegally give a user money?Yes possible if methods are implemented without access restrictions for outer class,it is about security rather about java code.

  • Indeed but the inner class is private so the instance can only exist inside the outer-class which cannot be edited because that's part of the rules. – The Cat Oct 23 '19 at 05:28
  • check this answer,it would help you understand.https://stackoverflow.com/questions/14112166/instantiate-private-inner-class-with-java-reflection – sivaramakrishnan Oct 23 '19 at 05:33