Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

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

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

피드문의개인정보© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
CVE-2022-46169 — CVE-2022-46169에 대한 단계별 분석: 인증 우회 및 명령 주입을 통한 Cacti의 인증되지 않은 원격 코드 실행으로, Docker 랩 설정 및 악용 연습이 포함됩니다. | Kitploit
도구/GitHubGitHub/hpt-intern-task-submission/cve-2022-46169
Vulnerability AnalysisExploitationWeb Application ExploitationCommand and ControlAuthenticationLearning & EducationLabs & Practice
GitHubhpt-intern-task-submission/cve-2022-46169

CVE-2022-46169

CVE-2022-46169에 대한 단계별 분석: 인증 우회 및 명령 주입을 통한 Cacti의 인증되지 않은 원격 코드 실행으로, Docker 랩 설정 및 악용 연습이 포함됩니다.

저장소 보기
242년 전아직 검토되지 않음

인기

모두 보기 →

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

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

CVE-2022-46169 - Cacti의 비인증 원격 코드 실행

Cacti란 무엇이며 어떤 취약점이 있나요?

Cacti는 PHP, MySQL/MariaDB로 작성된 오픈소스 운영 모니터링 도구로, 사용자 친화적인 인터페이스를 제공합니다.

이 취약점은 2022년에 발견되었으며 1.2.23 이전의 모든 버전에 영향을 미칩니다. 이 버그는 RCE(원격 코드 실행)를 달성하기 위해 인증 우회와 명령 주입의 체인이 필요합니다.

실습 환경 구성

이 CVE 분석에서는 Docker에서 Cacti를 실행하고 VSCode를 사용하여 코드를 분석하겠습니다. 설정은 매우 간단합니다. 먼저 새 환경을 만들기 위한 docker-compose.yaml 파일이 필요합니다. 아래는 docker-compose.yaml 파일입니다:

version: '2'

services:

  

cacti:

image: "smcline06/cacti"

container_name: cacti

domainname: example.com

hostname: localhost

ports:

- "8088:80"

environment:

- DB_NAME=cacti_master

- DB_USER=cactiuser

- DB_PASS=cactipassword

- DB_HOST=db

- DB_PORT=3306

- DB_ROOT_PASS=rootpassword

- INITIALIZE_DB=1

- TZ=America/Los_Angeles

volumes:

- cacti-data:/cacti

- cacti-spine:/spine

- cacti-backups:/backups

links:

- db

  

db:

image: "mariadb:10.3"

container_name: cacti_db

domainname: example.com

hostname: db

ports:

- "3307:3306"  # Change host port to 3307

command:

- mysqld

- --character-set-server=utf8mb4

- --collation-server=utf8mb4_unicode_ci

- --max_connections=200

- --max_heap_table_size=128M

- --max_allowed_packet=32M

- --tmp_table_size=128M

- --join_buffer_size=128M

- --innodb_buffer_pool_size=1G

- --innodb_doublewrite=ON

- --innodb_flush_log_at_timeout=3

- --innodb_read_io_threads=32

- --innodb_write_io_threads=16

- --innodb_buffer_pool_instances=9

- --innodb_file_format=Barracuda

- --innodb_large_prefix=1

- --innodb_io_capacity=5000

- --innodb_io_capacity_max=10000

environment:

- MYSQL_ROOT_PASSWORD=User@123

- TZ=America/Los_Angeles

volumes:

- cacti-db:/var/lib/mysql

  

volumes:

cacti-db:

cacti-data:

cacti-spine:

cacti-backups:

파일을 만든 후 명령줄을 열고 파일 디렉터리로 이동한 다음 docker-compose up -d 명령을 실행하고, 브라우저를 열어 localhost:8088에 접속합니다. 처음에는 로그인 페이지가 표시됩니다:

login_page

기본 자격 증명은 admin/admin입니다. 설정 과정은 아래 사진을 통해 확인할 수 있습니다:

new_password

새 비밀번호 생성

1 2 1 1 1 1 1 1 1 1 1

설치가 완료되면 다음과 같은 콘솔 화면이 표시됩니다.

console

이제 취약점 분석을 시작해 보겠습니다. 알다시피 취약한 파일은 remote_agent.php이므로 브라우저에서 해당 파일에 접속해 보겠습니다.

remote_agent

파일에 접근할 권한이 없다는 메시지가 표시됩니다. 이제 이 파일의 소스 코드를 확인할 차례입니다.

remote_client_authorized

remote_client_authorized() 함수를 호출하여 검사합니다. 그 함수를 자세히 살펴보겠습니다.

