85 lines
3.3 KiB
Diff
85 lines
3.3 KiB
Diff
From 93c027b954d4ccce1ad82b2f5e27e22357757fa8 Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Yoann=20Rodi=C3=A8re?= <yoann@hibernate.org>
|
|
Date: Mon, 24 Feb 2020 17:23:37 +0100
|
|
Subject: [PATCH] HV-1774 Test arbitrary code injection through
|
|
buildConstraintViolationWithTemplate()
|
|
|
|
---
|
|
.../ConstraintValidatorContextTest.java | 51 +++++++++++++++++++
|
|
1 file changed, 51 insertions(+)
|
|
|
|
diff --git a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java
|
|
index 6094195e3..a89a97016 100644
|
|
--- a/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java
|
|
+++ b/engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java
|
|
@@ -194,6 +194,20 @@ public void testAddParameterNodeForFieldLevelConstraintCausesException() throws
|
|
}
|
|
}
|
|
|
|
+ @Test
|
|
+ public void testInjectionCausedByRecklessConcatenation() {
|
|
+ String maliciousPayload = "$\\A{1 + 1}";
|
|
+
|
|
+ // Simulate user entry, through a web form for example
|
|
+ MyObjectWithELInjectionRiskCausedByRecklessConcatenation object = new MyObjectWithELInjectionRiskCausedByRecklessConcatenation();
|
|
+ object.field1 = maliciousPayload;
|
|
+ Set<ConstraintViolation<MyObjectWithELInjectionRiskCausedByRecklessConcatenation>> constraintViolations = validator.validate( object );
|
|
+ assertThat( constraintViolations ).containsOnlyViolations(
|
|
+ violationOf( ValidationWithELInjectionRiskCausedByRecklessConcatenation.class )
|
|
+ .withMessage( "Value '" + maliciousPayload + "' is invalid" )
|
|
+ );
|
|
+ }
|
|
+
|
|
@MyClassLevelValidation
|
|
private static class MyObject {
|
|
@NotNull
|
|
@@ -264,6 +278,13 @@ public String getName() {
|
|
}
|
|
}
|
|
|
|
+ @ValidationWithELInjectionRiskCausedByRecklessConcatenation
|
|
+ private static class MyObjectWithELInjectionRiskCausedByRecklessConcatenation {
|
|
+
|
|
+ String field1;
|
|
+
|
|
+ }
|
|
+
|
|
@Retention(RUNTIME)
|
|
@Constraint(validatedBy = MyClassLevelValidation.Validator.class)
|
|
public @interface MyClassLevelValidation {
|
|
@@ -496,4 +517,34 @@ public boolean isValid(String value, ConstraintValidatorContext context) {
|
|
}
|
|
|
|
}
|
|
+
|
|
+ @Retention(RUNTIME)
|
|
+ @Constraint(validatedBy = ValidationWithELInjectionRiskCausedByRecklessConcatenation.Validator.class)
|
|
+ public @interface ValidationWithELInjectionRiskCausedByRecklessConcatenation {
|
|
+ String message() default "failed";
|
|
+
|
|
+ Class<?>[] groups() default { };
|
|
+
|
|
+ Class<? extends Payload>[] payload() default { };
|
|
+
|
|
+ class Validator
|
|
+ implements ConstraintValidator<ValidationWithELInjectionRiskCausedByRecklessConcatenation, MyObjectWithELInjectionRiskCausedByRecklessConcatenation> {
|
|
+
|
|
+ @Override
|
|
+ public boolean isValid(MyObjectWithELInjectionRiskCausedByRecklessConcatenation value, ConstraintValidatorContext context) {
|
|
+ context.disableDefaultConstraintViolation();
|
|
+
|
|
+ // This is bad practice: message parameters should be used instead.
|
|
+ // Regardless, it can happen and should work as well as possible.
|
|
+ context.buildConstraintViolationWithTemplate( "Value '" + escape( value.field1 ) + "' is invalid" )
|
|
+ .addConstraintViolation();
|
|
+
|
|
+ return false;
|
|
+ }
|
|
+
|
|
+ private String escape(String value) {
|
|
+ return value.replaceAll( "\\$+\\{", "{" );
|
|
+ }
|
|
+ }
|
|
+ }
|
|
}
|