
Detection, mitigation, and reverse-engineering tooling for CVE-2026-41940 (SessionScribe): the cPanel/WHM unauthenticated session-forgery vulnerability disclosed 2026-04-28. Defense-in-depth active mitigation shim, ModSec rule pack, remote probe, on-host IOC scanner, and per-tier RE snapshot collector. GPL v2.
cPanel 및 WHM의 중요 인증되지 않은 원격 코드 실행(RCE) 취약점. 네 번의 HTTP 요청으로 CRLF 주입을 통해 사전 인증 세션의 비밀번호 필드에 삽입하여 루트 세션을 위조합니다. 인증 불필요, 사전 조건 없음, 지원되는 모든 티어에 영향을 미칩니다. 2026년 4월 28일 Sina Kheirkhah / watchTowr Labs가 공개.
Quickstart · ioc-scan · mitigate · remote-probe · Affected builds · Priority order
[!IMPORTANT] 티어 112, 114, 116, 120, 122, 128에는 공급업체 패치가 없습니다. 해당 티어의 모든 빌드가 취약합니다. 업그레이드 또는 마이그레이션이 유일한 영구적인 해결책입니다. 그때까지는 방화벽 TCP/2082, 2083, 2086, 2087, 2095, 2096을 관리 CIDR로 제한하십시오 (
mitigate.sh --apply가 이를 수행합니다). 나머지 표면은 ModSec 규칙 팩으로 보호하십시오.
운영자 우선순위 순서로 된 세 가지 원라인 명령어:```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --apply
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target HOST
종료 코드는 플릿 자동화를 위해 설계되었습니다: `ioc-scan`은 COMPROMISED 상태에서 `4`를 반환하고, VULNERABLE 상태에서 `1`을 반환합니다; `mitigate`는 `0` (정상), `1` (적용됨), `2` (수동), `3` (도구 오류)를 반환합니다; `remote-probe`는 대상 중 하나라도 VULN이면 `2`를 반환합니다.
---
## Tools
운영 우선순위 순서로 정렬됩니다. 모든 아티팩트는 구조화된 출력(`--json` / `--jsonl` / `--csv`)을 생성하며, 플릿 집계를 위해 `host`, `os`, `cpanel_version`, `ts`를 키로 사용합니다.
| Tool | 역할 | 실행 위치 |
|---|---|---|
| **[`sessionscribe-ioc-scan.sh`](#sessionscribe-ioc-scansh---ioc-ladder--kill-chain)** | 1차 분류. IOC 사다리, 코드 상태 + 호스트 상태 판정, 킬 체인 재구성, IR 번들. | cPanel 호스트에서 실행 |
| **[`sessionscribe-mitigate.sh`](#sessionscribe-mitigatesh---mitigation-orchestrator)** | 취약점 창을 닫습니다. 단계별 완화: 패치 확인, 방화벽, proxysub, ModSec. | cPanel 호스트에서 실행 |
| **[`sessionscribe-remote-probe.sh`](#sessionscribe-remote-probesh---non-destructive-fleet-probe)** | 보조 자료. 비파괴 4단계 프로브 → 호스트별 VULN/SAFE. | `curl`이 있는 모든 곳 |
| [`modsec-sessionscribe.conf`](#supporting-collateral) | `mitigate`에 의해 배포되는 ModSec 규칙 팩. | Apache 프론트엔드 |
| [`sessionscribe-revsnap.sh`](#supporting-collateral) | 바이너리 비교를 위한 계층별 RE 스냅샷 수집기. | cPanel 호스트에서, `upcp` 주변에서 실행 |
GPL v2. 모든 아티팩트는 위의 raw URL을 통해 `curl`로 바로 다운로드할 수 있습니다.
---
## `sessionscribe-ioc-scan.sh` - IOC 사다리 + 킬 체인
**이것을 먼저 실행하세요.** 기본적으로 탐지 전용입니다 (빠르고 플릿에 적합); `--full`을 추가하여 포렌식 단계를 인라인으로 실행합니다 (방어 타임라인, 공격 수집, 조정, 킬 체인 렌더러, IR 번들).```bash
# fast triage (detection only)
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash
# full kill-chain reconstruction inline
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --full
# full + ship IR bundle to intake
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --full --upload
# JSONL for SIEM ingest
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --jsonl --quiet > host.jsonl
# host IOCs only - periodic post-patch sweep, last 7 days
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --ioc-only --since 7
# replay forensic phases against a saved envelope (no re-scan)
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh | bash -s -- --replay /var/cpanel/sessionscribe-ioc/<run_id>.json
두 축이 독립적으로 보고합니다. code_verdict (PATCHED / VULNERABLE / INCONCLUSIVE)는 버전, Perl 소스 패턴 및 cpsrvd 바이너리 핑거프린트에서 비롯됩니다. host_verdict (CLEAN / SUSPICIOUS / COMPROMISED)는 세션 파일 IOC 사다리, 액세스 로그 스캔 및 패턴 A–G 파괴 프로브에서 비롯됩니다. 패치된 호스트라도 이전에 악용으로 인해 IOC가 디스크에 남아 있으면 종료 코드 4가 발생할 수 있습니다.
원격 프로브가 남긴 nxesec_canary_<nonce> 태그가 있는 세션은 PROBE_ARTIFACT로 분류되며 COMPROMISED로 에스컬레이션되지 않습니다.
--full은 모든 IOC를 방어 활성화와 대조하여 각각을 PRE-DEFENSE, POST-DEFENSE, POST-PARTIAL 또는 UNDEFENDED로 분류한 후, 판정 + 방어 지연 헤드라인으로 요약합니다. PRE-DEFENSE = 호스트가 지표가 도착했을 때 익스플로잇에 대해 열려 있었음; POST-DEFENSE = 부수적 손상 또는 사전 완화 잡음.```
+-- CVE-2026-41940 / IC-5790 --------------------------------------------
| host cpanel.example.com ()
| cpanel unknown os unknown
| verdict COMPROMISED score 315 ioc-scan v2.5.0
| defenses patch x absent modsec + up csf + clean mitigate + ran
+------------------------------------------------------------------------
| -- PRE-DEFENSE (32 events) -- | 2026-03-25T09:43:19Z ! pattern X ioc_attacker_ip_2xx_on_cpsess 57 hit(s) (last 90d) from IC-5790 IPs returned 2xx on /cpsess/ paths - real exploitation | 2026-04-28T14:35:56Z ! pattern X ioc_cve_2026_41940_crlf_access_chain 15 CRLF-bypass chain(s) — POST /login 401 then GET /cpsess 2xx as root within 2s | 2026-04-28T16:38:45Z ! pattern E ioc_pattern_e_websocket_shell_hits 45 external IP(s) reached /cpsess*/websocket/Shell with 2xx | 2026-04-29T08:41:22Z ! pattern F ioc_pattern_f_smark_envelope S_MARK/E_MARK harvester envelope in /root/.bash_history | 2026-04-29T16:41:24Z ! pattern A ioc_pattern_a_ransom_readme /home/user1/README.md | … (22 more Pattern A ransom_readme events across customer homedirs) | 2026-04-29T16:42:09Z ! pattern A ioc_pattern_a_sorry_files_present 608 .sorry-encrypted files present | 2026-04-29T17:52:58Z ! pattern D ioc_pattern_d_acctlog_encrypted /var/cpanel/accounting.log.sorry
| -- DEFENSES -- | 2026-04-29T23:48:21Z + DEFENSE mitigate_first sessionscribe-mitigate.sh first run | 2026-04-29T23:48:21Z + DEFENSE csf csf.conf cpsrvd ports stripped | 2026-04-29T23:48:46Z + DEFENSE modsec modsec rule 1500030 installed
| -- POST-PARTIAL (1 event) -- | 2026-04-30T12:23:42Z ! pattern E ioc_pattern_e_handoff_burst_present 3 distinct external IPs each minted cpsess + reached websocket Shell within 15-min window
| HEADLINE | verdict COMPROMISED (score 315) | defense lag 37d 9h LATE (first IOC 2026-03-25T09:43:19Z, defense up 37d 9h later)
<details>
<summary><b>검사 참조 + 포렌식 단계 + 번들 레이아웃</b> (클릭하여 펼치기)</summary>
| 검사 | 설명 |
|---|---|
| `version` | `cpanel -V` 와 공개된 패치 빌드 목록 비교 - `code_verdict` 결정 |
| `static-pattern` | `Cpanel/Session/*.pm`에서 패치 후 센티넬 패턴(`no-ob:` 디코드 분기) 그렙 |
| `cpsrvd-fingerprint` | cpsrvd 바이너리 검사, 패치 빌드 서명과 대조 |
| `access-log` | Apache + cpsrvd 로그에서 악용 트래픽 패턴 확인 (`--no-logs`로 건너뛰기) |
| `session-store` | `/var/cpanel/sessions/raw/` 탐색: 공급업체 IOCs + 4방향 동시발생 + 위조 타임스탬프 휴리스틱 (`--no-sessions`로 건너뛰기) |
| `destruction` | 패턴 A–G 프로브: `/root/sshd` 암호화기, mysql-와이프, BTC 인덱스, `nuclear.x86`, `sptadm` 리셀러, `__S_MARK__` 수집기, 의심스러운 SSH 키 (`--no-destruction-iocs`로 건너뛰기) |
| `probe` (옵트인) | `127.0.0.1:2087`에 단일 마커 GET - cpsrvd 응답 확인. **우회 시도하지 않음** |
**`--full` 포렌식 단계** (탐지 후 인라인 실행):
| 단계 | 설명 |
|---|---|
| `defense` | 적용된 모든 방어 계층의 타임스탬프 기록: cpanel 패치, 패치 후 cpsrvd 재시작, 완화 실행, ModSec 규칙, CSF/APF 포트 폐쇄, proxysub, `upcp` 요약 |
| `offense` | 관찰된 모든 침해 지표의 타임스탬프 기록 (패턴 A–G + 패턴 X CRLF-우회 체인) |
| `reconcile` | 지표별: 해당 지표가 처음 나타났을 때 관련 방어가 활성화되었는가? PRE-DEFENSE / POST-DEFENSE / POST-PARTIAL / UNDEFENDED + 시간 차이 |
| `bundle` | `/root/.ic5790-forensic/<TS>-<RUN_ID>/` 아래 원시 아티팩트의 타르볼, 모드 `0700` |
**번들 레이아웃** (`/root/.ic5790-forensic/<TS>-<RUN_ID>/`):```
manifest.txt host/uid/cpv/run_id/window/cap
sessions.tgz /var/cpanel/sessions/{raw,preauth} (filtered)
access-logs.tgz cpsrvd access + incoming_http_requests + error_log
+ global Apache access/error (NO domlogs)
system-logs.tgz /var/log/{secure,messages,audit/audit.log,auth.log}*
cpanel-state.tgz accounting.log + resellers + cpanel.config + api_tokens_v2
cpanel-users.tgz /var/cpanel/users/ (split out, per-account state)
persistence.tgz ssh keys + all cron tiers + systemd/init.d/profile.d
+ rc.local + root histories + passwd/group + sudoers
defense-state.tgz mitigate backups + csf/apf/modsec configs + updatelogs
ps.txt / connections.txt / iptables.txt
pattern-a-binary-metadata.txt only if /root/sshd present (metadata; binary NOT bundled)
user-histories/ per-user .bash_history (gated on --no-history)
90일 윈도우 기준 바쁜 호스트의 일반적인 번들: 압축 시 약 250MB ~ 2GB.
개별 tarball 2GB 제한(--max-bundle-mb)을 초과하는 후보는 개별적으로 제외됩니다.
실행 로그는 기본적으로 /var/cpanel/sessionscribe-ioc/에 기록됩니다(비활성화하려면 --no-ledger). --chain-forensic / --chain-on-critical / --chain-upload는 v1.x 하위 호환 별칭으로 유지됩니다.
추출된 tarball에 대한 오프라인 포렌식을 위한 스냅샷 테스트 재정의: --root DIR, --version-string S, --cpsrvd-path P. 전체 플래그 목록은 --help를 참조하세요.
sessionscribe-mitigate.sh - 완화 오케스트레이터기본적으로 읽기 전용(--check). 상태를 변경하려면 --apply를 추가하세요.
멱등적: 정상 호스트에서 다시 실행해도 아무 작업도 수행되지 않습니다. 변경 사항은 파일을 건드리기 전에 /var/cpanel/sessionscribe-mitigation/ 아래에 타임스탬프가 있는 백업을 작성합니다.```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --apply
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --apply --only modsec --probe curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --only patch,preflight # pre-upcp gate
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --csv > host.csv curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --jsonl > host.jsonl
| 단계 | 기능 |
|---|---|
| `patch` | `cpanel -V` 와(과) 게시된 패치 빌드 목록 비교 (EL6 11.86.0.41, EL6/CL6 110.0.103, tier 124, WP² 136.1.7 포함) |
| `preflight` | `/etc/yum.repos.d/threatdown.repo` 제거; `epel-release` 확인; 깨진 비기본 저장소를 비활성화하여 `upcp`가 실행 중에 중단되지 않도록 함 |
| `upcp` | 패치되지 않은 경우 `/scripts/upcp --force --bg` 실행 |
| `proxysub` | `proxysubdomains` + 새 계정 변형 활성화; httpd 구성 재구축 |
| `csf` / `apf` / `runfw` | `TCP_IN`/`TCP6_IN`/`IG_TCP_CPORTS`에서 cpsrvd 포트(2082/2083/2086/2087/2095/2096) 제거; 활성 iptables INPUT 체인 확인 |
| `apache` | `httpd` 실행 중 + `security2_module` 로드됨 |
| `modsec` | `modsec2.user.conf`에 규칙 `1500030` + `1500031` 포함; 누락된 경우 배포 (타임스탬프 백업, `httpd -t` 검증, 무중단 리로드) |
| `probe` (선택) | `127.0.0.1`에 대해 `sessionscribe-remote-probe.sh`를 실행하여 실제 차단 확인 |
CentOS / Alma / Rocky의 base/appstream/extras/updates/powertools 저장소는 `preflight`에 의해 **절대** 비활성화되지 않으며, 현재 연결할 수 없는 경우에도 마찬가지입니다.
### 종료 코드
| 종료 코드 | 의미 |
|---|---|
| 0 | 깔끔함 - 패치됨 및 상태 양호, 조치 불필요 |
| 1 | 수정 성공적으로 적용됨 (`--apply`가 변경을 수행함) |
| 2 | 수동 개입 필요 (`--check`에서 경고, `--apply`에서 실패) |
| 3 | 도구 오류 (잘못된 인수, 누락된 종속성, `--apply`에 대해 루트가 아님) |
단계 선택: `--only LIST`, `--no-PHASE`, `--no-fw` (`--no-csf --no-apf --no-runfw`의 약어). 출력: `--json` / `--jsonl` / `--csv`, `-o FILE`. 전체 플래그 목록은 `--help`를 참조하십시오.
### 60초 스모크 체크```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --list-phases # surface the phase API
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh | bash -s -- --check # safe read-only audit
echo "exit=$?" # 0 on a non-cPanel host
오케스트레이터는 cPanel이 아닌 호스트를 감지하고 깔끔하게 종료됩니다 — 실험실 없이도 멱등성을 입증합니다.
sessionscribe-remote-probe.sh - 비파괴적 플릿 프로브지원 자료. 타겟에 대해 4단계 체인을 비파괴적으로 실행합니다: mint preauth → CRLF inject → propagate raw→cache → /json-api/version을 통한 검증, 그런 다음 적극적으로 로그아웃합니다. 판정 신호는 4단계의 HTTP 코드입니다: 200 또는 라이선스 본문이 있는 5xx는 VULN, 401 또는 403은 SAFE입니다.
모든 테스트 세션에는 포렌식 정리를 위해 nxesec_canary_<nonce> 속성이 태깅되며, 상태를 변경하는 API 호출은 이루어지지 않습니다. 위조된 세션은 3단계와 5단계 로그아웃 사이에 약 1~3초 동안 루트와 동등합니다 — 전체 안전 모델은 스크립트 헤더를 참조하세요.```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target 1.2.3.4
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target 1.2.3.4 --proxy example.com
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh
| bash -s -- --csv $(awk '{print "--target "$1}' fleet.txt) > fleet.csv
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --target 1.2.3.4 --fingerprint-only
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh | bash -s -- --cleanup
출력 모드: pretty(기본), `-q`/`--quiet`, `--oneline`, `--csv`,
`--json`. 종료 코드: `0` 취약점 없음, `1` 불명확함만, `2`
하나 이상의 취약점. 전체 플래그 목록은 `--help`를 참조하세요. 여기에는
`--auto-host-discover`, `--all`, `--fingerprint-only` 의미론 및
stage-2 전용 `--no-verify` 모드(레거시, 패치된 호스트에서 오탐을 생성함)가 포함됩니다.
---
## 보조 자료
### `modsec-sessionscribe.conf` - ModSecurity 규칙 팩
자동으로 `mitigate.sh --apply --only modsec`에 의해 배포됩니다. 수동 설치:```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/modsec-sessionscribe.conf \
| sudo tee /etc/apache2/conf.d/modsec/modsec2.user.conf >/dev/null
sudo apachectl -t && sudo /usr/local/cpanel/scripts/restartsrv_httpd
예약된 ID 범위: 1500000–1500099. WHM 토큰 규칙은 운영자가 정의한 신뢰 목록에 대해 @ipMatch를 사용합니다. — 배포 전에 파일 상단의 CIDR을 편집하세요.
[!IMPORTANT] 이 규칙들은 Apache 내에서 실행됩니다.
cpsrvd는 2082/2083/2086/2087/2095/2096 포트에서 직접 수신 대기하며 Apache와 독립적으로 접근 가능합니다. 규칙 팩을 cpsrvd 포트 방화벽과 함께 관리 CIDR에 적용하세요.
sessionscribe-revsnap.sh - RE 스냅샷 수집기계층별 tarball(바이너리, strings, dynsym, disasm, Perl 모듈, 런타임 레이아웃)을 캡처하여 cPanel 업그레이드 간 바이너리 diffing에 사용합니다. upcp를 기반으로 pre/post-patch 쌍을 캡처하도록 설계되었습니다.```bash
curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-revsnap.sh | bash
/scripts/upcp --force curl -fsSL https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-revsnap.sh | bash
Generalises beyond SessionScribe: every future cpsrvd CVE will land in
roughly the same surface, and a tarball pair for the pre-patch and
patched build is the difference between hours and days of analysis.
See the [research article](https://rfxn.com/research/cpanel-sessionscribe-cve-2026-41940)
for the full RE walkthrough.
---
## 플릿 사용법
> [!TIP]
> 모든 아티팩트는 정형화된 출력(`--json`, `--jsonl`, `--csv`)을 내보내며,
> 모든 레코드에 `host`, `os`, `cpanel_version`, `ts`가 포함됩니다. 수백 대의
> 호스트를 한 번에 처리하기 위해 `pdsh | jq` 또는 `ansible -m script` 롤업에
> 적합하게 설계되었습니다.
동일한 curl-piped-bash 원시 방식 — 각 호스트가 최신 스크립트를 직접 가져와 실행하도록 합니다.```bash
IOC=https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-ioc-scan.sh
MIT=https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-mitigate.sh
PRB=https://raw.githubusercontent.com/rfxn/cpanel-sessionscribe/main/sessionscribe-remote-probe.sh
# IOC scan across fleet, JSONL to SIEM
for h in $(cat fleet.txt); do
ssh "$h" "curl -fsSL $IOC | bash -s -- --jsonl --quiet"
done | jq -c '.' > fleet-ioc.jsonl
# kill-chain reconciliation across fleet (no bundles on broad sweep)
ansible -i hosts cpanel -m shell \
-a "curl -fsSL $IOC | bash -s -- --full --no-bundle --jsonl" > fleet-forensic.jsonl
jq -r 'select(.phase=="summary" and .key=="verdict"
and .note=="COMPROMISED_PRE_DEFENSE") | .host' \
fleet-forensic.jsonl > pre-defense-hosts.txt
# bundle collection on the pre-defense subset
ansible -i pre-defense-hosts.txt all -m shell \
-a "curl -fsSL $IOC | bash -s -- --full --jsonl --bundle-dir /root/.ic5790-forensic"
# mitigation posture roll-up
pdsh -w cpanel-fleet "curl -fsSL $MIT | bash -s -- --jsonl --quiet" \
| jq -c 'select(.severity != "info")' > fleet-mitigate.jsonl
# remote probe sweep - exit 2 on any VULN (run from operator workstation)
curl -fsSL $PRB | bash -s -- --csv --quiet \
$(awk '{print "--target "$1}' fleet.txt) > fleet-probe.csv
The probe is independently fleet-safe (canary-tagged sessions, active logout, no state-changing API calls). The on-host scripts respect --quiet + structured-output flags so stdout is parser-clean.
Four HTTP requests, no auth, no preconditions:```mermaid sequenceDiagram autonumber actor A as attacker participant C as cpsrvd participant S as session file A->>C: POST /login/?login_only=1 with user=root, pass=wrong C-->>A: Set-Cookie · whostmgrsession=NAME,OBHEX A->>C: GET / · Authorization Basic b64(root:x + CRLF payload) · Cookie minus OBHEX C->>S: writes pass=x, user=root, hasroot=1, ... (CRLFs land verbatim) C-->>A: HTTP 307 · Location /cpsess[10digits]/ A->>C: GET /scripts2/listaccts · cookie only C->>S: propagate raw to cache · forged keys now readable C-->>A: 401 token denied (side-effect already done) A->>C: GET /cpsess[token]/json-api/version C-->>A: 200 OK means VULN · 403 means SAFE
Verdict는 요청 4의 HTTP 코드입니다. 디스크 상의 세션 파일(`/var/cpanel/sessions/raw/<sessname>`)이 사후 포렌식 아티팩트의 유일한 근거입니다. 전체 프리미티브(두 가지 구성 비대칭 — 모든 쓰기 경로에 `filter_sessiondata`가 적용되지 않음, `ob_part` 누락 시 인코더가 단락됨) 및 프록시 엔드포인트 적용을 위한 아키텍처적 논거는 [연구 문서](https://rfxn.com/research/cpanel-sessionscribe-cve-2026-41940)에 있습니다.
---
## 침해 지표
위조된 세션 파일 형태(`/var/cpanel/sessions/raw/<sessname>` (악용 후):```
local_port=2087
hasroot=1
hulk_registered=1
pass=x
origin_as_string=address=127.0.0.1,app=whostmgrd,method=badpass
token_denied=1
local_ip_address=127.0.0.1
external_validation_token=cS9C19OfV0hCA4uD
cp_security_token=/cpsess6844364556
ip_address=127.0.0.1
user=root
tfa_verified=1
successful_internal_auth_with_timestamp=9999999999
port=39040
login_theme=cpanel
일반적인 사전 인증 세션에는 pass=, hasroot=1,
user=root, tfa_verified=1 또는
successful_internal_auth_with_timestamp=가 포함되지 않습니다. 이 중 하나라도
origin_as_string=…method=badpass와 결합되면 진단적입니다. now+365d를 초과하는 위조된 타임스탬프 값(예: 9999999999)은 독립적으로 진단적입니다.```bash
for f in /var/cpanel/sessions/raw/*; do
[ -f "$f" ] || continue
if grep -q '^token_denied=' "$f"
&& grep -q '^cp_security_token=' "$f"
&& grep -q '^origin_as_string=.*method=badpass' "$f"; then
echo "IOC0 hit: $f"
fi
done
Access-log signal: 성공적인 `200`/`302`/`307` 응답이
`/json-api/`, `/execute/`, 또는 `/scripts2/` 경로에서 기준선이 아닌
소스 IP로부터 동일한 세션 창에 선행하는 `/login/` 200 없이 발생한 경우.
---
## 영향을 받는 빌드```
11.86.0.41 (EL6/CL7) 11.110.0.97 11.118.0.63 11.124.0.35
11.126.0.54 11.130.0.19 11.132.0.29 11.134.0.20
11.136.0.5 110.0.103 (EL6/CL6 from .50)
WP Squared: 136.1.7
벤더 패치 목록에서 제외된 티어는 즉시 수정이 불가능합니다: 112, 114, 116, 120, 122, 128. 해당 티어의 호스트는 패치된 메이저 시리즈로 업그레이드하거나, 마이그레이션하거나, cpsrvd 리스너를 방화벽으로 차단해야 합니다.
11.86.0.41 (EL6/CL7)은 04/29 권고 개정판에 추가되었습니다. 같은 개정판에서 11.130이 .18에서 .19로 업데이트되었습니다. 이후 개정판에는 11.124.0.35 (이전 티어 124의 간격을 메움) 및 110.0.103이 EL6/CL6 호스트 중 여전히 v110.0.50에 있는 경우를 위한 직접 업그레이드 대상으로 추가되었습니다.
즉시
sessionscribe-ioc-scan.sh를 실행합니다. 패치된 호스트도 여전히 손상될 수 있습니다.향후
@ipMatch 신뢰 목록이 설정된 상태로 modsec-sessionscribe.conf를 modsec2.user.conf에 배포합니다.프록시-엔드포인트 적용의 아키텍처적 근거는 연구 기사의 마지막 세 번째 부분에 설명되어 있습니다.
cpsrvd, cpsrvd.so 또는 Cpanel/Session/*.pm을 수정하지 않습니다. cpanel이 발행한 백포트가 실제 수정 사항입니다.proxysub + 방화벽 단계와 ModSec 규칙 팩이 피해 범위를 줄입니다. 업그레이드 또는 마이그레이션만이 유일한 장기적인 해결책입니다.nxesec_canary_<nonce> 속성을 태그하고 적극적으로 로그아웃합니다.ioc-scan은 이전 악용의 증거를 찾지만, 이를 해결하지는 않습니다. COMPROMISED 판정을 결론이 아닌 전체 IR의 트리거로 간주하십시오.[!TIP] 버그를 발견했거나, 놓친 IOC, 오탐지, 또는 운영 피드백이 있으신가요? GitHub 이슈 열기 - 버그 보고, 실제 환경에서 발견된 IOC 변종, 패치/패치되지 않은 호스트에서의 탐지 누락, ModSec 규칙 오탐지, 일반 운영자 피드백 모두 환영합니다.
민감한 공개(실제 악용 증거, 고객 데이터, 아직 공개되지 않은 새로운 익스플로잇 체인)는 GH Issues가 아닌 Keybase 또는 이메일로 보내주십시오.
GPL v2. 각 파일 헤더를 참조하십시오.
SessionScribe 사고 대응 중 작성됨 - Ryan MacDonald, R-fx Networks.
| 종료 코드 | 코드 상태 | 호스트 상태 | 분류 조치 |
|---|
| 0 | CLEAN/PATCHED | CLEAN | 없음 |
| 1 | VULNERABLE | (any) | cpsrvd 패치 |
| 2 | INCONCLUSIVE | (any) | 수동 코드 상태 검토 (또한: 도구 오류) |
| 3 | (any) | SUSPICIOUS | 세션/액세스 로그 검토 |
| 4 | (any) | COMPROMISED | 전체 IR; 번들 + 업로드 |
| 규칙 | 표면 | 조치 |
|---|
1500030 | CRLF inside Authorization: Basic decoded payload | deny, 모든 소스, 모든 경로 |
1500031 | whostmgrsession 쿠키에 유효한 ,OBHEX 접미사 누락 | deny (심층 방어) |
1500010 | /json-api/, /execute/, /acctxfer*/ 경로에 Authorization: WHM | 신뢰 목록에 없는 소스일 때 deny |
1500020 | WebSocket 디스패치 패밀리에 Authorization: WHM | 신뢰 목록에 없는 소스일 때 deny |
1500021 | SSE 디스패치 경로에 Authorization: WHM | 신뢰 목록에 없는 소스일 때 deny |