Skip to content

Commit 93c027b

Browse files
yrodieregsmet
authored andcommitted
HV-1774 Test arbitrary code injection through buildConstraintViolationWithTemplate()
1 parent 628c032 commit 93c027b

File tree

1 file changed

+51
-0
lines changed

1 file changed

+51
-0
lines changed

engine/src/test/java/org/hibernate/validator/test/constraints/ConstraintValidatorContextTest.java

+51
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,20 @@ public void testAddParameterNodeForFieldLevelConstraintCausesException() throws
208208
}
209209
}
210210

211+
@Test
212+
public void testInjectionCausedByRecklessConcatenation() {
213+
String maliciousPayload = "$\\A{1 + 1}";
214+
215+
// Simulate user entry, through a web form for example
216+
MyObjectWithELInjectionRiskCausedByRecklessConcatenation object = new MyObjectWithELInjectionRiskCausedByRecklessConcatenation();
217+
object.field1 = maliciousPayload;
218+
Set<ConstraintViolation<MyObjectWithELInjectionRiskCausedByRecklessConcatenation>> constraintViolations = validator.validate( object );
219+
assertThat( constraintViolations ).containsOnlyViolations(
220+
violationOf( ValidationWithELInjectionRiskCausedByRecklessConcatenation.class )
221+
.withMessage( "Value '" + maliciousPayload + "' is invalid" )
222+
);
223+
}
224+
211225
@MyClassLevelValidation
212226
private static class MyObject {
213227
@NotNull
@@ -278,6 +292,13 @@ public String getName() {
278292
}
279293
}
280294

295+
@ValidationWithELInjectionRiskCausedByRecklessConcatenation
296+
private static class MyObjectWithELInjectionRiskCausedByRecklessConcatenation {
297+
298+
String field1;
299+
300+
}
301+
281302
@Retention(RUNTIME)
282303
@Constraint(validatedBy = MyClassLevelValidation.Validator.class)
283304
public @interface MyClassLevelValidation {
@@ -486,4 +507,34 @@ public boolean isValid(String value, ConstraintValidatorContext context) {
486507
}
487508
}
488509
}
510+
511+
@Retention(RUNTIME)
512+
@Constraint(validatedBy = ValidationWithELInjectionRiskCausedByRecklessConcatenation.Validator.class)
513+
public @interface ValidationWithELInjectionRiskCausedByRecklessConcatenation {
514+
String message() default "failed";
515+
516+
Class<?>[] groups() default { };
517+
518+
Class<? extends Payload>[] payload() default { };
519+
520+
class Validator
521+
implements ConstraintValidator<ValidationWithELInjectionRiskCausedByRecklessConcatenation, MyObjectWithELInjectionRiskCausedByRecklessConcatenation> {
522+
523+
@Override
524+
public boolean isValid(MyObjectWithELInjectionRiskCausedByRecklessConcatenation value, ConstraintValidatorContext context) {
525+
context.disableDefaultConstraintViolation();
526+
527+
// This is bad practice: message parameters should be used instead.
528+
// Regardless, it can happen and should work as well as possible.
529+
context.buildConstraintViolationWithTemplate( "Value '" + escape( value.field1 ) + "' is invalid" )
530+
.addConstraintViolation();
531+
532+
return false;
533+
}
534+
535+
private String escape(String value) {
536+
return value.replaceAll( "\\$+\\{", "{" );
537+
}
538+
}
539+
}
489540
}

0 commit comments

Comments
 (0)