Skip to content

Commit

Permalink
Disable rpc.enhancedClasses by default at runtime (#9879)
Browse files Browse the repository at this point in the history
Logs warnings at compile time, indicating which classes need to be
cleaned up to remove this feature.

Mitigation for #9709
  • Loading branch information
niloc132 committed Jan 8, 2024
1 parent a607e97 commit 9434b2f
Show file tree
Hide file tree
Showing 6 changed files with 55 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ public boolean isAllowed(JClassType type) {
JPA_ENTITY_ANNOTATION =
Class.forName("javax.persistence.Entity").asSubclass(Annotation.class);
} catch (ClassNotFoundException e) {
// Ignore, JPA_ENTITY_CAPABLE_ANNOTATION will be null
// Ignore, JPA_ENTITY_CAPABLE_ANNOTATION will be null
}
}

Expand Down Expand Up @@ -869,6 +869,11 @@ public SerializableTypeOracle build(TreeLogger logger) throws UnableToCompleteEx

if (tic.maybeEnhanced()
|| (enhancedClasses != null && enhancedClasses.contains(type.getQualifiedSourceName()))) {
logger.log(TreeLogger.WARN, "The class " + type.getQualifiedSourceName() + " has " +
"JPA/JDO annotations or is explicitly configured as an enhanced class using the " +
"configuration property rpc.enhancedClasses. This makes the server vulnerable " +
"to an issue with deserialization of unsafe data. See " +
"https://github.com/gwtproject/gwt/issues/9709 for more information.");
type.setEnhanced();
}
}
Expand Down
16 changes: 16 additions & 0 deletions user/src/com/google/gwt/user/server/rpc/RemoteServiceServlet.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
package com.google.gwt.user.server.rpc;

import static com.google.gwt.user.client.rpc.RpcRequestBuilder.MODULE_BASE_HEADER;
import static com.google.gwt.user.server.rpc.SerializationPolicyLoader.ENABLE_ENHANCED_CLASSES;
import static com.google.gwt.user.server.rpc.SerializationPolicyLoader.ENABLE_GWT_ENHANCED_CLASSES_PROPERTY;

import com.google.gwt.user.client.rpc.IncompatibleRemoteServiceException;
import com.google.gwt.user.client.rpc.RpcTokenException;
Expand Down Expand Up @@ -94,6 +96,20 @@ static SerializationPolicy loadSerializationPolicy(HttpServlet servlet,
try {
serializationPolicy = SerializationPolicyLoader.loadFromStream(is,
null);
if (serializationPolicy.hasClientFields()) {
if (ENABLE_ENHANCED_CLASSES) {
servlet.log("WARNING: Service deserializes enhanced JPA/JDO classes, which is " +
"unsafe. See https://github.com/gwtproject/gwt/issues/9709 for more " +
"detail on the vulnerability that this presents.");
} else {
servlet.log("ERROR: Service deserializes enhanced JPA/JDO classes, which is " +
"unsafe. Review build logs to see which classes are affected, or set " +
ENABLE_GWT_ENHANCED_CLASSES_PROPERTY + " to true to allow using this " +
"service. See https://github.com/gwtproject/gwt/issues/9709 for more " +
"detail.");
serializationPolicy = null;
}
}
} catch (ParseException e) {
servlet.log("ERROR: Failed to parse the policy file '"
+ serializationPolicyFilePath + "'", e);
Expand Down
10 changes: 10 additions & 0 deletions user/src/com/google/gwt/user/server/rpc/SerializationPolicy.java
Original file line number Diff line number Diff line change
Expand Up @@ -82,4 +82,14 @@ public abstract void validateDeserialize(Class<?> clazz)
*/
public abstract void validateSerialize(Class<?> clazz)
throws SerializationException;

/**
* Returns true if there may be any unsafe client fields in the serialization policy. The default
* implementation returns true to ensure that custom implementations validate accordingly.
*
* @return true if the client may send unsafely serialized data, false otherwise
*/
public boolean hasClientFields() {
return true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@ public final class SerializationPolicyLoader {
*/
public static final String SERIALIZATION_POLICY_FILE_ENCODING = "UTF-8";

/**
* System property to enable gwt-rpc enhanced classes. To use this, set the JVM system property
* with name {@value ENABLE_GWT_ENHANCED_CLASSES_PROPERTY} to {@code true}, any other value will
* leave this feature disabled in the server at runtime.
*/
public static final String ENABLE_GWT_ENHANCED_CLASSES_PROPERTY = "gwt.enhancedClasses.enabled";

/**
* Flag to enable using enhanced classes, for applications that need them and are taking
* appropriate steps to secure them. Defaults to false.
*/
public static final boolean ENABLE_ENHANCED_CLASSES = "true".equals(System.getProperty(ENABLE_GWT_ENHANCED_CLASSES_PROPERTY));

private static final String FORMAT_ERROR_MESSAGE = "Expected: className, "
+ "[true | false], [true | false], [true | false], [true | false], typeId, signature";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,9 @@ private boolean isInstantiable(Class<?> clazz) {
}
return SerializabilityUtil.hasCustomFieldSerializer(clazz) != null;
}

@Override
public boolean hasClientFields() {
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,11 @@ public Set<String> getClientFieldNamesForEnhancedClass(Class<?> clazz) {
return fieldNames == null ? null : Collections.unmodifiableSet(fieldNames);
}

@Override
public boolean hasClientFields() {
return clientFields != null && !clientFields.isEmpty();
}

public final String getTypeIdForClass(Class<?> clazz)
throws SerializationException {
return typeIds.get(clazz);
Expand Down

0 comments on commit 9434b2f

Please sign in to comment.