CVE-2018-1273
https://github.com/vulhub/vulhub/tree/master/spring/CVE-2018-1273
概述
Spring Data Commons 远程命令执行漏洞(CVE-2018-1273)
Spring Data是一个用于简化数据库访问,并支持云服务的开源框架,Spring Data Commons是Spring Data下所有子项目共享的基础框架。Spring Data Commons 在2.0.5及以前版本中,存在一处SpEL表达式注入漏洞,攻击者可以注入恶意SpEL表达式以执行任意命令。
影响版本:
Spring Data Commons 1.13 - 1.13.10 (Ingalls SR10)
Spring Data REST 2.6 - 2.6.10 (Ingalls SR10)
Spring Data Commons 2.0 to 2.0.5 (Kay SR5)
Spring Data REST 3.0 - 3.0.5 (Kay SR5)
分析
搜索SpelExpressionParser可以定位到org.springframework.data.web.MapDataBinder.MapPropertyAccessor#setPropertyValue,但是无法往上追路径。
@Override
public void setPropertyValue(String propertyName, @Nullable Object value) throws BeansException {
if (!isWritableProperty(propertyName)) {
throw new NotWritablePropertyException(type, propertyName);
}
StandardEvaluationContext context = new StandardEvaluationContext();
context.addPropertyAccessor(new PropertyTraversingMapAccessor(type, conversionService));
context.setTypeConverter(new StandardTypeConverter(conversionService));
context.setTypeLocator(typeName -> {
throw new SpelEvaluationException(SpelMessage.TYPE_NOT_FOUND, typeName);
});
context.setRootObject(map);
Expression expression = PARSER.parseExpression(propertyName);
PropertyPath leafProperty = getPropertyPath(propertyName).getLeafProperty();
TypeInformation<?> owningType = leafProperty.getOwningType();
TypeInformation<?> propertyType = leafProperty.getTypeInformation();
propertyType = propertyName.endsWith("]") ? propertyType.getActualType() : propertyType;
if (propertyType != null && conversionRequired(value, propertyType.getType())) {
PropertyDescriptor descriptor = BeanUtils.getPropertyDescriptor(owningType.getType(),
leafProperty.getSegment());
if (descriptor == null) {
throw new IllegalStateException(String.format("Couldn't find PropertyDescriptor for %s on %s!",
leafProperty.getSegment(), owningType.getType()));
}
MethodParameter methodParameter = new MethodParameter(descriptor.getReadMethod(), -1);
TypeDescriptor typeDescriptor = TypeDescriptor.nested(methodParameter, 0);
if (typeDescriptor == null) {
throw new IllegalStateException(
String.format("Couldn't obtain type descriptor for method parameter %s!", methodParameter));
}
value = conversionService.convert(value, TypeDescriptor.forObject(value), typeDescriptor);
}
try {
expression.setValue(context, value);
} catch (SpelEvaluationException o_O) {
throw new NotWritablePropertyException(type, propertyName, "Could not write property!", o_O);
}
}
修复分析
修复实际上就是将StandardEvaluationContext变成SimpleEvaluationContext。