박연오

기술 분석 · Apache DolphinScheduler

작업 정의 수정의 프로젝트 간 권한 검사 우회

CVE-2026-66084에서 빠진 작업 정의와 허가된 프로젝트의 관계 검증, 그리고 DolphinScheduler의 구형 update-with-upstream API 제거를 분석합니다.

프로젝트 권한이 모든 작업에 대한 권한은 아닙니다

한 프로젝트에 쓰기 권한을 가진 인증된 DolphinScheduler 사용자가 자신의 권한 밖에 있는 프로젝트의 작업 정의를 수정할 수 있었습니다. Apache는 2026년 10월 8일 작업 정의 with-upstream 기능의 인가 우회를 CVE-2026-66084로 공개했습니다. 공개 권고문은 선택된 작업이 권한을 확인한 프로젝트에 속하는지 검사하지 않는 점을 원인으로 설명합니다. Apache 권고문.

조사에서 확인하려던 것은 권한을 검사한 프로젝트와 수정할 작업이 속한 프로젝트가 일치하는지였습니다. 보호된 프로젝트를 가진 Alice와 별도 프로젝트에 정당한 쓰기 권한을 가진 일반 사용자 Mallory를 생각해 보겠습니다. Mallory는 자신의 인증된 계정을 사용합니다. 자기 프로젝트의 작업을 편집할 권한이 Alice의 작업 정의에 대한 권한으로 이어져서는 안 됩니다. 당시 조사에서는 대상 작업 식별자를 알고 있다고 가정했으며, 이를 독립적으로 알아내는 방법까지 입증하지는 않았습니다.

애플리케이션 관찰은 직접 빌드한 DolphinScheduler 3.4.2의 로컬 독립 실행형 Docker 환경에서 얻었으며 인메모리 H2를 사용했습니다. 앞선 서비스 수준 검사는 배포된 3.4.2 패키지가 아닌 개발 스냅샷을 사용했습니다. 이 글을 위해 보존된 관찰 기록, 3.4.2 소스와 3.4.3에 반영된 제거 변경을 검토했습니다. 새로 재현하거나 수정 릴리스를 실행하지는 않았습니다.

권한 검사 이후 실제 작업을 따라가기

3.4.2의 TaskDefinitionController.updateTaskWithUpstream은 서비스로 처리를 넘기고, 서비스는 updateTask를 호출합니다. 이 보조 함수는 dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/TaskDefinitionServiceImpl.java에서 다음과 같이 시작합니다.

Project project = projectDao.queryByCode(projectCode);

// check if user have write perm for project
projectService.checkHasProjectWritePermissionThrowException(loginUser, project);

TaskDefinition taskDefinition = taskDefinitionDao.queryByCode(taskCode);

권한 검사와 조회는 각각 독립적으로 전달된 값을 다룹니다. 첫 번째는 요청된 프로젝트에 대한 쓰기 권한을 확인합니다. 두 번째는 작업 코드를 통해 작업을 찾습니다. 하위 매퍼는 이 조회를 프로젝트 범위로 제한하지 않습니다.

따라서 관계를 하나 더 확인해야 합니다. 해당 작업은 권한이 허가된 프로젝트에 속할까요? 검토한 메서드는 taskDefinitionDao.updateById(taskDefinitionToUpdate)에 도달하기 전에 이 관계를 확인하지 않습니다. 권한은 다른 프로젝트에 대해 검사했어도, 코드로 선택한 작업은 저장 작업에 도달할 수 있습니다. 수정 구현.

기존의 다른 검사도 여전히 의미가 있습니다. 작업이 존재해야 하고, 온라인 상태와 실행 유형에 따라 수정이 차단될 수 있으며, 전달된 정의가 작업 매개변수 검사를 통과해야 하고, 버전 정보도 존재해야 합니다. 이 검사들은 어떤 수정이 성공할 수 있는지 제한합니다. 하지만 권한을 확인한 프로젝트와 선택된 작업 사이의 관계를 검증하지는 않습니다. 유효한 작업 입력과 수정 가능한 생명주기 상태는 여전히 전제 조건입니다.

당시 애플리케이션 관찰로 구별한 것

