Budibase: 앱 수준 인증이 누락된 공개 역할 할당 API를 통한 권한 에스컬레이션
Budibase 3.39.19(03fbabae4 커밋)는 공개 역할 할당 API의 권한 상승/승인 누락 결함의 영향을 받습니다. 앱 범위 빌더(전역 빌더나 관리자가 아닌 특정 앱만 빌드하는 사용자 - user.builder.apps = [appA])는 자신에게 테넌트의 다른 모든 앱에 대한 빌더 액세스 권한을 부여하거나 POST /api/public/v1/roles/sign을 호출하여 모든 앱에서 자신/모든 사용자에게 임의의 데이터 영역 역할(예: ADMIN)을 할당할 수 있습니다. 엔드포인트는 두 개의 전역 플래그(admin, builder)만 승인합니다. 앱별 appBuilder 및 role:{appId,roleId} 부여 벡터는 호출자가 대상 앱을 제어하는지 인증 확인하지 않고 백엔드로 전달됩니다. 축어적 인증 게이트 및 SDK 로직을 사용하여 현지 공인 연구실에서 재현되었습니다.
이는 전역 플래그만 검증한 커밋 d63d1d9054("인라인 공개 사용자 전역 역할 유효성 검사")의 역할 할당 강화에 대한 불완전한 수정입니다.
이 문제는 호출자가 부여하는 범위를 검증하는 대신 인증이 플래그 수준 허용 목록(admin/builder)으로 구현되기 때문에 발생합니다.
관련 코드 경로:
packages/server/src/api/controllers/public/globalRoleValidation.ts — validateGlobalRoleUpdate(ctx, roleUpdate)는 roleUpdate.admin(isAdmin 필요) 및 roleUpdate.builder(isGlobalBuilder 필요)만 확인합니다. GlobalRoleUpdate 인터페이스는 { builder?, admin? }; appBuilder 및 role은 참조되지 않습니다.packages/server/src/api/controllers/public/roles.ts — 할당()은 const { userIds, ...locationProps } = ctx.request.body를 수행합니다. verifyGlobalRoleUpdate(ctx, 할당Props); sdk.publicApi.roles.할당(userIds, 할당Props)을 기다립니다. appBuilder/role 소품은 검증되지 않은 상태로 전달됩니다.packages/pro/src/sdk/publicApi/roles.ts — 할당(): opts.appBuilder의 경우 user.builder = { apps: 기존.concat([getProdWorkspaceID(opts.appBuilder.appId)]) }를 설정합니다. opts.role의 경우 user.roles[getProdWorkspaceID(opts.role.appId)] = opts.role.roleId를 설정합니다. 호출자가 대상 앱을 빌드하는지, userIds가 임의 목록(bulkGet)인지 확인하지 마세요. 유일한 게이트는 'isExpandedPublicApiEnabled()' 라이선스 확인입니다.packages/server/src/api/routes/public/index.ts — applyAdminRoutes(roleEndpoints)는 만 middleware.builderOrAdmin(publicApi 없음, authorized(PermissionType.USER, …) 없음)을 연결합니다.packages/backend-core/src/middleware/builderOrAdmin.ts — workspaceId가 있는 경우 isBuilder(ctx.user, WorkspaceId)만 필요합니다. 공격자는 x-budibase-app-id를 자신의 앱(appA)으로 설정하므로 게이트가 통과됩니다.packages/backend-core/src/middleware/builderOnly.ts — 작업자에서 POST /api/global/self/api_key에는 hasBuilderPermissions(ctx.user)만 필요하며 이는 앱 범위 빌더에 해당되므로 공격자가 공개 API 키를 자체 발급할 수 있습니다.packages/shared-core/src/sdk/documents/users.ts — isGlobalBuilder는 앱 범위 빌더에 대해 false입니다(따라서 전역 builder 플래그가 올바르게 차단됨). 반면 isBuilder(user, appA) 및 hasBuilderPermissions(user)는 true입니다.공격 흐름:
appA 전용 앱 범위 빌더입니다(전역 빌더/관리자는 아님).POST /api/global/self/api_key(작업자) — hasBuilderPermissions를 통해 builderOnly를 전달 → 공격자가 공개 API 키를 얻습니다.x-budibase-app-id: <appA prod id> 및 본문 {"userIds":["<self>"],"appBuilder":{"appId":"<appB>"}}가 있는 POST /api/public/v1/roles/sign — builderOrAdmin이 (isBuilder(user, appA))를 통과하고 validateGlobalRoleUpdate가 무시됩니다. appBuilder, SDK는 appB를 user.builder.apps에 푸시합니다.appB의 빌더입니다(그리고 role 벡터를 통해 모든 앱에서 ADMIN과 같은 모든 데이터 역할을 설정할 수 있습니다).보안 경계 초과:
appA 빌더만 해당됩니다.appB(및 기타 앱) 빌더 → 모든 행 읽기/수정, 데이터 소스 구성 읽기, 저장된 데이터 소스 자격 증명 추출, 자동화 편집(bash/executeScript/executeQuery 단계 포함) 또한 모든 앱에서 임의의 데이터 역할 할당이 가능합니다.환경:
3.39.19, 03fbabae4 커밋isExpandedPublicApiEnabled)user.builder.apps=[appA])단계(단위 수준 증명, 라이선스 필요 없음 - 축어적 인증 게이트 + SDK 논리):
``배쉬 cd D:/CVE-Hunting/budibase-audit-output/lab 노드 하네스/verify-privesc-authz.cjs
2. 관찰 결과(증거: `evidence/lab-privesc-authz.log`):
``텍스트
[통과-검증] appBuilder:{appId:APP_B} -> 거부되지 않음
[PASS-VALIDATION] 역할:{appId:APP_B, roleId:'ADMIN'}-> 거부되지 않음
[차단된 403] builder:true(글로벌) -> 글로벌 빌더 또는 관리자만 ...
[차단 403] admin:true (전역) -> 전역 관리자만 ...
이후 : builder={"apps":["app_A...","app_B..."]} 역할={"app_B...":"ADMIN"}
isBuilder(공격자, APP_B) 이제 = true <-- APP_B 빌더로 에스컬레이션됨
단계(라이센스가 부여된 연구실을 위한 HTTP PoC — poc/privesc-roles-sign.sh):
``배쉬
컬 -X POST http://localhost:10000/api/global/self/api_key -H "쿠키: <공격자 세션>" -d '{}'
컬 -X POST http://localhost:10000/api/public/v1/roles/sign
-H "x-budibase-api-key: " -H "x-budibase-app-id: "
-H "콘텐츠 유형: 애플리케이션/json"
-d '{"userIds":[""],"appBuilder":{"appId":""}}'
3. 예상 결과:
``텍스트
요청은 거부되어야 합니다(403). 앱 범위 빌더는 요청을 승인할 수 없어야 합니다.
제어하지 않는 앱에 대한 자체 빌더/역할 액세스입니다. 대신 200을 반환하고
보조금이 적용됩니다.
증거 파일:
-증거/lab-privesc-authz.log
poc/verify-privesc-authz.cjs, poc/privesc-roles-sign.sh런타임 제한: 전체 HTTP 종단 간에는 비즈니스/기업 라이선스(isExpandedPublicApiEnabled)가 필요합니다. 라이센스가 깨지지 않았습니다. Verbatim Validation + SDK 로직을 통해 단위 레벨에서 인증 결함을 입증하고, 소스 리뷰를 통해 경로→검증→SDK 콜 체인을 독립적으로 검증했습니다.
라이선스가 부여된(비즈니스/엔터프라이즈) 테넌트의 단일 앱에서 앱 범위 빌더 역할을 맡은 공격자는 다음을 수행할 수 있습니다.
전역 admin/builder 플래그(검증된 플래그)를 부여하지 않습니다, 따라서 직접적인 전역 관리자 인수가 아닙니다. 그러나 교차 앱 빌더는 사실상 테넌트 전체 앱/데이터 평면 절충안입니다. 테스트 중에는 실제 비밀에 액세스하지 않았습니다. 연구실에서는 카나리아 전용 데이터를 사용했습니다.
왜 이 VPI인가 (설명가능 · 실험적)
VPI 산정 기준
| 영향도 | 88.00 |
| 악용 신호(추가 악용신호 없음) | ×1.00 |
| VPI | 88.00 |
VPI 공식 vpi-v1 기준