日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
APACHE OFBIZ XMLRPC遠(yuǎn)程代碼執(zhí)行漏洞分析

                                     [[344961]]

創(chuàng)新互聯(lián)專注于棗陽網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供棗陽營銷型網(wǎng)站建設(shè),棗陽網(wǎng)站制作、棗陽網(wǎng)頁設(shè)計(jì)、棗陽網(wǎng)站官網(wǎng)定制、微信小程序定制開發(fā)服務(wù),打造棗陽網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供棗陽網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

漏洞分析
Apache OFBiz是一個開源的企業(yè)資源規(guī)劃(ERP)系統(tǒng),它提供了一系列企業(yè)應(yīng)用程序來幫助企業(yè)自動化實(shí)現(xiàn)很多業(yè)務(wù)流程。它包含了一個能提供常見數(shù)據(jù)模型和業(yè)務(wù)進(jìn)程的框架,企業(yè)內(nèi)所有的應(yīng)用程序都需要采用這個框架來使用常見數(shù)據(jù)、邏輯和業(yè)務(wù)處理組件。除了框架本身之外,Apache OFBiz還提供了包括會計(jì)(合同協(xié)議、票據(jù)、供應(yīng)商管理、總賬)、資產(chǎn)維護(hù)、項(xiàng)目分類、產(chǎn)品管理、設(shè)備管理、倉庫管理系統(tǒng)(WMS)、制造執(zhí)行/制造運(yùn)營管理(MES/MOM)和訂單處理等功能,除此之外,還實(shí)現(xiàn)了庫存管理、自動庫存補(bǔ)充、內(nèi)容管理系統(tǒng)(CMS)、人力資源(HR)、人員和團(tuán)隊(duì)管理、項(xiàng)目管理、銷售人員自動化、工作量管理、電子銷售點(diǎn)(ePOS)、電子商務(wù)(電子商務(wù))和scrum(開發(fā))等多種功能。

Apache OFBiz使用了一系列開源技術(shù)和標(biāo)準(zhǔn),比如Java、JavaEE、XML和SOAP。

超文本傳輸協(xié)議是一種請求/響應(yīng)協(xié)議,該協(xié)議在 RFC 7230-7237中有詳細(xì)描述。請求由客戶端設(shè)備發(fā)送至服務(wù)器,服務(wù)器接收并處理請求后,會將響應(yīng)發(fā)送回客戶端。一個HTTP請求由請求內(nèi)容、各種Header、空行和可選消息體組成:

 
 
 
  1. Request = Request-Line headers CRLF [message-body] 
  2.  
  3. Request-Line = Method SP Request-URI SP HTTP-Version CRLF 
  4.  
  5. Headers = *[Header] 
  6.  
  7. Header = Field-Name “:” Field-Value CRLF 

CRLF代表新的行序列回車符(CR),后跟換行符(LF),SP表示空格字符。參數(shù)將以鍵值對的形式通過Request- URI或message-body由客戶端傳遞給服務(wù)器,具體將取決于Method和Content-Type頭中定義的參數(shù)。比如說在下面的HTTP請求樣本中,有一個名為“param”的參數(shù),其值為“1”,使用的是POST方法:

 
 
 
  1. POST /my_webapp/mypage.htm HTTP/1.1 
  2.  
  3. Host: www.myhost.com 
  4.  
  5. Content-Type: application/x-www-form-urlencoded 
  6.  
  7. Content-Length: 7 
  8.  
  9.   
  10.  
  11. param=1 