애플리케이션이 수정을 무시했다면 성공 응답만으로는 잘못된 결론에 이를 수 있습니다. 당시 로컬 조사에서는 작업 전후의 상태를 확인했습니다.

과거 검증의 비교 조건 기록된 관찰 뒷받침하는 내용
일반 사용자의 프로젝트 범위 조회 보호된 작업이 반환되지 않았습니다. 해당 프로젝트 맥락에서는 작업에 접근할 수 없었습니다.
관리자의 기준 상태 확인 대상 작업이 존재했고 정의를 읽을 수 있었습니다. 앞선 거부는 대상이 존재하지 않아서 발생한 것이 아니었습니다.
수정 이후 애플리케이션 확인 작업이 성공했고 변경된 정의가 이후 조회에서 확인됐습니다. 성공 메시지를 넘어 작업 정의의 변경이 저장됐습니다.

이는 보존된 애플리케이션 응답을 요약한 것이며, 새로운 실행 결과나 별도로 수집한 데이터베이스 행의 변경 전후 비교가 아닙니다. 여기서 도출하는 결론은 권한 없는 작업 정의 변경입니다.

다른 설명으로는 프로젝트를 넘는 편집 권한이 의도된 정책일 가능성이 있었습니다. 일반 조회 결과만으로 이 정책 문제까지 판단할 수는 없었습니다. Apache의 공개된 CVE 기록은 작업과 프로젝트의 관계 확인 누락을 잘못된 인가로 분류하며, 이 작업에도 프로젝트 제한이 적용돼야 했음을 확인합니다.

작업 실행을 가정하지 않는 무결성 영향

Apache는 권한 없는 작업 정의 및 선행 의존 관계 변경으로 워크플로 무결성이 훼손되고 작업 실행이 방해받을 수 있다고 설명합니다. 로컬 관찰은 권한 없는 수정을 뒷받침하지만, 변경된 작업의 실행, 원격 코드 실행이나 시스템 장악을 입증하지는 않습니다. 필요한 권한과 알려진 식별자는 조사 조건에 포함됐으며, 실제 운영 환경에서 이 조건들이 얼마나 흔한지는 측정하지 않았습니다.

Apache는 수치 점수 없이 Moderate로 평가했고, CISA-ADP는 High 8.1 (CVSS 3.1)을 부여했습니다. 이는 공개된 CVE 데이터에 기록된 별개의 평가이며, 수치 평가는 로컬 관찰의 범위를 넓히지 않습니다.

구형 수정 경로 제거

Apache는 3.4.3 이전 버전이 영향받는다고 밝히고 3.4.3으로 업그레이드할 것을 권고합니다. 소스 검토를 통해 변경 방식도 구체적으로 확인할 수 있습니다. 업스트림 제거 변경은 update-with-upstream 컨트롤러 메서드와 이를 지원하던 서비스 구현을 삭제합니다. 3.4.3 업그레이드 안내에도 API 폐지가 기록돼 있으며, 릴리스 소스에 이 제거가 반영돼 있습니다.

이 변경은 검토한 진입점을 없애 해당 경로를 닫습니다. 기존 메서드에 프로젝트 일치 검사를 추가한 수정으로 설명해서는 안 됩니다. 소스에서는 3.4.3의 제거를 확인했지만, 이 글에서 수정 릴리스의 런타임 동작을 독립적으로 시험하지는 않았습니다. 이번 검토는 3.4.2와 3.4.3을 직접 비교했으며, 최초 영향 릴리스를 독립적으로 확정하거나 이전 릴리스 계열을 검증하지는 않았습니다.

후속 회귀 검사에서는 폐지된 경로가 상태를 바꾸지 못하는지, 지원되는 편집 기능에서 정당한 동일 프로젝트 수정이 유지되는지, 다른 프로젝트의 작업 식별자가 보호된 정의와 의존 관계를 변경하지 못하는지 확인할 수 있습니다. 이는 제안하는 검사이지 실행 결과가 아닙니다. 계속 유지해야 할 요건은 지원되는 작업이 상태를 바꾸기 전에 실제 작업과 그 프로젝트에 대한 권한을 확인하는 것입니다.