
Apache Spark 4.2.0 - 높음 - 원격 - 권한 잔여 - standalone REST가 spark.authenticate를 무시함
abraxaslabs.tech · github.com/abraxas · @abraxas_null · [email protected] · spark-rest-auth-bypass
분류: 권한 잔존 도달 범위: 원격
Apache Spark 4.2.0 (32f72996) - Apache Software Foundation
Standalone Master REST는 기본 활성화된 포트 6066이며 spark.authenticate를 절대 읽지 않는다. CVE-2018-11770은 REST를 기본적으로 비활성화하고, REST가 켜진 상태에서 RPC 시크릿이 설정되면 fail-closed로 동작하겠다고 약속했다. 이 핀은 둘 다 뒤집었다. MASTER_REST_SERVER_ENABLED는 createWithDefault(true)이다. 필터는 MASTER_REST_SERVER_FILTERS뿐이며 기본값은 Nil이다. 인증되지 않은 POST /v1/submissions/create가 공격자의 main을 Worker UID로 실행한다. Worker가 _SPARK_AUTH_SECRET을 주입하므로, 2018년의 "executor 없는 driver" 제한은 성립하지 않는다.
이것은 11770의 잔존이며, 새로운 CVE-2020-9480 RCE가 아니다. RPC 7077은 여전히 AuthServerBootstrap을 설치한다. spark.authenticate=false인 클러스터에서의 job submit은 문서화된 기본 동작이며 이 버그가 아니다.
| ID | 아직 CVE 없음 |
| 분류 | 권한 잔존 (CVE-2018-11770의 잔존) |
| 도달 범위 | 원격 (standalone Master 6066에 대한 인증되지 않은 HTTP) |
| CWE | CWE-306, CWE-287 |
| CVSS | High: 8.8 CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H |
| 제품 | Apache Spark |
| 영향받음 | 4.2.0 (32f7299601108917fb01920a54e084595b7b3bf8) standalone Master REST |
| 인증 | REST에는 없음. 운영자가 spark.authenticate=true를 설정함. REST는 기본값으로 남음. |
| 라이선스 | GNU Affero GPL v3.0 |
| 랩 | 127.0.0.1:18900 전용. 공식 spark:4.2.0 이미지. |
나는 태그 v4.2.0을 핀했고, 32f7299601108917fb01920a54e084595b7b3bf8 (2026-07-11, v4.2.0-rc6)을 peel했다. master가 아니다. 4.3 RC도 아니다.
6066의 standalone Master REST에 도달한다. Authorization 헤더 없음. spark.authenticate는 켜져 있음. spark.master.rest.filters는 설정되지 않음. 최소 하나의 Worker가 살아 있음.
| 메서드 | 싱크 | 권한 |
|---|---|---|
인증 없는 POST /v1/submissions/create | RequestSubmitDriver (Master.scala:402-420) 이후 Worker DriverWrapper classForName(mainClass).main | 무결성 (랩 입증): 공격자의 mainClass를 Worker UID로 실행. 랩: driver RUNNING, witness 파일. |
동일한 create; Worker CommandUtils.buildLocalCommand | driver 환경변수 _SPARK_AUTH_SECRET | 무결성 (랩 입증): driver가 인증된 RPC 클러스터에 SASL로 참여 가능. 랩: injected=yes. |
인증 없는 GET /v1/submissions/status/{id} | RequestDriverStatus (Master.scala:489-503) | 정찰 (생성된 id에 대해 랩 입증): driver 상태 / worker 호스트. |
인증 없는 GET /v1/submissions/readyz | RequestReadyz | 정찰 (랩 입증): Master가 STANDBY가 아님. |
인증 없는 POST /v1/submissions/kill/{id} | RequestKillDriver (Master.scala:422-453) | 무결성 + 가용성 (추론): 다른 테넌트의 standalone driver 중지. 동일한 인증 없는 서블릿 배선; 검증되지 않음. |
인증 없는 POST /v1/submissions/killall | RequestKillAllDrivers (Master.scala:455-478) | 가용성 (추론): 모든 대기/실행 중인 standalone driver 종료. 검증되지 않음. |
인증 없는 POST /v1/submissions/clear | RequestClearCompletedDriversAndApps | 무결성 (추론): 완료된 driver/app 장부 삭제. 검증되지 않음. |
랩 입증 vs 추론: create, secret 주입, 자체 id status, readyz는 랩. kill / killall / clear는 동일한 인증 없는 서블릿 맵에서 추론됨.
요구사항: standalone Master (YARN/K8s 아님). 운영자가 spark.authenticate=true를 설정함. REST는 기본값으로 남음 (spark.master.rest.enabled true, spark.master.rest.filters 미설정). Master 6066으로의 네트워크 경로. 최소 하나의 Worker. 문서화된 개방 클러스터(spark.authenticate=false)가 아님.
| 표면 | 이유 |
|---|---|
spark.authenticate=true인 RPC 7077 | AuthServerBootstrap이 여전히 필요. CVE-2020-9480 수신 경로는 닫힌 채로 유지. 새로운 9480 RCE가 아님. |
| 설정 시 JWSFilter | spark.master.rest.filters=org.apache.spark.ui.JWSFilter와 secretKey. JWT 없이는 403을 테스트함. 옵트인. 기본값 Nil. |
UI doAs | 여전히 admin 필요. REST는 UI 필터를 상속하지 않음. |
| CVE-2022-33891 UI shell | id -Gn argv 잔존은 이 핀에서 닫힘. |
| YARN / Kubernetes submit | 이 REST 서버는 standalone Master 전용. |
기본 spark.authenticate=false job submit | FAQ: 설계상. 이 잔존이 아님. |
| Mesos REST | Spark 4.0에서 제거됨. |
CLI spark-submit 기본 | 여전히 RPC 7077 사용 (useRest 문자열 기본값 false). spark://에서 --kill / --status는 항상 REST 사용. 잔존은 서버 리스너임. |
CVE-2018-11770의 코드 수정(SPARK-25088)은: REST 기본 비활성화, 그리고 REST가 켜진 상태에서 spark.authenticate.secret이 설정되면 Master가 fail-closed하도록 require. 이 핀:
package.scala:2045-2048. 문서: "Since Spark 4.1, Spark Master daemon provides REST API by default."Master.scala에서 fail-closed 부재. 테스트 SPARK-57451: Allows REST server and spark.authenticate.secret to be enabled together (MasterSuite.scala:253-261)는 시작이 반드시 성공해야 한다고 단언함.NETWORK_AUTH_ENABLED / AUTH_SECRET을 읽지 않음. addFilters는 기본값 Nil인 spark.master.rest.filters만 적용함.CVE-2018-17190 / FAQ("spark.authenticate 활성화")를 따른 운영자도 여전히 6066에서 인증 없는 HTTP job submit을 갖는다.
잘못된 방향: 개방 클러스터에서의 인증 없는 job submit을 CVE로 취급; 이것이 RPC 7077에서 9480을 재개방한다고 주장; JWSFilter 기본 비활성화를 잔존으로 취급하는 대신 spark.authenticate가 REST에 매핑되지 않는 것을 잔존으로 봄; 4.3 RC를 핀함.
연출: 리버스 셸. 오라클은 witness 문자열과 injected=yes.
python3 spark-rest-auth-bypass-Abraxas-Labs.py
또는
cd lab
./run.sh
루프백 127.0.0.1:18900이 컨테이너 6066에 게시됨. Compose 프로젝트 spark-rest-auth-bypass. 공식 spark:4.2.0 이미지. Master와 Worker 모두 spark.authenticate=true와 spark.authenticate.secret을 설정. REST 필터 미설정. Witness SPARK-REST-AUTH-BYPASS-WITNESS. 마지막 줄:
SUCCESS SPARK-REST-AUTH-BYPASS create-http=200 success=true submissionId=driver-20261012231831-0000 injected=yes state=RUNNING SPARK-REST-AUTH-BYPASS-WITNESS