river-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Peter Firmstone <j...@zeus.net.au>
Subject Re: The internet - Proxy Isolation - Denial of Service Attack.
Date Sun, 06 Feb 2011 08:53:05 GMT
Notice the code below also encapsulates the codebase download too, so 
denials of service using large codebases, InputStream's, deserialization 
etc are encapsulated.

This is fine for a smart proxy that implements a known service 
interface, but what about ServiceUI?

Any thoughts?

Cheers,

Peter.

Peter Firmstone wrote:
> The following class, isolates a proxy on it's own thread and using 
> reflection, isolates it completely from the rest of the executing 
> environment, by passing method calls as tasks.
>
> Forgive the tab formatting.
>
> Cheers,
>
> Peter.
>
> /*
> * Licensed to the Apache Software Foundation (ASF) under one
> * or more contributor license agreements.  See the NOTICE file
> * distributed with this work for additional information
> * regarding copyright ownership. The ASF licenses this file
> * to you under the Apache License, Version 2.0 (the
> * "License"); you may not use this file except in compliance
> * with the License. You may obtain a copy of the License at
> *
> *      http://www.apache.org/licenses/LICENSE-2.0
> *
> * Unless required by applicable law or agreed to in writing, software
> * distributed under the License is distributed on an "AS IS" BASIS,
> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 
> implied.
> * See the License for the specific language governing permissions and
> * limitations under the License.
> */
>
> package org.apache.river.impl.security.dos;
>
> import java.io.IOException;
> import java.lang.reflect.InvocationHandler;
> import java.lang.reflect.Method;
> import java.util.Collection;
> import java.util.concurrent.Callable;
> import java.util.concurrent.ExecutionException;
> import java.util.concurrent.ExecutorService;
> import java.util.concurrent.Executors;
> import java.util.concurrent.ThreadFactory;
> import java.util.concurrent.TimeUnit;
> import java.util.concurrent.TimeoutException;
> import net.jini.io.MarshalledInstance;
>
> /**
> * A preliminary experiment into Isolating a Smart Proxy.
> *
> * I think I'll investigate creating a Permission for additional threads
> * for improved performance and also creating an event model so clients
> * don't need to wait for remote method returns.  I'll create a new 
> interface
> * for this, that can be implemented by services directly too.
> *
> * Alternative, only maintain this data structure for as long as it takes
> * to verify proxy trust, then return proxy to the client or have the 
> client
> * thread call the smart proxy via the reflection proxy directly.
> *
> * REMIND: Investigate subclass method returns, this would be simple, 
> if the
> * smart proxy is confined to it's own ClassLoader, we just check the 
> class
> * of the object returned isn't from that ClassLoader, unless the smart 
> proxy
> * has a ServiceAPISubclassPermission or something like that.
> *
> * @author Peter Firmstone
> */
> public class ProxyIsolate implements InvocationHandler {
>    private volatile Object smartProxy;
>    private volatile ExecutorService proxyExecutor;
>    private volatile Throwable thrown;
>    private final long timeout;
>    private final TimeUnit unit;
>      @SuppressWarnings("unchecked")
>    public ProxyIsolate(MarshalledInstance proxy,
>                ClassLoader defaultLoader,
>                boolean verifyCodebaseIntegrity,
>                ClassLoader verifierLoader,
>                Collection context,
>                            long timeout,
>                            TimeUnit timeUnit
>        ) throws TimeoutException, InterruptedException, 
> ExecutionException{
>    this.timeout = timeout;
>        unit = timeUnit;
>    thrown = null;
>    proxyExecutor = Executors.newSingleThreadExecutor(new Factory(this));
>    UnmarshallProxyTask task =
>        new UnmarshallProxyTask(proxy, defaultLoader,
>        verifyCodebaseIntegrity, verifierLoader, context);
>        smartProxy = proxyExecutor.submit(task).get(timeout, timeUnit);
>    }
>      private Object taskInvoke(Object proxy, Method method, Object[] 
> args) throws
>        Exception {
>    String methodName = method.getName();
>    if (method.getDeclaringClass() == Object.class)  {
>        // Handle the Object public methods.
>        if (methodName.equals("hashCode"))  {
>        return new Integer(System.identityHashCode(proxy));         } 
> else if (methodName.equals("equals")) {
>        return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
>        } else if (methodName.equals("toString")) {
>        return proxy.getClass().getName() + '@' + 
> Integer.toHexString(proxy.hashCode());
>        }
>    }
>    return method.invoke(smartProxy, args);      }
>      @SuppressWarnings("unchecked")
>    public Object invoke(Object proxy, Method method, Object[] args) 
> throws Throwable {
>    if (isTerminated()) throw new IOException(thrown);
>    Callable task = new MethodInvocationTask(this, proxy, method, args);
>    return proxyExecutor.submit(task).get(timeout, unit);
>    }
>      private void terminate(Throwable e){
>    thrown = e;
>    smartProxy = null;
>    proxyExecutor.shutdown();      }
>      private boolean isTerminated(){
>    if (smartProxy == null) return true;
>    return false;
>    }
>      private static class Factory implements ThreadFactory{
>    private static final ThreadGroup tg = new 
> ThreadGroup("IsolatedProxy");
>    {
>        tg.setDaemon(true);
>        tg.setMaxPriority(4);
>    }
>    private final ProxyIsolate proxy;
>    Factory(ProxyIsolate spi){
>        proxy = spi;
>    }
>
>    public Thread newThread(Runnable r) {
>        Thread t = new Thread(tg, r);
>        t.setUncaughtExceptionHandler(new ExceptionHandler(proxy));
>        return t;
>    }      }
>      private static class ExceptionHandler implements 
> Thread.UncaughtExceptionHandler{
>    private final ProxyIsolate proxy;
>      ExceptionHandler(ProxyIsolate spi){
>        proxy = spi;
>    }
>
>    public void uncaughtException(Thread t, Throwable e) {
>        // For all other Exceptions we let the ExecutorService handle it.
>        if ( e instanceof Error){
>        // Do we want to take different actions based on the error?
>        proxy.terminate(e);
>        }
>    }
>      }
>      private static class UnmarshallProxyTask implements Callable{
>    private final MarshalledInstance mi;
>    private final ClassLoader defaultLoader;
>    private final boolean verifyCodebaseIntegrity;
>    private final ClassLoader verifierLoader;
>    private final Collection context;
>      UnmarshallProxyTask(MarshalledInstance proxy,
>        ClassLoader defaultLoader,
>        boolean verifyCodebaseIntegrity,
>        ClassLoader verifierLoader,
>        Collection context)
>    {
>        mi = proxy;
>        this.defaultLoader = defaultLoader;
>        this.verifyCodebaseIntegrity = verifyCodebaseIntegrity;
>        this.verifierLoader = verifierLoader;
>        this.context = context;
>    }  
>    public Object call() throws Exception {
>        return mi.get(defaultLoader, verifyCodebaseIntegrity,
>            verifierLoader, context);
>    }
>      }
>      private static class MethodInvocationTask implements Callable {
>    private final ProxyIsolate smartProxy;
>    private final Object proxy;
>    private final Method method;
>    private final Object[] args;
>    MethodInvocationTask(ProxyIsolate target, Object proxy, Method 
> method, Object[] args){
>        smartProxy = target;
>        this.proxy = proxy;
>        this.method = method;
>        this.args = args;          }
>    public Object call() throws Exception {
>        return smartProxy.taskInvoke(proxy, method, args);
>    }
>          }
>
> }
>
>


Mime
View raw message