
vcheck v1.6.3
취약점 감지 및 완화 도구: Copy Fail 및 Dirty Frag 버그 (CVE-2026-31431, CVE-2026-43284, CVE-2026-43500)
vcheck
SSH를 통해 원격 Linux 호스트를 감사하여 Copy Fail 및 Dirty Frag 커널 모듈 취약점을 확인하고, 선택적으로 완화 조치를 적용합니다:
| CVE | 이름 | 영향받는 모듈 |
|---|---|---|
| CVE-2026-31431 | 카피 실패 (Copy Fail) | algif_aead |
| CVE-2026-43284 | 더티 프래그 (IPsec) | esp4, esp6, ipcomp4, ipcomp6, xfrm_user |
| CVE-2026-43500 | 더티 프래그 (RxRPC) | rxrpc, kafs |
vcheck는 각 영향받는 모듈에 대해 현재 로드 여부, 실행 중인 커널에 내장(built-in)되었는지, 커널 로그에 과거 흔적이 있는지, 라이브 AF_ALG 소켓이 있는지(Copy Fail만 해당), 그리고 /etc/modprobe.d/ 아래에 이미 블랙리스트에 등록되었는지를 보고합니다.
-fix 옵션을 사용하면 vcheck가 초기 상태를 보고하고, 아직 블랙리스트에 없는 모듈에 대해 cve-XXXX-XXXXX-disable.conf 스니펫을 작성한 후 검사를 다시 실행하여 최종 상태를 보고합니다. -fix -unload를 사용하면 vcheck가 수정 전에 로드된 영향받는 모듈을 언로드하려고 시도한 후 최종 검사로 여전히 로드되어 있는지 확인합니다. -fix -rebuild-initramfs를 사용하면 vcheck가 스니펫이 작성된 후 현재 실행 중인 커널에 대해서만 initramfs를 재구축하므로 블랙리스트가 다음 부팅 이미지에 포함됩니다. 이전 커널 항목은 폴백(fallback)으로 원래 initramfs를 유지합니다.
-fix는 검사 전용 실행 후에만 사용하세요
항상 먼저 -fix 없이 vcheck를 실행하세요. 보고서를 읽고 영향받는 모듈을 이 호스트에서 비활성화해도 안전한지 확인한 후 -fix로 다시 실행하세요. 합법적인 워크로드가 의존하는 커널 모듈을 비활성화하면 사용자에게 영향을 주고 애플리케이션을 손상시킬 수 있습니다.
특히 다음 사항을 유의하십시오:
-fix가 안전한 것은 영향받는 모듈이 현재 로드되지 않은 경우에만 해당합니다. 즉, 모든 모듈이mitigated또는module not blacklisted로 보고되고VULNERABLE또는blacklisted but currently loaded줄이 없는 경우입니다. 로드된 모듈은 거의 항상 _호스트에서 무언가가 활발히 사용 중임_을 의미합니다. 블랙리스트에 추가하기 전에 확인하십시오.- IPsec 모듈(
esp4,esp6,ipcomp4,ipcomp6,xfrm_user)은 IPsec/strongSwan/WireGuard-over-IPsec/IKE 배포에 필요합니다.ipcomp4/ipcomp6모듈은 IPComp 페이로드 압축을 구현하며 명시적으로 구성되지 않은 경우에도 IPsec SA의 일부로 자동 협상될 수 있습니다. VPN 게이트웨이, IPsec 엔드포인트 또는ip xfrm policy가 규칙을 반환하는 곳에서는 이들 중 어느 것도 블랙리스트에 추가하지 마십시오.xfrm_algo프레임워크 모듈은 의도적으로 이 목록에 포함되지 않았습니다. 공급업체 지침(Red Hat, Ubuntu, AWS)에 따르면 ESP 및 IPComp 프로토콜 모듈과xfrm_usernetlink 구성 인터페이스를 차단하는 것으로 충분하며,xfrm_algo를 블랙리스트에 추가하면 추가 이점 없이 다른 모든 xfrm 변환을 손상시킵니다. - RxRPC 모듈(
rxrpc,kafs)은 AFS 파일 시스템을 마운트하는 모든 호스트에 필요합니다. 비활성화하면 다음 부팅 시 해당 마운트가 중단됩니다. algif_aead는AF_ALG소켓 패밀리를 통해 커널 암호화를 노출합니다. 애플리케이션 코드에서 직접 사용되는 경우는 드물지만, 블랙리스트에 추가하기 전에 라이브 소켓을 나열(ss -p --af-alg)하고 사용자 공간 소비자를 확인하십시오.
vcheck가 작성하는 블랙리스트 스니펫은 모듈 로드 시점(일반적으로 다음 부팅 또는 시스템이 유휴 상태일 때 modprobe -r <module>)에만 적용됩니다. 이미 로드된 모듈은 -fix 이후에도 계속 실행됩니다. vcheck는 이를 blacklisted but currently loaded; run 'modprobe -r' or reboot로 보고합니다. -fix와 함께 -unload를 전달하면 vcheck가 블랙리스트 스니펫을 작성한 후 로드된 영향받는 모듈에 대해 modprobe -r을 실행하도록 요청합니다. 실행 중인 커널에서 모듈을 제거해도 안전하다고 확인한 경우에만 사용하십시오.
-fix와 함께 -rebuild-initramfs를 전달하면 현재 실행 중인 커널에 대해서만 initramfs를 재생성합니다(Debian/Ubuntu에서는 update-initramfs -u -k $(uname -r), RHEL/Fedora에서는 dracut -f --kver $(uname -r)). 다른 설치된 커널은 기존 initramfs를 그대로 유지하므로 재부팅 후 문제가 발생하면 부팅 메뉴에서 이전 커널 항목을 선택하여 복구할 수 있습니다. 향후 커널 설치 시 현재 /etc/modprobe.d/ 상태에서 자체 initramfs를 재구축하므로 vcheck를 다시 실행하지 않고도 블랙리스트가 자동으로 전파됩니다. update-initramfs와 dracut이 모두 없는 경우(예: Arch, Alpine, 불변 이미지) vcheck는 경고하고 계속 진행합니다. 재부팅하기 전에 배포판 도구를 사용하여 수동으로 재구축하십시오.
재구축에는 몇 분이 걸릴 수 있으며(특히 드라이버가 많은 호스트에서 dracut), 이는 진단용 -command-timeout을 초과할 수 있습니다. 이 rebuild는 자체 -initramfs-timeout(기본값 10m) 아래에서 실행되므로 빠른 검사는 시간 제한을 유지하면서 rebuild에 충분한 시간을 할당합니다. 느린 하드웨어의 경우 -initramfs-timeout을 늘리거나 0을 전달하여 시간 제한을 완전히 비활성화하십시오. 장기 실행 원격 명령 중에 vcheck는 기본적으로 30s마다 SSH keepalive 요청을 보내 NAT/방화벽 유휴 타이머가 연결을 끊지 않도록 합니다. -ssh-keepalive로 조정하거나 0을 전달하여 비활성화하십시오.
설치
Homebrew (macOS):
brew install --cask krisiasty/tap/vcheck
미리 빌드된 바이너리 Linux, macOS 및 Windows용은 릴리스 페이지에서 제공됩니다.
소스에서 빌드 (Go 1.26+ 필요):
go install github.com/krisiasty/vcheck@latest
사용법
vcheck -host HOST [flags]
| 플래그 | 기본값 | 설명 |
|---|---|---|
-host | (필수) | 원격 호스트 |
-user | $USER | 원격 사용자 |
-port | 22 | 원격 SSH 포트 |
-agent | true | 인증에 SSH 에이전트 사용 |
-identity | (비어 있음) | 개인 키 파일 경로 (암호화된 경우 암호문 입력 요청) |
-password | false | SSH 비밀번호 입력 요청 |
-insecure | false | known_hosts에 아직 기록되지 않은 호스트 키 허용; 기록된 키와 불일치는 여전히 실패 |
-fix | false | 아직 블랙리스트에 없는 모듈에 대해 /etc/modprobe.d 스니펫 작성 |
-unload | false | -fix와 함께 사용: 블랙리스트에 추가한 후 영향받는 모듈 언로드 |
-rebuild-initramfs | false | -fix와 함께 사용: 실행 중인 커널에 대해서만 initramfs 재구축 (update-initramfs 또는 dracut) |
-skip-logs | false | 커널 로그 기록 검사 건너뛰기 |
-timeout | 15s | SSH 연결 시간 제한 |
-ssh-keepalive | 30s | SSH keepalive 간격 (0은 비활성화) |
-command-timeout | 30s | 원격 명령 시간 제한 (0은 비활성화) |
-initramfs-timeout | 10m | initramfs 재구축 단계 시간 제한 (0은 비활성화); -rebuild-initramfs와 함께만 사용 |
-debug | false | 로그 상세도 증가 |
-version | false | 버전 표시 후 종료 |
-agent, -identity, -password 중 적어도 하나는 사용 가능한 인증 방법을 생성해야 합니다. 메서드는 나열된 순서대로 시도됩니다.
대상에서 sudo가 필요합니다. 암호 없는 sudo가 구성된 경우 도구는 자동으로 진행됩니다. 그렇지 않으면 한 번 비밀번호를 입력하라는 메시지가 표시되고(입력이 숨겨짐) 이후 모든 명령에 대해 sudo -S를 통해 전달됩니다.
종료 코드
| 코드 | 의미 |
|---|---|
0 | 모든 영향받는 모듈이 블랙리스트에 등록, 언로드, 내장되지 않음, 비활성 상태 |
1 | 사용법 오류 |
2 | SSH 연결 실패 |
3 | Sudo 인증 실패 |
4 | 하나 이상의 모듈이 블랙리스트에 등록되지 않음 (현재 노출 없음) |
5 | 하나 이상의 모듈이 현재 로드, 커널에 내장 또는 활성 사용 중 |
99 | 내부/검사 실패 |
샘플 출력
완전히 완화된 호스트
$ vcheck -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF mitigated cve=CVE-2026-31431 module=algif_aead
INF mitigated cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
완화되지 않고 부분적으로 로드됨 — 기본 검사
$ vcheck -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR VULNERABLE cve=CVE-2026-43284 module=esp4 loaded=true
ERR module not blacklisted cve=CVE-2026-43284 module=esp6
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp4
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp6
ERR module not blacklisted cve=CVE-2026-43284 module=xfrm_user
ERR module not blacklisted cve=CVE-2026-43500 module=rxrpc
ERR module not blacklisted cve=CVE-2026-43500 module=kafs
동일한 호스트에 -fix 적용 — 첫 실행
$ vcheck -fix -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF findings before fix
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR VULNERABLE cve=CVE-2026-43284 module=esp4 loaded=true
ERR module not blacklisted cve=CVE-2026-43284 module=esp6
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp4
ERR module not blacklisted cve=CVE-2026-43284 module=ipcomp6
ERR module not blacklisted cve=CVE-2026-43284 module=xfrm_user
ERR module not blacklisted cve=CVE-2026-43500 module=rxrpc
ERR module not blacklisted cve=CVE-2026-43500 module=kafs
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43284-disable.conf modules="[esp4 esp6 ipcomp4 ipcomp6 xfrm_user]"
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43500-disable.conf modules="[rxrpc kafs]"
INF re-scanning after fix snippets_written=2
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF findings after fix
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR blacklisted but currently loaded; run 'modprobe -r' or reboot cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
블랙리스트는 적용되었지만 esp4는 스니펫이 작성되기 전에 이미 커널에 로드되었습니다. 완전히 해제하려면 대상에서 재부팅하거나 sudo modprobe -r esp4를 실행하십시오.
두 번째 실행 — esp4가 여전히 로드됨
$ vcheck -fix -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF findings before fix
INF mitigated cve=CVE-2026-31431 module=algif_aead
ERR blacklisted but currently loaded; run 'modprobe -r' or reboot cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
INF fix: nothing to do — all affected modules already blacklisted
세 번째 실행 — modprobe -r esp4 실행 후
$ vcheck -host host.example.com -identity ~/.ssh/id_ed25519
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
INF checking vulnerability cve=CVE-2026-43284 name="Dirty Frag (IPsec)"
INF checking vulnerability cve=CVE-2026-43500 name="Dirty Frag (RxRPC)"
INF mitigated cve=CVE-2026-31431 module=algif_aead
INF mitigated cve=CVE-2026-43284 module=esp4
INF mitigated cve=CVE-2026-43284 module=esp6
INF mitigated cve=CVE-2026-43284 module=ipcomp4
INF mitigated cve=CVE-2026-43284 module=ipcomp6
INF mitigated cve=CVE-2026-43284 module=xfrm_user
INF mitigated cve=CVE-2026-43500 module=rxrpc
INF mitigated cve=CVE-2026-43500 module=kafs
-rebuild-initramfs 사용
$ vcheck -fix -rebuild-initramfs -host host.example.com -identity ~/.ssh/id_ed25519
...
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43284-disable.conf modules="[esp4 esp6 ipcomp4 ipcomp6 xfrm_user]"
INF writing modprobe.d snippet path=/etc/modprobe.d/cve-2026-43500-disable.conf modules="[rxrpc kafs]"
INF rebuilding initramfs for running kernel timeout=10m0s
INF initramfs rebuilt for running kernel tool=update-initramfs
INF re-scanning after fix snippets_written=2
...
실행 중인 커널의 initramfs만 재구축됩니다. 다른 설치된 커널은 기존 initramfs를 유지하므로 새 initramfs가 문제를 일으키는 경우 부팅 메뉴의 이전 항목이 작동하는 폴백으로 남아 있습니다. update-initramfs와 dracut이 모두 없는 호스트에서는 vcheck가 WRN no supported initramfs tool found ... 로그를 남기고 계속 진행합니다.
첫 접속 호스트 — -insecure
$ vcheck -insecure -host host.example.com -identity ~/.ssh/id_ed25519
WRN host key not in known_hosts; accepting due to -insecure host=host.example.com:22 remote=192.0.2.42:22 fingerprint=SHA256:AAAAEXAMPLEfingerPrint000000000000000000000
INF connected user=ops host=host.example.com port=22
INF checking vulnerability cve=CVE-2026-31431 name="Copy Fail"
...
-insecure는 아직 known_hosts에 없는 호스트를 허용합니다. 호스트가 이미 기록되어 있고 다른 키를 제시하는 경우 연결은 여전히 실패합니다. 이 플래그는 "첫 접속" 재정의일 뿐, 알려진 호스트에 대한 중간자 공격 경고를 억제하는 방법이 아닙니다.
탐지 세부 사항
- 로드됨:
lsmod를 한 번 가져와 모듈 이름을 첫 번째 열과 비교합니다. - 내장(Built-in):
/lib/modules/$(uname -r)/modules.builtin과/sys/module을 확인합니다. modprobe 스니펫은 실행 중인 커널에 컴파일된 코드를 비활성화할 수 없기 때문입니다. - 블랙리스트:
/etc/modprobe.d/아래의 모든 파일을 검색(grep -rE)하여install <module> /bin/false지시문을 찾습니다. 이는 vcheck가-fix로 작성하는 형식과 동일합니다. 다른 비활성화 방식(예:blacklist)은 인식되지 않습니다. - 과거 활동: 먼저
journalctl -k를 확인하고, 실패 시/var/log/kern.log로 대체합니다. 모듈당 마지막 다섯 개의 일치하는 줄을 유지합니다. 이 단계를 건너뛰려면-skip-logs를 전달하십시오. - 활성 소켓(
algif_aead만 해당):ss -p --af-alg로 열린AF_ALG소켓을 나열합니다. 헤더 이외의 출력은 라이브 사용으로 간주됩니다.
모든 명령은 sudo를 통해 실행되며 -command-timeout으로 제한됩니다. /var/log/kern.log 읽기, AF_ALG 소켓 나열, /etc/modprobe.d/ 아래에 쓰기에는 권한 있는 액세스가 필요합니다. -unload를 사용하면 modprobe -r 실행에도 권한 있는 액세스가 필요합니다. -rebuild-initramfs를 사용하면 vcheck가 update-initramfs -u -k $(uname -r) (Debian/Ubuntu) 또는 dracut -f --kver $(uname -r) (RHEL/Fedora)를 실행하며, 이 역시 루트 권한이 필요합니다.