Skip to content
KitploitKITPLOIT
도구블로그
Log in
제출
도구블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2017-11610 — CVE-2017-11610(Supervisord XML-RPC RCE)에 대한 단계별 익스플로잇 라이트업으로, 공격 표면 분석, 네임스페이스 트래버설 발견, Docker 랩 환경에서의 사후 익스플로잇 기법을 다룹니다. | Kitploit
도구/GitHubGitHub/dungsocool/cve-2017-11610
Vulnerability AnalysisExploitationWeb Application ExploitationPenetration TestingLearning & EducationRemote Access ToolLabs & Practice
GitHubdungsocool/cve-2017-11610

CVE-2017-11610

CVE-2017-11610(Supervisord XML-RPC RCE)에 대한 단계별 익스플로잇 라이트업으로, 공격 표면 분석, 네임스페이스 트래버설 발견, Docker 랩 환경에서의 사후 익스플로잇 기법을 다룹니다.

저장소 보기
44개월 전아직 검토되지 않음

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

LAB 3- CVE-2017-11610

I. 시스템 분석

Docker 환경에서 공격 표면 식별

환경에서 실행 중인 것부터 시작합니다. 모든 활성 컨테이너를 나열합니다:``` docker ps-a

![image.png](https://assets.kitploit.com/production/public/readmes/35745/528df65b5736399b78ecfb94ba4506b37ef721e8e31f8247ad7d022a4e54124b.png)

**피해자는 단일 포트를 노출합니다: `9001`**.

포트 9001은 표준 웹 앱이 아닙니다. **포트 데이터베이스**를 조회해 보면 이 포트가 **Supervisord**(IANA에 따르면 ETL Service Manager), Tor 프록시 또는 기타 내부 서비스와 연관될 수 있음을 알 수 있습니다. 그러나 포트 번호만으로 결론을 내릴 수는 없습니다.

⇒ 응답을 읽기 위해 curl로 직접 요청하고, 추가 정보를 수집하기 위해 웹 GUI에도 접속합니다.```
curl -i http://192.168.3.137:9001/

image.png

image.png

응답 분석:

  • 반환된 응답에는 Server: Medusa/1.12와 제목 Supervisor Status가 표시됩니다.

→ 이는 Tor나 다른 서비스가 아니라 Supervisord임을 확인합니다.

  • 로그인 양식이나 인증 프롬프트가 없음 ⇒ 접근에 인증이 필요하지 않음
  • 노출된 기능: REFRESH, RESTART ALL, STOP ALL
  • 공격 표면 평가:

Supervisord는 Linux의 프로세스 관리자입니다. port 9001이 비밀번호 없이 네트워크에 노출되어 있다면 이는 위험한 구성입니다. 공격자는 서비스를 확인하고 프로세스를 재시작/중지할 수 있으며, 특정 구성에서는 관리 대상 프로그램을 수정하거나 제어할 권한이 있는 경우 명령 실행을 위해 이를 악용할 수 있습니다.

분석 결론: 대상이 Supervisord 관리 인터페이스를 포트 9001에서 네트워크에 노출하고 있음을 확인할 수 있습니다. 이는 표준 웹 서비스가 아니라 프로세스를 모니터링하고 제어하는 데 사용되는 관리 인터페이스입니다. 이 인터페이스에 접근할 수 있는 능력은 인증 없이도 공격자가 관리 대상 서비스의 상태를 확인하거나 상호작용할 수 있는 위험을 만듭니다.

그러나 표시되는 UI와 그 이면의 제어 메커니즘을 구분해야 합니다. REFRESH, RESTART ALL, STOP ALL 같은 버튼은 프론트엔드에서 요청을 독립적으로 처리하지 않으며, 대신 Supervisord의 인터페이스/백엔드를 호출하여 상태를 검색하거나 프로세스 제어 명령을 전송해야 합니다. 따라서 웹 UI가 노출된 것을 확인한 후, 다음 분석 단계는 웹 UI 뒤에 기본 제어 인터페이스가 존재하는지와 인증이 필요한지를 결정하는 것입니다.

⇒ 생각: 웹 UI 뒤의 제어 인터페이스가 존재하는지, 그리고 인증이 필요한지 확인해야 합니다.