Java序列化
Java支持對對象進(jìn)行序列化操作,使它們額能夠被表示為緊湊和可移植的字節(jié)流,然后可以通過網(wǎng)絡(luò)傳輸這個字節(jié)流,并將其反序列化以供接收的servlet或applet使用。下面的示例演示了如何將一個類進(jìn)行序列化并在隨后提取數(shù)據(jù):

 
 
 
  1. public static void main(String args[]) throws Exception{ 
  2.  
  3.    //This is the object we're going to serialize. 
  4.  
  5.    MyObject1 myObj = new MyObject1(); 
  6.  
  7.    MyObject2 myObj2 = new MyObject2(); 
  8.  
  9.    myObj2.name = "calc"; 
  10.  
  11.    myObj.test = myObj2; 
  12.  
  13.   
  14.  
  15.    //We'll write the serialized data to a file "object.ser" 
  16.  
  17.    FileOutputStream fos = new FileOutputStream("object.ser"); 
  18.  
  19.    ObjectOutputStream os = new ObjectOutputStream(fos); 
  20.  
  21.    os.writeObject(myObj); 
  22.  
  23.    os.close(); 
  24.  
  25.   
  26.  
  27.    //Read the serialized data back in from the file "object.ser" 
  28.  
  29.    FileInputStream fis = new FileInputStream("object.ser"); 
  30.  
  31.    ObjectInputStream ois = new ObjectInputStream(fis); 
  32.  
  33.   
  34.  
  35.    //Read the object from the data stream, and convert it back to a String 
  36.  
  37.    MyObject1 objectFromDisk = (MyObject1)ois.readObject(); 
  38.  
  39.    ois.close(); 
  40.  

所有的Java對象都需要通過Serializable或Externalizable接口來進(jìn)行序列化,這個接口實(shí)現(xiàn)了writeObject()/writeExternal()和readObject()/readExternal()方法,它們會在對象序列化或反序列化時被調(diào)用。這些方法能夠在序列化和反序列化過程中通過修改代碼來實(shí)現(xiàn)自定義行為。

XML-RPC
XML-RPC是一個遠(yuǎn)程過程調(diào)用(RPC)協(xié)議,它使用XML對其調(diào)用進(jìn)行編碼,并使用HTTP作為傳輸機(jī)制。它是一種標(biāo)準(zhǔn)規(guī)范,并提供了現(xiàn)成的實(shí)現(xiàn)方式,允許運(yùn)行在不同的操作系統(tǒng)和環(huán)境中。在在XML-RPC中,客戶機(jī)通過向?qū)崿F(xiàn)XML-RPC并接收HTTP響應(yīng)的服務(wù)器發(fā)送HTTP請求來執(zhí)行RPC。

每個XML-RPC請求都以XML元素“”開頭。此元素包含一個子元素“something”。元素“”包含子元素“”,該子元素可以包含一個或多個“”元素。param XML元素可以包含許多數(shù)據(jù)類型。

如下樣例所示,常見的數(shù)據(jù)類型可以被轉(zhuǎn)換成對應(yīng)的XML類型:

 
 
 
  1.  
  2.  
  3.    
  4.  
  5.     1404 
  6.  
  7.     Something here 
  8.  
  9.     1 
  10.  
  11.    
  12.  
  13.  

各種原語的編碼示例如下:

 
 
 
  1. 1 
  2.  
  3. -12.53 
  4.  
  5. 42 

字符串的編碼示例如下:

 
 
 
  1. Hello world! 

對結(jié)構(gòu)體的編碼示例如下:

 
 
 
  1.  
  2.  
  3.    
  4.  
  5.     foo 
  6.  
  7.     1 
  8.  
  9.    
  10.  
  11.    
  12.  
  13.     bar 
  14.  
  15.     2 
  16.  
  17.    
  18.  
  19.  

序列化數(shù)據(jù)由””和””XML元素包裹來表示,在Apache OFBiz中,序列化代碼在org.apache.xmlrpc.parser.SerializableParser這個Java類中實(shí)現(xiàn)。

