反思改进访问现场的秘密,当字段类型是未知(Reflection improvements to ac

2019-10-19 09:42发布


我正在学习有关安全和寻找存储在清澈的秘密。

当我取回一个私有字段的内容,它返回一个对象。 我的发作代码正确地假定和注塑对象作为int,但是如果我改变/解析从字段类型int secretInt = 42;String secretInt = (new Integer(42).intValue()).tostring的玛码悲惨地失败。

编辑:不寻常的包装(new Integer(42).intValue()).tostring由自动化解析器创建,它不是由一个程序员写。

如何添加鲁棒性马累的代码,以便返回类型的假设被删除。 这可能吗? 我需要使用这个值作为INT PARAM。

编辑:“字符串”是一个例子,但解析器可以选择一个数据结构适当-不适当的,因为字节[],CHAR []。

这是我的不符合规定的代码。

public final class SecretInClear implements Check4SecretsInClear {

    //Non-Compliant: Secret int stored in Clear.
    private final int secretInt = 42;

    @Override
    public boolean isSecretInt(int check) {
        return (check == secretInt);
    }
}

这是我的发作代码。

    public class ReadClearSecret implements Tester {

    //Example of running
    public static void main(String[] args) {
        String testResult = new ReadClearSecret().test(new SecretInClear());
        System.out.println(testResult);
    }

    private Object readPrivateField(Object o, String fieldName) {
        try {
            Field field = o.getClass().getDeclaredField(fieldName);
            field.setAccessible(true);
            return field.get(o);
        } catch(Exception e) {
            throw new IllegalArgumentExecption(e);
    }


    @Override
    public String test(final Object secretChecks) {
        final Check4SecretsInClear check4SecretsInClear = (Check4SecretsInClear)secretChecks;
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("class:").
        append(check4SecretsInClear.getClass().getSimpleName());

        boolean bSecretInt = false;
        String s = "";
        try {
            int secretInt = (Integer)readPrivateField(check4SecretsInClear,"secretInt"); //<<< HERE! It's cast as an integer!!!

            bSecretInt = check4SecretsInClear.isSecretInt(secretInt); //<<< HERE! Param must be an int.
        } catch (ClassCastException e) {
            s = "," + e.getClass().getSimpleName();
        } finally {
            stringBuilder.append(" int:").append(bSecretInt).append(s);
            s = "";
        }
        return stringBuilder.toString();
    }
}

编辑:

相反,从铸造(INT)的readPrivateField() 相反,我提取字符串值String.valueOf(Object)Object.toString() 然后我就可以传递字符串作为一个INT PARAM new Integer(stringValue)

然而:

如果解析器选择代表secretInt类型字节[]字符串值将是坚果和MAL代码将被PWNED。 任何建议生产可以有效抵抗呢?

Answer 1:

Field.get的返回类型()是一个对象。 如果你需要知道它的类,你可以调用Field.getType()但通常你不需要知道的类型,只包含的信息。

你可以只是做

 String secret = "42";

要么

@Override
public boolean isSecretInt(int check) {
    return check / 6.0 == 7;
}

不要使用整数来比较值,因为这比较对象,而不是它们的值。


更短的实现

private Object readPrivateField(Object o, String fieldName) {
     try {
         Field field = o.getClass().getDeclaredField(fieldName);
         field.setAccessible(true);
         return field.get(o);
     } catch(Exception e) {
         throw new IllegalArgumentExecption(e);
     }
}

BTW:对于那些谁看过银河系漫游指南银河“那如果你乘6 9你”。

System.out.println(Integer.toString(6 * 9, 13));

版画

42

;)



Answer 2:

您可以随时使用:

String value = String.valueOf(field.get(o));

为了避免关心的类型是什么,总是给你一个字符串。



Answer 3:

出处:彼得Lawrey

如果是适当不合适你知道答案,就不能在代码中不一般。 你需要阅读的字节码isSecretInt ,看看它是如何做,并为人类是最简单的解决方案;) -



文章来源: Reflection improvements to access field secret, when field type is unknown