You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by ku...@apache.org on 2024/06/17 11:03:01 UTC
(struts) 01/01: WW-5428 Allowlist capability should resolve Hibernate proxies when disableProxyObjects is not set
This is an automated email from the ASF dual-hosted git repository.
kusal pushed a commit to branch WW-5428-allowlist-hibernate
in repository https://gitbox.apache.org/repos/asf/struts.git
commit 1c25b0537f63a28ca25db39d146b4595487fb032
Author: Kusal Kithul-Godage <gi...@kusal.io>
AuthorDate: Mon Jun 17 21:02:49 2024 +1000
WW-5428 Allowlist capability should resolve Hibernate proxies when disableProxyObjects is not set
---
.../xwork2/ognl/SecurityMemberAccess.java | 10 +++++++
.../com/opensymphony/xwork2/util/ProxyUtil.java | 33 ++++++++++++++++++++++
2 files changed, 43 insertions(+)
diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
index f882b2c58..db0598541 100644
--- a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
+++ b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java
@@ -209,6 +209,16 @@ public class SecurityMemberAccess implements MemberAccess {
* @return {@code true} if member access is allowed
*/
protected boolean checkAllowlist(Object target, Member member) {
+ if (!disallowProxyObjectAccess && ProxyUtil.isProxy(target)) {
+ // If disallowProxyObjectAccess is not set, allow resolving Hibernate entities to their underlying classes/members
+ // This allows the allowlist capability to function in applications where the developer has accepted this risk
+ Object newTarget = ProxyUtil.getHibernateProxyTarget(target);
+ if (newTarget != target) {
+ target = newTarget;
+ member = ProxyUtil.resolveTargetMember(member, newTarget);
+ }
+ }
+
Class<?> memberClass = member.getDeclaringClass();
if (!enforceAllowlistEnabled) {
return true;
diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
index c169af20b..895cfb7ee 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/ProxyUtil.java
@@ -24,6 +24,7 @@ import com.opensymphony.xwork2.ognl.OgnlCacheFactory;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.apache.commons.lang3.reflect.MethodUtils;
+import org.hibernate.Hibernate;
import org.hibernate.proxy.HibernateProxy;
import java.lang.reflect.Constructor;
@@ -33,6 +34,8 @@ import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
+import static java.lang.reflect.Modifier.isPublic;
+
/**
* <code>ProxyUtil</code>
* <p>
@@ -255,4 +258,34 @@ public class ProxyUtil {
return false;
}
+
+ /**
+ * @return the target instance of the given object if it is a Hibernate proxy object, otherwise the given object
+ */
+ public static Object getHibernateProxyTarget(Object object) {
+ try {
+ return Hibernate.unproxy(object);
+ } catch (NoClassDefFoundError ignored) {
+ return object;
+ }
+ }
+
+ /**
+ * @return matching member on target object if one exists, otherwise the same member
+ */
+ public static Member resolveTargetMember(Member proxyMember, Object target) {
+ int mod = proxyMember.getModifiers();
+ if (proxyMember instanceof Method) {
+ if (isPublic(mod)) {
+ return MethodUtils.getMatchingAccessibleMethod(target.getClass(), proxyMember.getName(), ((Method) proxyMember).getParameterTypes());
+ } else {
+ return MethodUtils.getMatchingMethod(target.getClass(), proxyMember.getName(), ((Method) proxyMember).getParameterTypes());
+ }
+ } else if (proxyMember instanceof Field) {
+ return FieldUtils.getField(target.getClass(), proxyMember.getName(), isPublic(mod));
+ } else if (proxyMember instanceof Constructor && isPublic(mod)) {
+ return ConstructorUtils.getMatchingAccessibleConstructor(target.getClass(), ((Constructor<?>) proxyMember).getParameterTypes());
+ }
+ return proxyMember;
+ }
}