没有返回值的方法更安全吗?

时间:2014-12-16 04:41:59

标签: security oop

请原谅我的天真,因为我不熟悉利用或消除软件漏洞,所以我可能会问一个没有任何意义的问题。这是我最近想到的,无法在网上发现任何专门解决我问题的内容。

请比较以下类(Java):

public class ProvidesCollection {
    private Item[] items;

    public Item[] getItemsArray() {
        return Arrays.copyOf(items, items.length);
    }
}

public class ContainsCollection {
    private Item[] items;

    public void actionItem(int itemNumber, ItemAction itemAction) {
        if(itemNumber < 0 || itemNumber > items.length)
            return; // Or handle as error

        Item i = items[itemNumber - 1];

        if(i != null)
            itemAction.performOn(i);
    }
}

ProvidesCollection类是典型的OO设计。调用者可信遍历从getItemsArray返回的items数组。如果调用者忘记进行边界检查,它可以打开代码进行缓冲区溢出攻击(如果我没有弄错的话)。我知道Java的内存管理可以避免缓冲区溢出,所以Java也是一个不好的例子。让我们假设没有捕获溢出的机制。

ContainsCollection类使数组完全隐藏。注意actionItem方法如何允许程序员检查输入错误并解决它们。那些负责实现API的人可以更好地控制数据和执行流程。

我想知道,ContainsCollection类比ProvidesCollection类更安全吗?有没有证据表明避免返回值(void方法)有助于消除黑客利用代码中错误的能力?

1 个答案:

答案 0 :(得分:4)

不,void方法本质上不比返回值的方法更安全。您可以编写返回值的安全方法,并且可以编写不返回任何内容的不安全方法。

通常,当您想要封装一些实现副作用的代码时,您将拥有void个方法。例如,将文件发送到打印机,更改对象的内部状态或执行其他操作。这应该是签名的返回类型是否应该是void的试金石 - 当它发生火灾并且忘记了#34;操作类型。

返回值的方法在将敏感数据暴露给不道德的人时,实际上只比void方法更不安全。然而,这并不意味着同样不道德的人无法将某些数据传递给无效方法,以破坏安全性。虽然无效方法不会返回值,但它们仍然可以抛出异常。调用者可以通过使异常并尝试/捕获它们来了解有关void方法数据的某些事情。此外,我有幸有机会阅读将密码记录到跟踪文件的代码,并且该记录方法为void

说明您的Item对象包含CreditCardNumberSocialSecurityNumber等属性。在这种情况下,您的第一种方法可能会暴露安全漏洞。但是,您可以通过在返回数组引用之前加密这些值来缓解这种情况(或者根本不暴露它们)。任何需要使用信用卡号进行操作以执行副作用操作(例如授权事务)的操作都可以标记为无效,并在内部执行解密(或在封装操作中获取未加密的值)。

但它不一定是方法的返回签名使其或多或少安全 - 它是暴露的数据,以及它暴露给谁的数据。请记住,任何人都可以编写一个愚蠢的void方法,将其数据库连接字符串写入公共网页。

<强>更新

  

...说存在漏洞,因为方法返回错误的值或   从错误的使用返回值。如果你能解决问题怎么办?   用户依赖于返回值?没有机会回去了   删除返回,因为其他人依赖它。

如果您需要,则引入重大变更。这是让客户依赖于接口而不是具体类型的抽象的一个很好的理由。在必须具备混凝土类型的地方,请仔细设计。公开所需的最少量信息。

最后,所有数据都只是文本。您的Item类将包含字符串,整数,布尔值和其他原始值或包装基元的嵌套对象。您仍然可以对封装的getItemsArray方法进行更改,以便在需要时返回值之前对敏感数据进行模糊处理。如果这有可能打破客户端代码,那么你决定是否咬紧牙关并发布一个突破性的变化或者接受这个缺陷。

  

虚空方法是否更好,因为你可以解决它?

没有。然后,您最终会得到一个仅执行操作的API,例如黑洞,您可以在其中发送数据,而不会再次收到数据。就像我之前说过的,如果方法执行一些副作用并且调用者不需要返回任何内容(除了可能捕获异常),方法应该是void。当您的API需要返回数据时,返回一个抽象,如接口而不是具体类型。