2026年10月、Ivanti Connect Secure(ICS)の脆弱性が3件、米CISAの悪用済み脆弱性カタログ(KEV)に載りました。10月13日のCVE-2026-104935に続き、30日にCVE-2026-111357とCVE-2026-118527が加わっています。このうち少なくとも2件は1本の攻撃に組み合わされ、認証なしで機器のroot権限まで奪われました。この記事では、連鎖の仕組み、自社の版が対象かを判定するスクリプト、Integrity Checkerでは見えない侵害の調べ方、Active Directoryの資格情報の入れ替え、22.x系の終了を踏まえた移行の判断までを、実装と運用の目線で整理しました。内容は2026年10月31日時点の公開情報にもとづきます。
まとめ:10月13日の更新だけでは足りず、侵害の調査とADの入れ替えまで進める
10月13日に出た修正版(22.8R2.5や25.1.1.2)で塞がるのは、認証回避と任意コードの実行までです。root昇格のCVE-2026-111357は10月29日に別の修正が出ており、NVDの構成情報では22.8R2.5と25.1.1.2も対象に入っています。13日に急いで更新した機器も、もう一度上げてください。
攻撃者は痕跡をログから消し、Ivantiの整合性チェックにも映らない手口を使いました。10月3日以降に影響版をインターネットへ公開していたなら、更新だけで終えず、侵害を前提に調べます。ICSが使うADのサービスアカウント、Kerberoastの対象になりうるアカウント、LAPSのパスワードは入れ替えの候補です。
22.x系は2027年1月31日にサポートが終わります。今回の再更新を機に25.1.3系へ移る組織が多くなるはずです。社外に開いたVPN機器の版と設定をまとめて点検する場合は、脆弱性診断・セキュリティ診断で範囲を決めると抜けが出にくくなります。
10月に悪用された3件の中身:認証回避からroot昇格までの連鎖
発見したのは米Volexityです。Volexityの報告によれば、10月5日に顧客のネットワークで調査を始め、当時の最新版22.8R2.4(Build 19097)のICSが侵入口だと突き止めました。攻撃者はUTA0576と名付けられ、10月3日から繰り返し悪用していたとされます。
welcome.cgiとwu.cgiの認証回避・競合状態とコード実行
CVE-2026-104935の1段目は、welcome.cgiを使った認証の回避です。ログイン画面を返す公開スクリプト/dana-na/auth/url_default/welcome.cgiへ要求を送り、ヘッダX-DSCGI-PATHに認証が必要な別のスクリプトを書きます。ICSは許可の判定にURLを、転送先の決定にヘッダを使っていたため、要求は認証なしで奥のスクリプトへ届きました。
2段目はファイル書き込みです。wu.cgiのアップロード処理は、受け取ったファイルをファイル名のMD5で決まるパスへ先に書き、ZIPでなければ後から消します。消されるまでの一瞬に、同じヘッダの手口で書いたPerlスクリプトを並列に呼び出すと、コードが動きます。Ivantiはこの2つをまとめてCVE-2026-104935として扱いました。
NVDの登録では、Ivanti自身が付けたCVSS v3.1の基本値は8.6、弱点の分類はCWE-290(なりすましによる認証回避)です。説明文には「22.7R2.14以前は影響を受けない」とあります。
dsinvokedとDSCacheのroot昇格とCVSS値の相違
CVE-2026-111357に当たる3段目では、dsinvokedとDSCacheを介してroot権限まで上げます。ICSにはroot権限で保守作業を動かすdsinvokedというサービスがあり、作業ごとにどのプログラムを動かすかを共有設定のDSCacheから読みます。攻撃者はメモリ上のライブラリを書き換えてDSCacheの作業定義をPerlの起動に差し替え、dsinvokedに悪意のあるスクリプトをrootで実行させました。
NVDのCVE-2026-111357は、説明文に「2026年10月に実際に悪用された」と明記しています。採番したのはMITREで、CVSSは7.0(攻撃元区分がローカル)、分類はCWE-829(信頼できない領域の機能の取り込み)です。国内の報道には8.8とするものがあり、評価者によって値が割れています。単独では手元の権限が要る欠陥でも、1段目と2段目でその権限が手に入るため、点数の低さを理由に後回しにはできません。各指標の読み方はCVSSv3の計算式とスコアの目安で確認できます。
名称だけが先にKEVへ載ったCVE-2026-118527と11月13日の期限
CVE-2026-118527は、10月31日の時点でNVDにもCVEの公開記録にもまだありません。手がかりはCISAのKEVカタログの名称「予測可能な数値または識別子の生成」だけです。参照先には、CVE-2026-104935と同じIvantiの勧告が挙がっています。
2段目で書き込み先のパスがファイル名のMD5で決まり、攻撃者が事前に計算できた点は、この名称と符合します。ただし対応関係をIvantiが示した資料は確認できておらず、これは私たちの推定です。分類としてはCWE-340が近い内容です。
| CVE | 中身 | CVSS | KEV追加 | KEV期限 |
|---|---|---|---|---|
| CVE-2026-104935 | 認証回避と任意コード実行 | 8.6 | 10月13日 | 10月16日 |
| CVE-2026-111357 | root昇格 | 7.0(NVD) | 10月30日 | 11月2日 |
| CVE-2026-118527 | 予測可能な識別子 | 未公開 | 10月30日 | 11月13日 |
期限が3日のものと14日のものが混ざっているのは、KEVの期限を危険度から決める方式に変わったためです。期限の決まり方はBOD 26-04の是正期限の決まり方で解説しています。
自社のICSが対象かを版で判定する:Ivantiの修正版とNVDの構成情報
ICSの版は「22.8R2.4」と「25.1.1.2」の2つの書式が並び、取り違えが起きやすい製品です。Ivantiの公表とNVDの構成情報(CPE)の両方で判定します。
修正版25.1.1.2・25.1.3系・22.8R2.5とroot昇格の残存
CVE-2026-104935の修正版は、Ivantiの10月のPatch Tuesday解説に25.1.1.2、25.1.3.0、25.1.3.1、22.8R2.5と書かれています。10月のセキュリティ更新の告知は、修正版への更新とあわせてIntegrity Checker Toolを定期的に動かすよう求めています。
CVE-2026-111357は事情が違います。NVDが10月31日に更新したCPEでは、25.1.0.0以上25.1.1.3未満と、22.8R2から22.8R2.5までが対象です。つまり13日の修正版のうち、22.8R2.5と25.1.1.2はまだ対象に残ります。複数の報道は修正版を25.1.1.3と22.8R2.6としていますが、Ivantiの勧告で版名を確かめてから作業してください。
| いまの版 | CVE-2026-104935 | CVE-2026-111357 | 判断 |
|---|---|---|---|
| 22.8R2.4以前の22.8R2系 | 対象 | 対象 | 至急更新 |
| 22.8R2.5 | 対象外 | 対象 | 再更新 |
| 25.1.1.1以前 | 対象 | 対象 | 至急更新 |
| 25.1.1.2 | 対象外 | 対象 | 再更新 |
| 25.1.2系 | 対象 | CPEに無し | 25.1.3系へ |
| 25.1.3.0・25.1.3.1 | 対象外 | CPEに無し | 勧告で確認 |
CPEはNISTの解析結果で、ベンダーの表と食い違うことがあります。「CPEに無し」は対象外の保証ではありません。22.7R2系もCVE-2026-111357のCPEには出てこないため、勧告の記載を見て判断します。
NVDのCPEで版を照合するPythonスクリプトと出力の読み方
台数が多いときは、NVDのAPIから構成情報を取り、資産台帳の版を流し込んで判定します。機器には接続しません。
import json
import re
import sys
import time
import urllib.request
CVES = ["CVE-2026-104935", "CVE-2026-111357"]
NVD = "https://services.nvd.nist.gov/rest/json/cves/2.0?cveId="
def nums(text):
# "22.8R2.4" や "25.1.1.2" を数値の組に分ける(文字列のまま比べない)
return tuple(int(n) for n in re.findall(r"\d+", text))
def cpe_version(criteria):
# cpe:2.3:a:ivanti:connect_secure:22.8:r2.4:... を "22.8R2.4" に戻す
parts = criteria.split(":")
ver, upd = parts[5], parts[6]
if ver == "*":
return None
return ver + (upd.upper() if upd not in ("*", "-") else "")
def hit(m, ver):
exact = cpe_version(m["criteria"])
if exact:
return nums(exact) == nums(ver)
v = nums(ver)
lo = m.get("versionStartIncluding")
hi = m.get("versionEndExcluding")
if lo and v < nums(lo):
return False
if hi and v >= nums(hi):
return False
return bool(lo or hi)
versions = sys.argv[1:] or ["22.8R2.4", "22.8R2.5", "25.1.1.2", "25.1.3.1"]
for cve in CVES:
req = urllib.request.Request(NVD + cve, headers={"User-Agent": "Mozilla/5.0"})
data = json.load(urllib.request.urlopen(req, timeout=30))
item = data["vulnerabilities"][0]["cve"]
matches = [m for c in item.get("configurations", [])
for n in c["nodes"] for m in n["cpeMatch"] if m["vulnerable"]]
print(cve, "NVD最終更新:", item["lastModified"][:10],
"KEV期限:", item.get("cisaActionDue", "未登録"))
for ver in versions:
flag = "対象" if any(hit(m, ver) for m in matches) else "対象外"
print(f" {ver:<10} {flag}")
time.sleep(6) # APIキー無しのNVDは30秒に5回まで
python ics_nvd_check.py 22.8R2.5 25.1.1.2 25.1.3.1 のように版を渡します。2026年10月31日に実行したところ、22.8R2.5と25.1.1.2はCVE-2026-104935で「対象外」、CVE-2026-111357で「対象」と出ました。「22.8R2.4」と「22.8R2.10」を文字列で比べると大小が逆になるため、数値の組に分けてから比べています。構成情報は後から直ることがあるため、作業の直前に取り直してください。
侵害の有無を確かめる:Integrity Checkerに映らない痕跡の探し方
更新は今後の侵入を防ぐだけです。10月3日以降に影響版を公開していた機器は、次の観点で調べます。
Integrity Checker Toolが今回の攻撃を検知できない理由とメモリ調査
Volexityによれば、攻撃者はroot権限を得たあと、書き換えたDSCacheの定義とメモリ上のライブラリを元に戻しています。ディスク上のファイルは変わらないため、ファイルの改変を見るIntegrity Checker Toolでは検知できません。さらに/home/runtime/dlogs/debuglogと/var/log/audit/audit.logから、該当時間帯の記録を選んで消していました。
Webシェルやバックドアも置かれていません。コマンドを打つたびに連鎖全体を最初から実行し、結果をHTTPの応答で受け取る方式でした。痕跡は主にメモリに残るため、Volexityはネットワークとメモリの両面からの調査を勧めています。外部に調査を頼むときの流れと費用はフォレンジック調査の流れと依頼先の選び方で確認できます。
welcome.cgiへの集中とX-DSCGI-PATHヘッダを前段のログで洗う手順
Volexityが挙げた監視の観点は、welcome.cgiへの大量の要求と、URLとX-DSCGI-PATHが別のスクリプトを指す要求です。ICSの前にWAFやロードバランサを置き、要求ヘッダを記録している構成なら、そのログで遡れます。次のPythonは、JSON Lines形式に書き出したアクセスログを読みます。
import collections
import json
import sys
WELCOME = "/dana-na/auth/url_default/welcome.cgi"
per_ip = collections.Counter()
for line in open(sys.argv[1], encoding="utf-8"):
rec = json.loads(line)
path = rec.get("path", "").split("?")[0]
headers = {k.lower(): v for k, v in rec.get("headers", {}).items()}
dscgi = headers.get("x-dscgi-path")
if path == WELCOME:
per_ip[rec.get("src_ip", "-")] += 1
if dscgi:
# URLとヘッダが別のスクリプトを指していれば、Volexityの言う不一致
mismatch = not dscgi.endswith(path.rsplit("/", 1)[-1])
print("要調査" if mismatch else "参考", rec.get("time"), rec.get("src_ip"),
path, "X-DSCGI-PATH=" + dscgi)
for ip, count in per_ip.most_common(5):
print("welcome.cgiへの要求回数", ip, count)
ログの項目名(path・headers・src_ip)は自社の機器に合わせて書き換えます。10月31日に、攻撃の要求2件と通常のログイン2件を入れたサンプルで実行し、攻撃の2件だけが「要調査」と出ることを確かめました。Volexityは、攻撃者が別のURLやヘッダの組み合わせを見つける可能性も指摘しています。wu.cgiの文字列だけで探すと取りこぼすため、不一致そのものを拾う形にしました。
VolexityのYARAルールとIOCの使い方と機器内に残るファイル名
VolexityのGitHubには、YARAルール2本とIOCが公開されています。1本目はX-DSCGI-PATH: /home/webserver/htdocs/dana/fb/smb/wu.cgiの文字列をファイルとメモリから探し、2本目は権限昇格に使われたPythonの断片をメモリから探します。IOCは攻撃に使われたIPアドレス108.165.147[.]64の1件です。
yara -s rules.yar ics_memory.lime
yara -r -s rules.yar ./ics_disk_image_mount/
機器内に作られたファイルは、/tmp配下のml.py・rq5.py・mk.py・rr.py・spray_hits.json、隠しディレクトリ/data/.icscap/のdsstatmond(名前を変えたtcpdump)です。多くは攻撃者が実行後に消しているため、無いことは安全の証明になりません。
侵害を前提にした事後対応:AD資格情報の入れ替えとLDAP通信の暗号化
UTA0576が狙ったのは、ICSの先にあるActive Directoryでした。Volexityは、LDAP接続用の資格情報の抜き取り、Kerberoast用ツールの設置、LAPSのパスワードとBitLocker回復キーの検索、パスワードスプレー、LDAP通信の盗聴を確認しています。
ICSのADサービスアカウントとSPN付きアカウントのパスワード変更順序
最初に変えるのは、ICSがADへ問い合わせるときに使うサービスアカウントです。攻撃者はこのアカウントでドメインコントローラへ接続し、高価値の属性を探していました。次がSPN(サービスプリンシパル名)を持つユーザーアカウントです。Kerberoastは、これらのアカウントのチケットを持ち帰ってパスワードを手元で解く攻撃です。
Import-Module ActiveDirectory
Get-ADUser -Filter 'ServicePrincipalName -like "*"' -Properties ServicePrincipalName, PasswordLastSet |
Sort-Object PasswordLastSet |
Select-Object SamAccountName, PasswordLastSet, @{n = 'SPN'; e = { $_.ServicePrincipalName -join ';' }}
Get-ADUserでSPN付きのユーザーを、パスワードの最終変更日が古い順に並べます。長いあいだ変えていない短いパスワードほど解かれやすいため、一覧の上から順に変更してください。ICSに設定したアカウントのパスワードを変えたら、ICSの認証サーバ設定も同時に直さないとVPNのログインが止まります。
LAPSのパスワードを即時に失効させるコマンドとBitLocker回復キーの扱い
LAPSのパスワードが読まれた可能性がある端末は、次の更新周期を待たずに失効させます。Set-LapsADPasswordExpirationTimeは、日時を省くと有効期限を現在時刻にし、パスワードをすぐに切らします。
Import-Module LAPS
Get-ADComputer -Filter 'OperatingSystem -like "Windows*"' |
ForEach-Object { Set-LapsADPasswordExpirationTime -Identity $_.Name }
公式の説明どおり、新しい期限が効くのは各端末が次にLAPSのポリシー処理を回したときです。端末が電源を落としている間は古いパスワードが残ります。BitLocker回復キーには一括で失効させる仕組みが無く、持ち出された場合は端末ごとに回復パスワードを作り直す作業になります。ADの情報が持ち出され、そこに従業員の個人データが含まれていたなら、個人情報保護委員会への報告義務と期限も確かめてください。
平文LDAPの盗聴を防ぐLDAPSと25.1.3.0のサーバ証明書検証の既定化
攻撃者は、ICSが流す389番ポートの通信を記録し、平文のLDAP認証情報やNTLMのハッシュを取り出していました。ICSとドメインコントローラの間が暗号化されていなければ、ICSを乗っ取られた時点で、そこを通る認証情報が読めてしまいます。
対策はICSからの接続をLDAPS(636番)かStartTLSに切り替えることです。ICS 25.1.3.0のリリースノートは、LDAPサーバを新しく設定するときに「Validate Server Certificate」を既定で有効にしたと書いています。既存の設定は自動では変わらないため、更新後に認証サーバの設定を開いて確かめてください。LDAPと暗号化の仕組みはLDAPの仕組みと認証実装で解説しています。
22.8R2系で再更新するか25.1.3系へ移るか:2027年1月の終了を踏まえた判断
IvantiはPatch Tuesdayの解説で、22.x系が2027年1月31日にサポート終了となるため、25.x系へ早く移るよう勧めています。今回の再更新は、その判断の機会でもあります。
25.1.3.0で既定が変わるIKEv2・SAML・LDAPの設定と移行前の確認項目
25.1.3系への移行は、版を上げるだけでは済みません。リリースノートが挙げる既定値の変更は次のとおりです。
- IKEv2のPhase 1は、AES-256・SHA-256・2048ビット以上のDHだけを既定で許可する。古い暗号設定のクライアントはつながらなくなる
- SAMLのサービスプロバイダとして使う場合、応答の署名検証が既定で有効になる。IdPの証明書チェーンの登録が要る
- LDAPサーバの新規設定でサーバ証明書の検証が既定で有効になる
- セッション終了時にすべてのCookieを消す設定が既定で有効になる
- ストレージ周りの制限の変更により、旧版へのダウングレードができなくなる
ダウングレードできない点が一番の注意です。更新後に不具合が出ても旧版へ戻せないため、設定のバックアップと、IKEv2・SAMLを使う利用者での接続試験を先に済ませます。
22.8R2系の再更新で当面しのぐ条件と今回で25.1.3系へ移る組織
私たちの判断はこうです。IKEv2やSAMLを使っておらず、検証環境で25.1.3系を1〜2日試せるなら、今回の作業で25.1.3系へ移ります。3か月後に同じ規模の更新作業をもう一度するより、1回で済ませたほうが停止の回数が減ります。
逆に、古いIKEv2クライアントを抱えている、SAMLの証明書を整える時間が無い、冗長構成が組めず停止時間を取りにくい、という組織は、22.8R2系の最新の修正版で今回をしのぎます。そのうえで、1月31日より前に移行の日程を確保してください。終了後の22.x系に新しい脆弱性が出ても、修正は提供されません。
VPN機器を残すか見直すかの判断とZTNAへの移行を採らない場面
ICSはKEVに繰り返し載ってきた製品で、2024年1月のCVE-2023-46805とCVE-2024-21887、2025年1月のCVE-2025-0282、4月のCVE-2025-22457も、認証なしで悪用された欠陥でした。社外に開いた入口を減らすためにZTNAへ移る選択肢は、ゼロトラストネットワーク(ZTNA)とVPNの違いと製品選定で比べられます。
ただし、今回の対応の最中に乗り換えを決めるのは勧めません。移行には数か月かかり、その間もICSは動き続けます。まず更新と侵害調査を終えてください。乗り換えを検討するのは、その対応を終えてからの別の計画です。他社のVPN機器も含めて版をKEVと突き合わせる仕組みは、VPN機器の版確認コマンドとKEV照合スクリプトが土台になります。点検の範囲を決めて外部に任せる場合の進め方は、脆弱性診断の種類と進め方・外注時の判断基準で確認できます。
Ivanti Connect Secureの脆弱性対応でよく受ける質問と回答
10月の3件の対応を進める中で出てきやすい疑問に、公開されている一次情報の範囲で答えます。
10月13日に22.8R2.5へ更新済みですが、また更新が必要ですか?
必要です。NVDの構成情報では、22.8R2.5はCVE-2026-104935の対象から外れていますが、root昇格のCVE-2026-111357の対象には残っています。13日の更新で塞がったのは認証回避とコード実行で、権限昇格の修正は10月29日に別に出ました。もう一度、Ivantiの勧告が示す修正版へ上げてください。25.1.1.2へ上げた機器も同じ扱いです。
Integrity Checker Toolで問題が出なければ侵害されていないと考えてよいですか?
考えられません。今回の手口はディスク上のファイルを変えないため、Integrity Checker Toolでは検知できないとVolexityが明記しています。10月3日以降に影響版を公開していた場合は、メモリを含む調査を検討してください。ツール自体は、別の手口の改変を拾うために定期的に動かす価値があります。
Pulse Connect SecureやIvanti Policy Secureも対象ですか?
Pulse Connect SecureはICSの旧名称です。旧名称のまま動く古い版はサポートが切れている可能性が高く、今回の修正も届きません。Policy Secureは、10月31日時点のKEVとNVDでは製品に挙がっていません。過去には同時に対象となった例があるため、使っている場合はIvantiの勧告で確かめてください。
JPCERT/CCの注意喚起は出ていますか?
2026年10月31日の確認では、JPCERT/CCの2026年の注意喚起一覧に本件はありません。同じIvantiのEndpoint Manager Mobile(EPMM)については注意喚起が出ています。国内に注意喚起が無くても、KEVへの登録と悪用の報告がある以上、対応を待つ理由にはなりません。
VPN機器にWebシェルが無ければ、ADの対処まではしなくてよいですか?
今回の攻撃ではWebシェルが置かれていないため、見つからないことは安全の証明になりません。ICSがADと連携しているなら、少なくともICSのサービスアカウントのパスワードは変えることを勧めます。手間は小さく、盗まれていた場合の被害を大きく減らせます。
関連記事
- VPN 脆弱性:機器の版確認コマンドとKEV照合スクリプト・パッチと移行の判断【2026年10月】:Ivantiを含むVPN機器全体の版確認とKEV照合の進め方です。
- Cisco ASAの脆弱性CVE-2026-76418:二次認証の設定確認と8月修正版からの再更新:同じ10月に悪用が確認されたVPN機器で、修正版の再更新が要る点も共通しています。
- NetScalerの脆弱性CVE-2026-88771とは?88779で変わった修正版と侵害調査の手順:リモートアクセス製品の侵害調査の進め方を扱っています。
- Fortinetの脆弱性まとめ|FortiGateの悪用済みCVE一覧と仮想パッチ・確認手順【2026年10月】:FortiGateを併用している場合の悪用済みCVEの一覧です。
- API不正アクセス対策の実装手順:JPCERT注意喚起に沿うレート制限・認可・トークン失効とアプリ解析・SSRF対策:VPN以外の入口から入られる不正アクセスへの備えです。