但是,Apache OFBiz中存在一個不安全的反序列化漏洞,這個漏洞是由于OFBiz被配置為在發(fā)送到“/webtools/control/xmlrpc”URL時使用XML-RPC攔截和轉(zhuǎn)換HTTP主體中的XML數(shù)據(jù)所導(dǎo)致的。發(fā)送到此端點(diǎn)的請求最初由org.apache.ofbiz.webapp.control.RequestHandler這個Java類來處理,它確定的URL的映射方式。接下來,org.apache.ofbiz.webapp.event.XmlRpcEventHandler類將調(diào)用execute()方法,XML解析首先需要通過XMLReader類來調(diào)用parse()方法,而這個方法需要在org.apache.ofbiz.webapp.event.XmlRpcEventHandler類的getRequest()方法中調(diào)用。

XML-RPC請求中的元素將會在下列類中被解析:

 
 
 
  1. org.apache.xmlrpc.parser.XmlRpcRequestParser 
  2.  
  3. org.apache.xmlrpc.parser.RecursiveTypeParserImpl 
  4.  
  5. org.apache.xmlrpc.parser.MapParser 

不安全的序列化問題存在于org.apache.xmlrpc.parser.SerializableParser類的getResult()方法之中。一個未經(jīng)身份驗(yàn)證的遠(yuǎn)程攻擊者可以利用該漏洞來發(fā)送包含了定制XML Payload的惡意HTTP請求。由于OFBiz使用了存在漏洞的Apache Commons BeanUtils庫和Apache ROME庫,攻擊者將能夠使用ysoserial工具以XML格式來構(gòu)建惡意Payload。該漏洞的成功利用將導(dǎo)致攻擊者在目標(biāo)應(yīng)用程序中實(shí)現(xiàn)任意代碼執(zhí)行。

源代碼分析
下列代碼段取自Apache OFBiz v17.12.03版本,并添加了相應(yīng)的注釋。

