Skip to content

Commit 1e9e926

Browse files
committed
add resolveProxyClassRejectsDynamicProxies unit test
Signed-off-by: ceki <ceki@qos.ch>
1 parent 2de5cbe commit 1e9e926

1 file changed

Lines changed: 61 additions & 0 deletions

File tree

logback-core/src/test/java/ch/qos/logback/core/net/HardenedObjectInputStreamTest.java

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
import java.io.IOException;
2020
import java.io.InvalidClassException;
2121
import java.io.ObjectOutputStream;
22+
import java.io.Serializable;
23+
import java.lang.reflect.InvocationHandler;
24+
import java.lang.reflect.Method;
25+
import java.lang.reflect.Proxy;
2226
import java.util.HashSet;
2327
import java.util.Set;
2428

@@ -109,4 +113,61 @@ private Set buildEvilHashset() {
109113
}
110114
return root;
111115
}
116+
117+
/**
118+
* Demonstrates that HardenedObjectInputStream.resolveProxyClass works correctly
119+
* by rejecting deserialization of dynamic proxy classes, even when the interfaces
120+
* they implement are whitelisted.
121+
*/
122+
@Test
123+
public void resolveProxyClassRejectsDynamicProxies() throws Exception {
124+
ProxyInterface proxy = (ProxyInterface) Proxy.newProxyInstance(
125+
getClass().getClassLoader(),
126+
new Class<?>[]{ProxyInterface.class},
127+
new TestInvocationHandler()
128+
);
129+
130+
// Serialize the proxy instance
131+
ByteArrayOutputStream bos = new ByteArrayOutputStream();
132+
try (ObjectOutputStream oos = new ObjectOutputStream(bos)) {
133+
oos.writeObject(proxy);
134+
}
135+
136+
// Attempt to deserialize using HardenedObjectInputStream.
137+
// We deliberately whitelist both the interface and the invocation handler.
138+
// Despite this, deserialization must fail because resolveProxyClass always
139+
// throws InvalidClassException for proxy classes.
140+
String[] whitelist = new String[]{
141+
ProxyInterface.class.getName(),
142+
TestInvocationHandler.class.getName()
143+
};
144+
145+
ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
146+
HardenedObjectInputStream hardenedOis = new HardenedObjectInputStream(context, bis, whitelist);
147+
148+
assertThrows(InvalidClassException.class, hardenedOis::readObject);
149+
hardenedOis.close();
150+
}
151+
152+
/**
153+
* A marker interface for the dynamic proxy used in the resolveProxyClass test.
154+
*/
155+
interface ProxyInterface extends Serializable {
156+
String getMessage();
157+
}
158+
159+
/**
160+
* A serializable InvocationHandler used to create the test dynamic proxy.
161+
*/
162+
static class TestInvocationHandler implements InvocationHandler, Serializable {
163+
private static final long serialVersionUID = 1L;
164+
165+
@Override
166+
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
167+
if ("getMessage".equals(method.getName())) {
168+
return "hello from proxy";
169+
}
170+
return null;
171+
}
172+
}
112173
}

0 commit comments

Comments
 (0)