【问题标题】:Reflection improvements to access field secret, when field type is unknown当字段类型未知时,对访问字段秘密的反射改进
【发布时间】:2014-02-20 14:20:11
【问题描述】:

我正在学习安全性并正在研究以明文方式存储秘密。

当我检索私有字段的内容时,它返回一个对象。我的恶意代码正确地假定并将对象转换为 int,但是如果我将字段类型从 int secretInt = 42; 更改/解析为 String secretInt = (new Integer(42).intValue()).tostring,恶意代码将失败。

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

我怎样才能为 Mal 代码添加健壮性,以便删除返回类型的假设。这可能吗?我需要将此值用作 int 参数。

编辑:'String' 是一个例子,但解析器可能会选择一种数据结构,因为它不适合 byte[]、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();
    }
}

编辑:

而不是从readPrivateField() 转换 (int)。相反,我提取字符串值String.valueOf(Object)Object.toString()。然后我可以将该字符串作为 int 参数传递给 new Integer(stringValue)

但是:

如果解析器选择将secretInt 表示为 byte[] 类型,则字符串值将是疯狂的,并且恶意代码将被 pwned。有什么建议可以对此产生鲁棒性吗?

【问题讨论】:

  • instanceof 怎么样?
  • 我是从Class&lt;?&gt; type = field.getType();那里得到的吗?
  • 关于non-compliant 代码:if(condition){return true}else{return false}return condition 相同。另外,如果您只想将secretInt 与原始int 进行比较,为什么还要将secretInt 包装在新的Integer 中?无论如何,包裹的secretInt 将立即拆箱为原始int
  • 在向下转换之前,您可以使用instanceof检查类型。
  • @Pshemo "与返回条件相同" 哈哦耶!不错!

标签: java security reflection refactoring exploit


【解决方案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);
     }
}

顺便说一句:“如果你将 6 乘以 9,你会得到什么”,对于那些阅读过《银河系漫游指南》的人来说。

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

打印

42

;)

【讨论】:

  • 抱歉New Integer(check) 的包装是我忘记删除的自动解析器的代码,已更正。
  • 我已经用你的 readPrivateField() 进行了修改,并更正了 isSecretInt()
【解决方案2】:

您可以随时使用:

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

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

【讨论】:

  • 类似于.toString()。然后当我打电话给isSecret(new Integer(s)) ?
  • 如果秘密被解析成一个字节[]或其他适当不合适的东西,这将不起作用?
  • @AnotherCompilerError 如果它不合适你知道答案,它不能在代码中不通用。您需要阅读 isSecretInt 的字节码以了解它是如何完成的,为此人类是最简单的解决方案;)
  • @PeterLawrey 是的!谢谢你。我会等着看看有没有人有什么建议。
【解决方案3】:

学分:彼得·劳里

如果您知道答案是适当的不合适的,那么它不能在代码中通用。您需要阅读isSecretInt 的字节码以了解它是如何完成的,为此人类是最简单的解决方案;) –

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    相关资源
    最近更新 更多