org.apache.ofbiz.webapp.control.RequestHandler:

 
 
 
  1. public void doRequest(HttpServletRequest request, HttpServletResponse response, String chain, 
  2.  
  3. GenericValue userLogin, Delegator delegator) throws RequestHandlerException, 
  4.  
  5. RequestHandlerExceptionAllowExternalRequests { 
  6.  
  7.     ConfigXMLReader.RequestResponse eventReturnBasedRequestResponse; 
  8.  
  9.     if (!this.hostHeadersAllowed.contains(request.getServerName())) { 
  10.  
  11.       Debug.logError("Domain " + request.getServerName() + " not accepted to prevent host header injection ", module); 
  12.  
  13.       throw new RequestHandlerException("Domain " + request.getServerName() + " not accepted to prevent host header injection "); 
  14.  
  15.     }   
  16.  
  17.     boolean throwRequestHandlerExceptionOnMissingLocalRequest = EntityUtilProperties.propertyValueEqualsIgnoreCase("requestHandler", "throwRequestHandlerExceptionOnMissingLocalRequest", "Y", delegator); 
  18.  
  19.     long startTime = System.currentTimeMillis(); 
  20.  
  21.     HttpSession session = request.getSession(); 
  22.  
  23.     ConfigXMLReader.ControllerConfig controllerConfig = getControllerConfig(); 
  24.  
  25.     Map requestMapMap = null; 
  26.  
  27.     String statusCodeString = null; 
  28.  
  29.     try { 
  30.  
  31.       requestMapMap = controllerConfig.getRequestMapMap(); 
  32.  
  33.       statusCodeString = controllerConfig.getStatusCode(); 
  34.  
  35.     } catch (WebAppConfigurationException e) { 
  36.  
  37.       Debug.logError((Throwable)e, "Exception thrown while parsing controller.xml file: ", module); 
  38.  
  39.       throw new RequestHandlerException(e); 
  40.  
  41.     } 
  42.  
  43.     if (UtilValidate.isEmpty(statusCodeString)) 
  44.  
  45.       statusCodeString = this.defaultStatusCodeString; 
  46.  
  47.     String cname = UtilHttp.getApplicationName(request); 
  48.  
  49.     String defaultRequestUri = getRequestUri(request.getPathInfo()); 
  50.  
  51.     if (request.getAttribute("targetRequestUri") == null) 
  52.  
  53.       if (request.getSession().getAttribute("_PREVIOUS_REQUEST_") != null) { 
  54.  
  55.         request.setAttribute("targetRequestUri", request.getSession().getAttribute("_PREVIOUS_REQUEST_")); 

org.apache.ofbiz.webapp.event.XmlRpcEventHandler:

 
 
 
  1. public void execute(XmlRpcStreamRequestConfig pConfig, ServerStreamConnection pConnection) throws XmlRpcException { 
  2.  
  3.     try { 
  4.  
  5.         ByteArrayOutputStream baos; 
  6.  
  7.         OutputStream initialStream; 
  8.  
  9.         Object result = null; 
  10.  
  11.         boolean foundError = false; 
  12.  
  13.         try (InputStream istream = getInputStream(pConfig, pConnection)) { 
  14.  
  15.             XmlRpcRequest request = getRequest(pConfig, istream); 
  16.  
  17.             result = execute(request); 
  18.  
  19.         } catch (Exception e) { 
  20.  
  21.             Debug.logError(e, module); 
  22.  
  23.             foundError = true; 
  24.  
  25.         } 
  26.  
  27.         if (isContentLengthRequired(pConfig)) { 
  28.  
  29.             baos = new ByteArrayOutputStream(); 
  30.  
  31.             initialStream = baos; 
  32.  
  33.         } else { 
  34.  
  35.             baos = null; 
  36.  
  37.             initialStream = pConnection.newOutputStream(); 
  38.  
  39.         }   
  40.  
  41.         try (OutputStream ostream = getOutputStream(pConnection, pConfig, initialStream)) { 
  42.  
  43.             if (!foundError) { 
  44.  
  45.                 writeResponse(pConfig, ostream, result); 
  46.  
  47.             } else { 
  48.  
  49.                 writeError(pConfig, ostream, new Exception("Failed to read XML-RPC request. Please check logs for more information")); 
  50.  
  51.             } 
  52.  
  53.         } 
  54.  
  55.         if (baos != null) 
  56.  
  57.         try (OutputStream dest = getOutputStream(pConfig, pConnection, baos.size())) { 
  58.  
  59.             baos.writeTo(dest); 
  60.  
  61.         } 
  62.  
  63.         pConnection.close(); 
  64.  
  65.         pConnection = null; 
  66.  
  67.     } catch (IOException e) { 
  68.  
  69.         throw new XmlRpcException("I/O error while processing request: " + e.getMessage(), e); 
  70.  
  71.     } finally { 
  72.  
  73.         if (pConnection != null) 
  74.  
  75.         try { 
  76.  
  77.             pConnection.close(); 
  78.  
  79.         } catch (IOException e) { 
  80.  
  81.             Debug.logError(e, "Unable to close stream connection"); 
  82.  
  83.         } 
  84.  
  85.     } 
  86.  
  87.  
  88.   
  89.  
  90. protected XmlRpcRequest getRequest(final XmlRpcStreamRequestConfig pConfig, InputStream pStream) throws XmlRpcException { 
  91.  
  92.     final XmlRpcRequestParser parser = 
  93.  
  94.     new XmlRpcRequestParser((XmlRpcStreamConfig)pConfig, getTypeFactory()); 
  95.  
  96.     XMLReader xr = SAXParsers.newXMLReader(); 
  97.  
  98.     xr.setContentHandler((ContentHandler)parser); 
  99.  
  100.     try { 
  101.  
  102.         xr.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true); 
  103.  
  104.         xr.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 
  105.  
  106.         xr.setFeature("http://xml.org/sax/features/external-general-entities", false); 
  107.  
  108.         xr.setFeature("http://xml.org/sax/features/external-parameter-entities", false); 
  109.  
  110.         //the parsing of XML in the HTTP body starts in this function 
  111.  
  112.         xr.parse(new InputSource(pStream)); 
  113.  
  114.         //truncated 
  115.  
  116.     } 
  117.  

org.apache.xmlrpc.parser.XmlRpcRequestParser:

 
 
 
  1. public void endElement(String pURI, String pLocalName, String pQName) throws SAXException { 
  2.  
  3.     //XML-RPC parsing happens here 
  4.  
  5.     switch(--level) { 
  6.  
  7.         case 0: 
  8.  
  9.             break; 
  10.  
  11.         case 1: 
  12.  
  13.             if (inMethodName) { 
  14.  
  15.                 if ("".equals(pURI) && "methodName".equals(pLocalName)) { 
  16.  
  17.                     if (methodName == null) { 
  18.  
  19.                         methodName = ""; 
  20.  
  21.                         } 
  22.  
  23.                     } else { 
  24.  
  25.                         throw new SAXParseException("Expected /methodName, got " + new QName(pURI, pLocalName), getDocumentLocator()); 
  26.  
  27.                         }   
  28.  
  29.                     inMethodName = false; 
  30.  
  31.                 } else if (!"".equals(pURI) || !"params".equals(pLocalName)) { 
  32.  
  33.                     throw new SAXParseException("Expected /params, got " + new QName(pURI, pLocalName), getDocumentLocator()); 
  34.  
  35.                 } 
  36.  
  37.                 break; 
  38.  
  39.             case 2: 
  40.  
  41.                 if (!"".equals(pURI) || !"param".equals(pLocalName)) { 
  42.  
  43.                     throw new SAXParseException("Expected /param, got " + new QName(pURI, pLocalName), getDocumentLocator()); 
  44.  
  45.                 } 
  46.  
  47.                 break; 
  48.  
  49.             case 3: 
  50.  
  51.                 if (!"".equals(pURI) || !"value".equals(pLocalName)) { 
  52.  
  53.                     throw new SAXParseException("Expected /value, got " + new QName(pURI, pLocalName), getDocumentLocator()); 
  54.  
  55.                 } 
  56.  
  57.                 endValueTag(); 
  58.  
  59.                 break; 
  60.  
  61.             default: 
  62.  
  63.                 super.endElement(pURI, pLocalName, pQName); 
  64.  
  65.                 break; 
  66.  
  67.          }   
  68.  

org.apache.xmlrpc.parser.SerializableParser:

 
 
 
  1. public class SerializableParser extends ByteArrayParser { 
  2.  
  3.     public Object getResult() throws XmlRpcException { 
  4.  
  5.         try { 
  6.  
  7.             byte[] res = (byte[]) super.getResult(); 
  8.  
  9.             ByteArrayInputStream bais = new ByteArrayInputStream(res); 
  10.  
  11.             ObjectInputStream ois = new ObjectInputStream(bais); 
  12.  
  13.      
  14.  
  15.             //insecure deserialization happens here 
  16.  
  17.             return ois.readObject(); 
  18.  
  19.         } catch (IOException e) { 
  20.  
  21.             throw new XmlRpcException("Failed to read result object: " + e.getMessage(), e); 
  22.  
  23.         } catch (ClassNotFoundException e) { 
  24.  
  25.             throw new XmlRpcException("Failed to load class for result object: " + e.getMessage(), e); 
  26.  
  27.         } 
  28.  
  29.     }   
  30.  

為了觸發(fā)該漏洞,攻擊者需要以XML格式在HTTP請求中攜帶定制的序列化對象,并發(fā)送給存在漏洞的目標(biāo)應(yīng)用程序,當(dāng)服務(wù)器端在序列化XML數(shù)據(jù)時,便會觸發(fā)該漏洞。


文章名稱:APACHE OFBIZ XMLRPC遠(yuǎn)程代碼執(zhí)行漏洞分析
文章轉(zhuǎn)載:http://m.5511xx.com/article/cdieice.html