XML-RPC 프로토콜 확인

image.png

Supervisor의 문서에 따르면 [inet_http_server]는 TCP 소켓에서 수신 대기하는 HTTP 서버입니다. 이 인터페이스는 기본적으로 활성화되지 않으며, 신뢰할 수 있는 환경에서만 사용해야 하고, 암호화를 지원하지 않으며, username/password가 구성되지 않는 한 기본 인증이 없습니다.

문서는 또한 [inet_http_server]의 포트가 HTTP/XML-RPC 요청을 수신하는 데 사용된다고 설명합니다. supervisorctl은 이 포트를 통해 XML-RPC를 사용하여 supervisord와 통신합니다. 이는 실습 환경에서의 관찰 결과와 일치합니다. 컨테이너가 0.0.0.0:9001->9001/tcp를 노출하고 있고, 웹 UI에 인증 없이 접근할 수 있으며, 표시된 버전이 Supervisor 3.3.2입니다.

따라서 포트 9001의 웹 UI를 확인한 후 다음 단계는 XML-RPC 엔드포인트 /RPC2를 검사하는 것입니다. Supervisord의 공식 메커니즘에 따라 다음 목표를 검증해야 합니다:

  • /RPC2가 존재하는지 여부.
  • 엔드포인트에 인증이 필요한지 여부.
  • supervisor.getState 또는 system.listMethods 같은 비파괴적 메서드를 호출할 수 있는지 여부.
  • 인증 없이 RPC를 호출할 수 있다면, 위험 수준은 노출된 웹 UI에서 노출된 프로세스 제어 API로 상승합니다.

엔드포인트가 살아 있는지 확인합니다:``` curl -i -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.getState'
http://192.168.3.137:9001/RPC2

![image.png](https://assets.kitploit.com/production/public/readmes/35745/f97bef2d42858c30a246414af228b739e3a49e9ed633b48e68f5702db1b289af.png)

결과는 `401 Unauthorized`나 `403 Forbidden`이 아닌 `HTTP/1.1 200 OK`를 반환하며, 이는 요청이 자격 증명 없이 서버에서 수락되었음을 보여줍니다. 응답은 XML-RPC `<methodResponse>` 형식이며 `statename=RUNNING` 및 `statecode=1`을 포함하므로 `/RPC2` 엔드포인트가 활성 상태이고 `supervisor.getState` 메서드가 성공적으로 실행되었음을 입증합니다.

**⇒ 생각:** 공격 표면은 더 이상 Web UI로 제한되지 않고, 데몬/프로세스 제어 명령이 처리되는 XML-RPC API로 확장되었습니다. 여기서 다음 분석 방향은 **XML-RPC**에서 `methodName`을 **Supervisor가 어떻게 처리하는지 확인**하여, 현재 대상이 이 메서드의 디스패치/조회 메커니즘에 내재된 **CVE-2017-11610의 동작을 보이는지** 판단하는 것입니다. 이것이 **CVE-2017-11610**인지 결론을 내리려면 이를 검증해야 합니다.

### **XML-RPC에서 메서드 이름 처리 분석**

이전 단계에서 우리는 `/RPC2` 엔드포인트를 통해 `supervisor.getState` 메서드를 성공적으로 호출했습니다. 이는 다음 질문을 제기합니다: 문자열 기반의 `methodName`을 수신할 때, Supervisord는 그 문자열을 내부 Python 함수에 어떻게 매핑할까요?

XML-RPC에서 메서드는 일반적으로 네임스페이스를 활용합니다. 예를 들어:

- `supervisor.getState`
- `supervisor.stopProcess`
- `supervisor.getAllProcessInfo`

논리적으로, 서버는 `methodName` 문자열을 받아 마침표 `.`로 분할하고, 등록된 핸들러 내에서 해당 객체/함수를 검색합니다.

의사 코드는 다음과 같이 이해할 수 있습니다:

``````python
# Pseudo-code simulating the dispatch method concept in XML-RPC
def dispatch(method_name, params):
    parts = method_name.split(".")          # ["supervisor", "getState"]

    obj = registered_handlers[parts[0]]     # get namespace "supervisor"

    for attr in parts[1:]:
        obj = getattr(obj, attr)            # lookup the next attribute

    return obj(*params)                     # call the final function

For standard methods like supervisor.getState, this mechanism functions normally: the server retrieves the supervisor handler, then calls the getState function. However, the core issue of CVE-2017-11610 is that this lookup mechanism does not sufficiently restrict the attributes allowed to be accessed. If an attacker controls the methodName, they can not only call public methods like getState, but also traverse deeper into the internal objects/modules reachable from the supervisor handler.

In other words, the dot . in methodName is not just used to invoke valid methods, but can be abused to traverse object attributes.

This establishes our exploitation path:

supervisor → supervisord → options → warnings → linecache → os → system

The core idea is to start from the supervisor handler, follow attributes to the daemon's internal objects, and then leverage pre-imported Python modules to reach os.system. If os.system can be called, the attacker can execute system commands with the privileges of the supervisord process.

Thus, the attack chain follows this logic:

/RPC2 accepts unauthenticated method calls → inspect how XML-RPC dispatches methodName → discover methodName can traverse object attributes → leads to calling os.system.

II. 악용

네임스페이스 순회 동작 확인

첫 번째로, 서버가 실제로 내부 속성 탐색을 허용하는지 확인해야 합니다. 평소보다 더 긴 method name을 호출해 보겠습니다. 서버가 "method not found" 오류를 반환하면 필터가 활성화된 것이고, 다른 오류를 반환하거나(성공하거나) 하면 순회가 동작하는 것입니다.

생각: supervisor.getState가 동작한다는 것은 이미 알고 있습니다. 한 단계 더 깊이 들어가는 supervisor.supervisord를 시도했을 때 서버가 unknown method 오류를 반환하지 않는다면, 실제로 화이트리스트 없이 재귀적 getattr을 사용하고 있다는 뜻입니다.

We know XML-RPC is a remote procedure call protocol over HTTP, with data encoded in XML. Each request consists of only 3 fixed components:```

