🇰🇷 한글 설명
pgAdmin 4의 SQL Editor 모듈 내 두 개의 엔드포인트에서 인증 누락 결함이 발견되었습니다. 공격자가 서버 측 세션 파일에 악성 피클(pickle) 페이로드를 삽입할 수 있는 환경이라면, 인증 없이 원격 코드 실행(RCE)이 가능합니다.
💡 쉬운 설명
로그인하지 않은 사용자도 특정 명령을 실행할 수 있는 보안 구멍이 발견되었습니다. 만약 해커가 이미 서버의 비밀 키를 알고 있다면, 이 구멍을 통해 컴퓨터를 마음대로 조종할 수 있습니다.
🇺🇸 원문 (English)
Two state-mutating endpoints in pgAdmin 4's SQL Editor blueprint -- DELETE /sqleditor/close/<trans_id> and POST /sqleditor/initialize/sqleditor/update_connection/<sgid>/<sid>/<did> -- were the only routes in the module missing the @pga_login_required decorator. Both reach a pickle.loads sink on session['gridData'][<trans_id>]['command_obj']: the close endpoint via close_sqleditor_session(), and update_sqleditor_connection via check_transaction_status(). In server mode these endpoints were reachable without any authenticated pgAdmin session.
The defect is a missing-authentication-on-critical-function (CWE-306) wrapper around a deserialization-of-untrusted-data sink (CWE-502). Exploiting it for remote code execution requires the attacker to also forge a server-side session file whose gridData entry contains a malicious pickle payload, which in turn requires both (a) knowledge of pgAdmin's Flask SECRET_KEY (no chain to leak it is described here -- the attacker must already possess it) and (b) write access to pgAdmin's sessions/ directory on the host. Neither precondition is granted by this defect on its own. When those preconditions are met from another channel (misconfigured deployment, prior compromise, leaked configuration), the missing auth gate is the final hop that turns an existing partial compromise into unauthenticated code execution in the pgAdmin process -- and, by extension, on the host under whatever account runs pgAdmin.
Fix is a one-line @pga_login_required decorator on each of the two endpoints, matching the convention used by every other route in the module. The is_authenticated / MFA chain now runs before the trans_id is dereferenced, so an unauthenticated request is rejected before reaching the deserialization path.
The defect is server-mode only. In DESKTOP mode pgAdmin's before_request hook re-authenticates DESKTOP_USER on every request, so no endpoint can be exercised in an unauthenticated state and no auth decorator (or its absence) is meaningful. The accompanying regression test mirrors the attacker's path -- harvests an X-pgA-CSRFToken from GET /login and replays it against both endpoints -- and self-skips outside server mode for that reason; it is wired into the existing server-mode CI workflow alongside the data-isolation tests.
This issue affects pgAdmin 4: from 6.9 before 9.16.
📍 영향받는 시스템
pgAdmin 4 버전 6.9부터 9.16 미만 버전 (Server mode 전용)
⚔️ 공격 벡터
인증이 누락된 엔드포인트를 통해 조작된 세션 데이터를 전달하여 피클 역직렬화(Pickle Deserialization) 공격 수행
🛡️ 대응 방법
pgAdmin 4를 최신 버전(9.16 이상)으로 업데이트하거나 해당 엔드포인트에 @pga_login_required 데코레이터를 적용
🔧 검증 코드
출력된 버전이 6.9 이상 9.16 미만인지 확인하여 취약 여부를 판단합니다.
python3 -c "import pgadmin; print(pgadmin.__version__)" 2>/dev/null || echo 'Version check failed'