An interesting point:

Q: Unicast discovery can use JERI-SSL Endpoint's but is not subject to the unmarshalling attack, why not? A: It doesn't use unmarshalling, instead, the connection is authenticated before the proxy is downloaded. Discovery code already knows the interface to expect: ServiceRegistrar. It applies any remaining method constraints to the proxy after the proxy is created.

So it dawned on me that the problem with Reggie (our existing lookup service implementing the ServiceRegistrar interface), is it uses MarshalledInstance.

When the lookup service stores and later retrieves a service proxy, it already knows the proxy service interface and classes. But to allow the proxy to utilise any communication method it wishes, the connection implementation choice is left to the proxy. Now this makes sense on trusted networks, but that flexibility comes at the expense of security.

What's the alternative?

Provide a ServiceItem (subclass) that contains Entry's, ServiceID and a URI (when we decide the appropriate format), which can be used to establish an Endpoint connection.

The ServiceRegistrar2 proxy doesn't need to perform unmarshalling on the client, instead a connection is made directly to the service by the ServiceRegistrar2 proxy, on behalf of the client. If MethodConstraints are not satisfied, the proxy is never downloaded.

Now since we're applying method constraints, which may include minimum principals, authentication, integrity and confidentiality, the only remaining task for the client to perform is proxy verification. This could also be complimentary to maven provisioning. Maven provisioning doesn't solve deserialization privilege escallation attacks, no deserialization whatsoever should be performed before authentication.

This functionality would be limited to ServiceRegistrar2, the existing ServiceRegistrar would behave as it always has.

A client could then avoid the unmarshalling attack, but would have to ensure that it trusts the ServiceRegistrar2 first.

public interface ServiceRegistrar2 extends ServiceRegistrar{

    /**
* Returns a ResultStream that provides access to ServiceClasspathSubItem * instances. The ResultStream terminates with a null value. The result
     * stream may be infinite, or limited by an integer limit value.
     *
* A ServiceClasspathSubItem implementation instance is a ServiceItem that
     * contains only Objects that are resolvable on the local classpath,
     * this is useful for clients to perform filtering before requiring a
     * download of the actual ServiceItem.
     *
     * The ResultStream should be closed once the desired service has been
     * found, or services have been processed.
     *
     * @param tmpl template to match
     * specified template
     *
     * @param maxBatchSize held locally, larger batch sizes reduce network
* traffic, but may delay processing locally depending on implementation. * @param limit - Zero for infinite, otherwise limits the number of matching
     * results.
     * @return ResultStream containing ServiceItem's
     * @throws java.io.IOException
     * @see ServiceItem
     * @see ServiceClasspathSubItem
     * @see ResultStream
     * @see ServiceResultStreamFilter
     * @see ResultStreamUnmarshaller
     * @since 2.2.0
     */
ResultStream lookup(ServiceTemplate tmpl, Class[] entryClasses, MethodConstraints constraints,
            int maxBatchSize, int limit)  throws IOException;
}

/**
 * <p>
 * ServiceItemClasspathSub is intended for client side filtering of lookup
 * service results prior to clients using a service, the lookup service
 * that implements this class, implements #getServiceItem(), so clients
 * can obtain a complete ServiceItem when required after filtering.
 * </p><p>
 * ServiceItemClasspathSub extends ServiceItem and can be used anywhere a
 * ServiceItem is required for querying or inspecting Entry fields that are
 * resolvable from the local classpath.  If dynamically downloaded code is
 * required, Remote or Serializable object references are not resolved,
 * instead, such fields are set to null to avoid codebase download.
 * </p><p>
 * ServiceItemClasspathSub inherits all fields from ServiceItem.
 * </p><p>
* Some fields in ServiceItemClasspathSub may be null or fields in Entry's may * be null or even the service reference may be null, these fields would be * non-null in a ServiceItem that resolves classes from dynamically downloaded
 * code or a remote codebase.
 * </p><p>
 * The serviceID field shall be non-null always.
 * </p><p>
 * ServiceItem's toString() method will return a different result for
 * ServiceItemClasspathSub instances.
 * </p><p>
 * When required, a new ServiceItem that is unmarshalled
 * using remote codebases and dynamically downloaded code can be obtained
 * by calling #getServiceItem().
 * </p>
 *
 * @since 2.2.1
 */
public abstract class ServiceItemClasspathSub extends ServiceItem{
    private static final long SerialVersionUID = 1L;
protected ServiceItemClasspathSub(ServiceID id, Entry[] unmarshalledEntries){
        super(id, (Object) null, unmarshalledEntries);
    }

    /* Default constructor for serializable sub class.
     */
    protected ServiceItemClasspathSub(){
        super(null, null, null);
    }
    /**
     * Using remote and local code as required getServiceItem returns a
     * new ServiceItem.
     *
     * The returned ServiceItem must not be an instance of this class.
     *
* @return ServiceItem, totally unmarshalled, using remote codebase resources
     * in addition to any local classpath or resources.
     */
    public abstract ServiceItem getServiceItem();
}



Reply via email to