FUNCTION_NAME VALUE ``` 간단한 구조입니다 — ``과 ``만 교체하면 됩니다. 함수에 매개변수가 필요하지 않으면 ``를 비워 두세요. 함수에 문자열이 필요하면 `...` 안에 감싸면 됩니다. 이것은 비밀 지식이 아닙니다 — XML-RPC RFC를 읽으면 이 내용이 자세히 설명되어 있습니다.

⇒ 응용: 평소보다 더 긴 methodName을 호출하여 네임스페이스 순회를 확인해 보세요:``` curl -s -X POST -H "Content-Type: text/xml"
-d 'supervisor.supervisord.options'
http://192.168.3.137:9001/RPC2

![image.png](https://assets.kitploit.com/production/public/readmes/35745/2e90c7be7c467c3e59434434765b5a823150ebdd7206775390b53b92532b5254.png)

결과는 표준 `unknown method` 오류 대신 `HTTP 500 Internal Server Error`를 반환합니다. 이는 서버가 유효한 네임스페이스 수준에서 `methodName`을 차단하지 않고, 디스패칭 중에 계속해서 `supervisor.supervisord.options` 체인을 처리했음을 나타냅니다. 즉, 요청이 속성 조회 메커니즘 깊숙이 침투했으며, 오류는 확인된 객체가 메서드로 호출 가능하지 않았을 때 이후 단계에서 발생했습니다. 이는 `methodName`을 통한 네임스페이스 탐색이 활성화되어 있다는 명확한 신호입니다.

### **명령 실행 함수로 가는 경로 찾기**

탐색은 작동하고 있습니다. 다음 단계는 **시스템 명령을 실행할 수 있는 호출 가능 함수로 끝나는 속성 체인을 찾는** 것입니다. Python에서 확인하기 가장 쉬운 대상은 `os.system()`입니다. 그러나 대상에는 **셸이 없고** 컨테이너의 **소스/런타임 객체를 직접 읽을 수 없습니다.** 따라서 **Python의 import 메커니즘에서 추론**하고 **로컬에서 먼저 의존성을 검증**해야 합니다.

확인할 체인은 다음과 같습니다:

`supervisor` → `supervisord` → `options` → `warnings` → `linecache` → `os` → `system`
도구 다운로드