remote_client_authorized_dive_deep

먼저 서버는 get_client_addr() 함수를 통해 우리의 IP 주소를 가져온 다음, gethostbyaddr() 함수를 사용하여 IP를 호스트 이름으로 변환합니다. 그런 다음 서버는 poller 테이블에서 사용 가능한 모든 pollers를 가져와 각 poller's hostname을 IP 주소에서 변환된 hostname과 비교합니다. 여기 get_client_addr() 내부에 우회 지점이 있습니다:

get_client_addr

서버가 다음 헤더 중 하나를 통해 IP 주소를 검색한다는 것을 알 수 있습니다:

-   X-Forwarded-For
-   X-Client-IP
-   X-Real-IP
-   X-ProxyUser-Ip
-   CF-Connecting-IP
-   True-Client-IP
-   HTTP_X_FORWARDED
-   HTTP_X_FORWARDED_FOR
-   HTTP_X_CLUSTER_CLIENT_IP
-   HTTP_FORWARDED_FOR
-   HTTP_FORWARDED
-   HTTP_CLIENT_IP
-   REMOTE_ADDR

이를 통해 우리는 IP 주소 값을 완전히 제어할 수 있습니다. 이 경우 X-Forwarded-For 헤더를 사용하여 IP를 유효한 IP로 스푸핑할 수 있으며, 이를 통해 인증을 우회할 수 있습니다. X-Forwarded-For 헤더는 클라이언트와 서버 사이에 프록시나 로드 밸런서가 있을 때 원래 IP 주소를 식별하는 데 자주 사용됩니다. 그러나 이는 공격자가 악용할 수 있는 공격 표면이 됩니다. Cacti를 로컬에서 실행 중이므로 localhost로 변환될 IP 주소, 즉 127.0.0.1을 지정해야 합니다.

IP_spoofed

이제 괜찮아 보이죠? 하지만 이건 시작에 불과합니다!!! 명령 주입에 성공하고 원격 코드 실행을 달성하려면 더 많은 코드 분석이 필요합니다. 인증이 완료된 후 프로그램은 다음 코드를 실행합니다.

switch_case_action

서버는 action 매개변수를 가져와 Switch/Case 문으로 들어갑니다. action의 값이 pollerdata이면 프로그램은 poll_for_data()를 호출합니다. 이 함수는 명령 주입에 취약하므로 주의 깊게 분석하겠습니다.

poll_for_data

이 함수는 사용자 요청 매개변수 local_data_ids, host_id, poller_id에서 받은 3개의 매개변수 $local_data_ids, $host_id, $poller_id를 사용합니다. 매개변수를 검색하는 함수의 차이점에 주목하세요. 하나는 get_filter_request_var이고 다른 하나는 get_nfilter_request_var입니다. 마지막 함수에는 n이 하나 더 있습니다. 이에 대해서는 나중에 더 자세히 다루겠습니다. 그 후 프로그램은 local_data_ids 매개변수를 제공했는지 확인하고, 각각을 반복하여 local_data_ids와 host_id를 기반으로 poller_item 테이블에서 데이터를 검색합니다. 쿼리 결과는 $items에 저장됩니다.

proc_open

쿼리가 결과를 반환하면 프로그램은 $items의 각 $item을 반복하고, $item['action']을 Switch 값으로 사용하는 Switch/Case 문으로 들어갑니다. 케이스가 많지만 우리가 조사해야 할 케이스는 action이 2와 같은 POLLER_ACTION_SCRIPT_PHP입니다.

POLLER_ACTION_SCRIPT_PHP

action이 2이면 프로그램은 exec()와 매우 유사한 proc_open() 명령을 실행하며, 완전히 우리가 제어하는 변수 중 하나인 $poller_id를 사용합니다. 더 명확하게 이해하기 위해 데이터베이스에 접속하여 poller_item 테이블의 내용을 확인해 보겠습니다.

poller_item_table

테이블에서 action = 2인 poller를 얻으려면 local_data_id를 브루트포스해야 한다는 것을 알 수 있습니다. 이는 실제 공격 환경에서도 적용됩니다. 기본적으로 cacti에는 action = 2인 poller가 없지만, device와 같은 새 템플릿을 추가하면 만들 수 있습니다.

create_device_1

create_device_2

create_device_3

새 device를 생성한 후 poller_item 테이블에 다시 접속하면 action = 2인 새 poller가 생성된 것을 확인할 수 있습니다.

create_device_4

도구 다운로드