PHP2Shell、LiteLLM、GitLab 等多項安全漏洞曝光,讀者需即時修補
PHP2Shell, LiteLLM, GitLab: Find What You Need to Patch
導語:本週 PHP、Node.js、GitLab、LiteLLM 等多個熱門開發環境曝出高危漏洞,攻擊者已在公開前嘗試利用,讀者需盡速確認環境並升級。
本週多項關鍵漏洞曝光,讀者可快速掌握評估與修補流程,並瞭解漏洞利用視窗縮短的趨勢,保障系統安全。
在 2026 年 10 月 16 日至 23 日之間,PHP、Node.js、GitLab、LiteLLM、OpenCode 與 eMudhra 證書授權機構皆發生嚴重安全事件。PHP、Node.js 與 GitLab 於 10 月 21 日發布修補程式,當日同時釋出惡意 LiteLLM 版本。每則安全公告皆以升級、重建或輪換作為結束。
執行升級是最簡單的步驟。真正耗時的是為自己的帳號確認受影響的專案在哪裡執行、誰擁有以及它能夠存取什麼。若你擁有可靠的資產清單,這只需一個下午;若沒有,則需一週的 Slack 互動,而這週並未給任何人一週。Amazon 的 MadPot 蜜罐紀錄了 PHP2Shell 的利用嘗試 在漏洞公佈前四天。
本週事件
| 事件 | 發生了什麼 | 修正 | 你必須查明的事項 |
|---|---|---|---|
| PHP2Shell (CVE-2026-109618, CVE-2026-109619) | PHP 中有兩個在未驗證前的遠端程式碼執行漏洞,兩者 CVSS 分數均為 9.2。利用嘗試在漏洞公佈前已發生。 | PHP 8.5.12、8.4.27、8.3.36 或 8.2.35。臨時設定迴避方案 並未涵蓋所有變體,因此升級是唯一完整的修復方法。 | 哪些例項、容器和 App Service 應用執行 PHP,以及哪些使用 8.1 或更舊版本? |
| Node.js (CVE-2026-111497) | Bundled Brotli 解碼器中的越界寫入,可能導致崩潰、記憶體洩露或遠端程式碼執行,並附帶九項其他修補。 | 22.23.4、24.22.1 或 26.12.1。已停止支援的版本不會收到修補。 | 哪些 Lambda 函式、容器和虛擬機器執行 Node.js,以及哪些使用 20.x 或更舊版本? |
| GitLab (CVE-2026-110264) | 未經驗證的遠端程式碼執行,CVSS 分數 10.0,透過 GitLab 正規表示式編譯器的整數溢位。漏洞可回溯至 2014 年發布的 GitLab 7.0。 | 10 月 21 日發布補丁。自託管例項無可用迴避方案。 | 是否存在被人遺忘的自託管 GitLab,且網際網路能否存取? |
| LiteLLM 1.107.0 (Microsoft’s analysis) | PyPI 與官方容器映像中的惡意版本在 Python 啟動時執行憑證竊取程式。 | 從已驗證版本重新建置,然後輪換所有環境可存取的憑證。 | 它在哪執行、以何身份執行,以及該身份可存取什麼? |
| OpenCode Console (TechCrunch) | 攻擊者存取了遺留系統,且使用者在 Console 儲存的 AI 供應商金鑰可能已被洩露。一些使用者報告了未授權的費用。 | 撤銷並重新發行金鑰。 | 該金鑰還存於何處,且在撤銷時哪些工作負載會失效? |
| eMudhra (The Register) | 八個中介 CA 私鑰是小於 256 的整數。其中一個是數字 4。 | 瀏覽器 封鎖了中介憑證。 | 我們是否持有此鏈的憑證,且我們的映像仍信任它? |
清單中沒有任何隱蔽專案。兩個是大量網站所使用的執行環境,一個是許多公司仍自行託管的原始碼控制伺服器,另一個是許多團隊急於路由 LLM 流量而採用的 AI 閘道。若你在 AWS 或 Azure 上運營相當規模的環境,至少其中一項可能是你需要處理的。
利用視窗持續縮短
Mandiant 追蹤攻擊者在漏洞公開後多久才利用該漏洞。其 利用時間分析 顯示,2018–2019 年平均為 63 天,2020–2021 年為 44 天,2021–2022 年為 32 天。2023 年為五天,且 Mandiant 追蹤的被利用漏洞中有 70% 為零日漏洞,於修補程式發布前已被利用。
Drew Silcock 的貼文 這是新的網路常態嗎?,於 10 月 23 日登上 Hacker News 首頁,主張 LLM 已進一步縮短此間距,因而惡意 RCE 變得公開與對其進行自動化攻擊之間的時間差現在是數小時而非數週。PHP2Shell 正好符合。這些漏洞是 在 AI 模型協助下發現,已修補的二進位檔案 在公告前出現,在禁運爭議之後,且攻擊嘗試在大多數人能安裝修補程式之前就已開始。
您的曝露視窗是找出受影響專案所需時間加上修復所需時間。大多數團隊已經花了多年時間透過 CI/CD、受管執行環境和自動修補來縮短後者。前者仍是試算表、Slack 會話,還有記得舊 GitLab 伺服器如何設定的人。
這也是為什麼框架會優先列出清單。CIS Controls 要求先列出企業資產與軟體清單(Controls 1 與 2);漏洞管理直到 Control 7 才出現。CISA 的 BOD 23-01 要求美國聯邦機構每七天執行一次自動資產偵測,每十四天執行一次漏洞列舉。若您不知道伺服器存在,您就無法修補它。
使用原生工具處理公告
以下是我如何使用 AWS 與 Azure 的即時功能回答這些問題,並以本週的事件為例。以下所有命令均為唯讀。
1. 它執行於哪裡
從 Node.js 開始。在 Lambda 上,受支援的受管執行環境 會自動取得執行環境更新,預設如此,因此大多數使用目前 Node.js 執行環境的函式會在不重新部署的情況下接收修補。兩個群組不會。使用已棄用的 nodejs20.x 執行環境的函式 在 Node.js 20 於 2026 年 4 月到達生命週期結束時停止接收安全修補。以容器映像部署的函式則攜帶映像中所編譯的 Node.js。您實際需要的是舊執行環境或打包成映像的函式清單:
# Node.js and container-image Lambda functions in every enabled region
for region in $(aws ec2 describe-regions --query "Regions[].RegionName" --output text); do
echo "== $region"
aws lambda list-functions --region "$region" \
--query "Functions[?PackageType=='Image' || (Runtime && starts_with(Runtime, 'nodejs'))].[FunctionName, Runtime || PackageType]" \
--output text
done映像檔式函式會出現在該輸出中,因為 Lambda API 無法告知您其內部內容。對於這些,您需要映像掃描器,或重新編譯。
在 Azure 上的 PHP2Shell,App Service 會記錄每個 Linux 應用程式的執行堆疊,Azure Resource Graph 可以在您可讀取的所有訂閱中搜尋:
az graph query -q "
resources
| where type =~ 'microsoft.web/sites'
| mv-expand setting = properties.siteProperties.properties
| where setting.name =~ 'LinuxFxVersion' and tostring(setting.value) startswith 'PHP'
| project name, resourceGroup, subscriptionId, stack = tostring(setting.value)
" --first 1000 -o table任何使用 PHP 8.1 或更舊版本的環境都不會收到常規上游修補,請將其排在清單最上方。
虛擬機器與容器更難,因為雲端控制平面不知道它們安裝了什麼。這正是 AWS Systems Manager Inventory、Amazon Inspector 與 Microsoft Defender for Cloud 的用途,每個工具僅能看到已啟用的機器。這個覆蓋缺口是最痛苦的,我會再回到這個話題。
2. 網際網路是否能夠連線到它
GitLab 已修補 GitLab.com 本身。自託管例項由您負責,若不升級則無法解決。令我擔憂的並非平臺團隊運營的 GitLab。它是某個團隊於 2019 年建立的,或是隨著併購而來的,仍在 443 埠上回應。
先按名稱與標籤搜尋,然後檢視曝露情況:
# Instances that look like GitLab, with public IPs and security groups
aws ec2 describe-instances \
--filters "Name=tag:Name,Values=*gitlab*,*GitLab*" \
--query "Reservations[].Instances[].[InstanceId, State.Name, PublicIpAddress, join(',', SecurityGroups[].GroupId)]" \
--output text
# Security groups with an inbound rule open to the whole internet
aws ec2 describe-security-groups \
--filters Name=ip-permission.cidr,Values=0.0.0.0/0 \
--query "SecurityGroups[].[GroupId, GroupName, VpcId]" \
--output text在 Azure 中,az vm list -d --query "[?contains(name, 'gitlab')].{name:name, rg:resourceGroup, ips:publicIps}" -o table 會得到相同的第一次通過。
請小心這些訊息所告訴你的內容。名稱過濾器只能找到有人真實命名的伺服器,而沒有公共 IP 的例項仍可能透過公共負載平衡器被存取。這兩點都使得在事故發生時於控制台直接回答變得困難。若你已經擁有能夠呈現關係的資產清單,則會容易許多。
3. 誰擁有它
找到伺服器後,必須有人批准停機,理想情況下該人應該知道其安裝方式。標籤是首要檢視之處。若沒有標籤,CloudTrail 可以告訴你誰建立了該資源:
aws cloudtrail lookup-events \
--lookup-attributes AttributeKey=ResourceName,AttributeValue=i-0abc123example \
--query "Events[].[EventTime, EventName, Username]" \
--output table事件歷史僅可追溯 90 天,Azure 活動記錄亦同。對於 2019 年的伺服器,你需要在 S3 中保留追蹤紀錄並使用 Athena 查詢,Who Created This AWS Resource? 會說明流程。即便如此,建立者可能已離職。在 我們檢視的一個案例 中,89 臺閒置的 Azure VM 來自一次收購,現任團隊無人能說明其用途。這類資源正是未修補的 GitLab 可能停留的地方。
4. 它能存取的範圍
LiteLLM 展示了為何僅偵測到套件即為起點。根據 Microsoft 的分析,惡意版本針對 AWS、Azure 與 Google Cloud 的憑證快取、Kubernetes 服務帳戶檔案、Docker 設定與掛載的秘密進行攻擊。它亦嘗試從 AWS 與 GCP 的 metadata 服務拉取憑證,並在代理主機上從 LiteLLM 自身資料庫讀取供應商金鑰。
惡意套件即為掃描器報告的內容。你實際需要回應的是主機執行的身分。對於每個安裝了 1.107.0 的環境,先找出其所擁有的角色以及該角色允許執行的操作:
# The instance profile behind an EC2 instance
aws ec2 describe-instances --instance-ids i-0abc123example \
--query "Reservations[].Instances[].IamInstanceProfile.Arn" --output text
# The role inside that profile, and the policies attached to it
aws iam get-instance-profile --instance-profile-name litellm-proxy \
--query "InstanceProfile.Roles[].RoleName" --output text
aws iam list-attached-role-policies --role-name litellm-proxy-role
aws iam list-role-policies --role-name litellm-proxy-role在 ECS 上,身分即為工作定義中的任務角色;在 EKS 上則為對應至 pod 服務帳戶的角色。Microsoft 的建議是從乾淨機器進行調查,從已驗證的產物重建,旋轉所有可存取的憑證,並以 digest 鎖定容器映像,而非使用漂浮標籤如 latest。我特別強調乾淨機器的部分:他們的分析指出,payload 在 Python 啟動時執行,於可疑環境中執行 pip 檢查套件可能會觸發它。
5. 秘密或憑證可能存放的其他位置
OpenCode 建議使用者撤銷並重新發行已曝光的金鑰。撤銷只需點選一次。真正的工作是找出撤銷後會中斷哪些功能,因為 AI 供應商金鑰會存於 Secrets Manager 或 Key Vault、Lambda 與 App Service 設定、CI 變數以及開發者的 .env 檔案中。在 AWS 上,Secrets Manager 至少會記錄每個秘密最後一次被讀取與旋轉的時間,而 CloudTrail 的 GetSecretValue 事件則顯示哪些角色讀取了它:
aws secretsmanager list-secrets \
--query "SecretList[].[Name, LastAccessedDate, LastRotatedDate]" \
--output tableeMudhra 對憑證提出相同問題。若私鑰僅此大小,任何人都能計算出來並簽署瀏覽器曾信任的憑證,直到中介憑證被封鎖。值得執行兩項檢查。首先,搜尋你已匯入的憑證中是否有 eMudhra 或 emSign 發行者。ACM 具區域性,CloudFront 使用的憑證位於 us-east-1,請於你使用的每個區域(包括 us-east-1)執行此項:
for arn in $(aws acm list-certificates \
--includes keyTypes=RSA_2048,RSA_3072,RSA_4096,EC_prime256v1,EC_secp384r1,EC_secp521r1 \
--query "CertificateSummaryList[].CertificateArn" --output text); do
aws acm describe-certificate --certificate-arn "$arn" \
--query "Certificate.[DomainName, Issuer, Type]" --output text
done | grep -i -E "emudhra|emsign"在 Azure 中,Resource Graph 可覆蓋跨訂閱的 App Service 憑證:
az graph query -q "
resources
| where type =~ 'microsoft.web/certificates'
| where tostring(properties.issuer) contains 'emSign' or tostring(properties.issuer) contains 'eMudhra'
| project name, resourceGroup, subscriptionId, issuer = tostring(properties.issuer), expires = properties.expirationDate
" -o table其次,內建信任庫的軟體會持續信任該 CA,直到信任庫被更新。舊版 AMI、基礎映像與執行環境若內含自訂 CA 列表,則被封鎖的鏈條仍會在瀏覽器放棄後繼續運作很久。
掃描器與控制台的終點
Amazon Inspector 和 Defender for Cloud 能很好地告訴你在特定機器上某個套件版本是否易受攻擊。AWS 與 Azure 控制台則能告知你某個帳號在某個區域內的內容。當安全建議一釋出時,這兩者都無法滿足你的需求。
第一個問題是覆蓋範圍。掃描器能看到已啟用的帳號、訂閱與機器,而從併購來的 GitLab 伺服器通常停留在沒有人加入的帳號中。第二個問題是擁有權。發現會落到共享佇列,沒有人有權重新啟動別人的伺服器,因此它們就會一直停留。沒有附加擁有者的發現只是一個額外的警示。第三個問題是上下文。掃描器只說套件有問題,卻不說主機角色能存取帳號內所有 S3 bucket,或是三個其他團隊的服務會呼叫它。使用 LiteLLM 時,這些上下文佔了事件的大部分。
填補這些空白的是一個始終保持最新、記錄現有資源、擁有者以及它與其他所有東西連結的清單。這正是我們正在打造 Cloud Sleuth 的目的。
在 Cloud Sleuth 中的實際樣貌
Cloud Sleuth 會對映你的 AWS 與 Azure 資源,無論是否標記都為每項資源指派擁有者,並保持兩者同步更新。以下是以 Cloud Sleuth 設計方式回答的 GitLab 問題。
示範範例 - 指令與輸出尚未定稿:
$ sleuth ask "gitlab servers the internet can reach, and who owns them"
ec2 scm-legacy-01 account acquired-prod · eu-west-1
image GitLab CE 13.12 AMI, launched 2021-06-02
exposure internet → alb-scm (public) → target group scm-https → :443
owner team-devex confidence 88%
created by role/terraform-ci (CloudTrail, 2021-06-02)
managed by github.com/acme/legacy-infra (terraform state)
role scm-legacy-instance → read on 4 S3 buckets, 2 secrets
findings no owner tag · public ingress那個結果涵蓋了暴露、擁有權與可達性:伺服器、從網際網路到它的路徑、與該答案相關的證據以及團隊,還有伺服器角色能觸及的範圍。有了它,你就不必在四個控制台和一次 CloudTrail 搜尋中重複這一切,亦不必為每個帳號(包括併購來的帳號)重複操作。
庫存搜尋 將 AWS 與 Azure 資源放入一個可用 SQL 或簡易英文查詢的結構,因而上述逐區域 Lambda 迴圈可改為一次跨兩雲端、已附上擁有者的查詢:
示範範例 - schema 尚未定稿:
select cloud, account, type, name, runtime, owner
from resources
where runtime in ('nodejs18.x', 'nodejs20.x')
order by owner;雲端地圖 會從實際帳號中繪製網路路徑、負載平衡器目標、附件與 IAM 關係,讓你能在開始輪替前,先看到遺忘伺服器前方的環境以及其角色可存取的範圍。擁有權模型 會從 CloudTrail 與 Azure 活動記錄、IaC 狀態、命名與帳號結構推斷擁有者,並顯示信心分數與相應證據。守門檻 會標示未擁有、未標記與孤立資源,在 Cloud Sleuth 中,雲端發現可被導向擁有團隊的 Slack 或 Jira,並持續執行自訂政策,例如「不允許在已棄用的執行環境上部署函式」。此外還有隻讀的 MCP 伺服器,因此在事件發生時,你可以詢問像 Claude 或 Cursor 這類代理「我們哪些函式執行 Node.js 20,且誰擁有它們?」
鑒於本週出現供應商控制台洩露客戶存放的金鑰,以及熱門套件傳送憑證竊取程式,信任模型變得重要。Cloud Sleuth CLI 預設為只讀,並不會在你的伺服器上安裝任何程式,且可在你的機器或 VPC 中執行。若你想試用,加入早期使用者名單。
一小時演練
請挑選本週的安全公告之一,並測量您的團隊完成以下任務所需的時間。列出 Node.js 與 PHP 執行的所有環境,包括 Lambda 執行時、App Service 堆疊、容器映像與虛擬機器。尋找所有自行管理的 GitLab,以及任何其他自託管的開發工具,並檢查是否可被網際網路存取。於每項旁邊標註負責人姓名。若任何環境安裝了 LiteLLM 1.107.0,請列出其執行的角色並輪換該角色可存取的所有資源。寫下 AI 供應商金鑰存放位置及使用它們的工作負載。搜尋您的憑證,尋找 eMudhra 或 emSign 之簽發者。
如果這花費超過一小時,請預期下一則安全公告也大約需要同樣時間。
常見問題
我的 AWS Lambda 函式是否受 Node.js Brotli 漏洞影響?
僅當程式碼使用 node:zlib 從不受信任的來源解壓 Brotli 資料時才會暴露。Lambda 會預設自動為受支援的管理執行時推出執行時更新,且函式日誌中的 INIT_START 行顯示其執行的執行時版本。已棄用的 nodejs20.x 執行時不再收到安全修補程式,容器映像函式則載入映像內的 Node.js 版本,請升級或重新建置。
GitLab.com 是否受 CVE-2026-110264 影響?
GitLab 已修補 GitLab.com 及 GitLab Dedicated 本身,並且發行說明指出兩者已在執行已修補的版本。自行管理的 GitLab Community 與 Enterprise Edition 例項須升級至已修補版本。沒有可行的變通方法。
如果環境安裝了 LiteLLM 1.107.0,我該怎麼辦?
將其視為已被入侵。請於乾淨機器上進行調查,從已驗證的版本重新建置,確認 cook.pth、cook.py 與 sitecustomize.py 已不在 Python 函式庫路徑中,並輪換環境可存取的所有憑證:雲端角色、CI/CD 秘密、SSH 金鑰及模型供應商金鑰。Microsoft 的分析列出了搜尋指標。
當新漏洞被公佈時,Cloud Sleuth 如何協助?
它回答了決定您能多快回應的問題:您的 AWS 與 Azure 資源中哪些在範圍內,哪些可被網際網路存取,誰負責每一項,以及每一項能存取什麼。擁有者附帶證據,確保修正指派給能真正執行的團隊。CLI 以唯讀方式在您的機器上執行,您現在可 加入早期存取名單。