본문 바로가기

웹 개발

[9주차] 게시판 구현 #7 - File Upload 기능 만들기

이번에는 File Upload 기능을 구현해보겠습니다.

해킹에 있어 File Upload 라는 공격이 있는데, 차후에 이 공격을 기반으로 한 웹 쉘을 이용해 제가 만든 

웹 서버를 탈취해볼 계획입니다.

 

우선, 데이터베이스에 File 컬럼을 추가해줍니다.

 

여태까진 터미널에서 데이터베이스에 컬럼을 추가하거나 다양한 작업을 했지만,

이번에는 phpmyadmin을 한번 사용해보겠습니다.

 

localhost/phpmyadmin로 들어가면 접속할 수 있습니다.

 

원하는 테이블로 이동합니다.

 

스크롤을 내리면 몇 개의 컬럼을 추가할지, 어디에 추가할지 선택할 수 있습니다.

 

실행 버튼을 누릅니다.

 

 

그럼 이렇게 이름과 종류를 선택할 수 있습니다.

varchar(100)으로 설정해주고 NOT NULL을 위해 NULL 체크를 풀어주는 게 중요합니다.

저장을 누르면 잘 추가된 것을 볼 수 있습니다.

 

write.php 부분의 form 태그 부분입니다. 이 다음에 하단처럼 enctype 속성을 추가해줍니다.

 

이 속성을 추가하면 기존 POST 방식에서 업로드하는 용량보다 큰 용량을 업로드할 수 있게 됩니다.

   <form action="write_update.php" method="POSTE" enctype="multipart/form-data">

 

그 후, 파일을 선택하는 type="file"인 input 태그를 form 태그 밑에 추가해줍니다.

<input type="file" name="board_file" />

 

다음은 write_update.php 파일을 보겠습니다.

 

SQL문에 file 컬럼을 추가해줍니다.

 

그 후, 아래의 코드를 추가해줍니다.

 

php에 존재하는 초전역변수 $_FILES 를 사용할 것입니다

 

$_FILES['userfile']['name']  클라이언트 머신에 존재하는 파일의 원래 이름. 
$_FILES['userfile']['type']  브라우저가 이 정보를 제공할 경우에, 파일의 mime 형식. 예를 들면 "image/gif". 
$_FILES['userfile']['size']  업로드된 파일의 바이트로 표현한 크기. 
$_FILES['userfile']['tmp_name']  서버에 저장된 업로드된 파일의 임시 파일 이름. 
$_FILES['userfile']['error']  파일 업로드에 관련한 에러 코드. ['error']는 PHP 4.2.0에서 추가되었습니다. 

 

$tmpfile =  $_FILES['board_file']['tmp_name'];
$origin_filename = $_FILES['board_file']['name'];
$filename = iconv("UTF-8", "EUC-KR",$_FILES['board_file']['name']);
$upload_path = "./upload/".$filename;
move_uploaded_file($tmpfile,$upload_path);

 


read.php 에도 추가해줍니다.

적당한 곳에 추가해주면 되겠습니다.

저는 조회수 표시 밑에 입력했습니다.

 

파일 : <a href="upload/<?php echo $board['file']; ?>" download><?php echo $board['file']; ?></a>

 

 

가상 머신에는 첨부할만한 마땅한 이미지가 없어서 구글을 통해

귀여운 우파루파 이미지를 한번 받아서 첨부해보겠습니다

 

 

글 작성을 누른 후 cutefish.jpeg라고 저장한 우파루파 이미지를 첨부해줍니다

 

 

글 작성이 잘 되었습니다

 

들어가서 읽어보니 잘 읽어집니다

 

그런데 클릭했을 때 아무 표시도 없는 새 탭이 떴습니다.

 

구글링을 통해 브라우저 마다 파일 다운로드가 안될 수도 있다고 하고 쿠키를 삭제하니 된다는 얘기가 보여

쿠키를 지워봤습니다.

 

기록 > 에 들어가 모든 기록 지우기를 눌렀습니다.

 

 

이렇게 해도 해결이 안되었습니다.

 

근본적으로 코드가 부족했다고 생각되어 코드를 수정해보겠습니다.

 

 


오류 해결

저 write_update.php 다운로드 현상은 제가 이것저것 구글링하다

header함수를 write_update.php 상단에 추가해버려서 그랬던 것 같습니다

해당 코드를 지우니 해결되더라구요

 

header 함수는 다운로드를 관리하는 페이지에만 사용해야겠습니다. (ex : download_proc.php)

 


 

write_update.php에 있던 파일 관련 변수들을 수정해주겠습니다

 

 

//파일 관련 변수
$tmpfile =  $_FILES['board_file']['tmp_name'];
$origin_filename = $_FILES['board_file']['name'];
//mime 허락된 형식
$allowed_mime_types = ['image/jpeg','image/png','image/gif','application./zip','application/x-hwp','application/msword','application/pdf']
$filename = iconv("UTF-8", "EUC-KR",$_FILES['board_file']['name']);

$timestamp = time();
$new_filename = $timestamp.'_'.$filename;
	$file_mime_type = mime_content_type($tmpfile);
	$upload_path = "./upload/".$new_filename;
	if(move_uploaded_file($tmpfile,$upload_path)){
    	$_SESSION['write_error'] = '파일 업로드 success!';
    } else {
	$_SESSION['write_error'] = '파일 업로드 Failㅜㅜ';
	}

 

파일의 이름은 초기에 사용자가 올린 파일명과 timestamp함수로 찍힌 업로드 시간 문자열과 합쳐서

파일명 = 업로드시간_원래파일명.png 이런식으로 저장되게 됩니다.

게시판 내용에서 출력될 때는 timestamp 시간은 빼고 출력되는 코드가 들어있어 원래 파일명만 출력됩니다.

 

이 부분 코드가 미완성이지만 $allowed_mime_types로 업로드 가능한 확장자 형식을 지정할 수 있습니다.

현재는 jpeg,png,gif,zip,hwp,word,pdf 만 허락되어있습니다.

 

저장위치는 해당 웹 서버에 upload 폴더를 만들어 new_filename 변수 이름으로 저장됩니다.

 

move_uploaded_file 함수가 실행되고 정상적으로 업로드되면 성공 표시가 뜨고 실패하면 실패 표시가 뜹니다.

 

그리고 read.php 하단에 아래 코드를 추가해줍니다.

 

세션함수를 활용하여 $_SESSION['write_error'] 변수가 존재하면 echo로 해당 메시지를 출력하고,

unset으로 초기화합니다.

<?php
if(isset($_SESSION['write_error'])){
	echo $_SESSION['write_error'];
	unset($_SESSION['write_error']);
}
?>

 

 

 

이제 파일 업로드는 구현된 것 같으니 다운로드를 구현해보겠습니다.

 

download_proc.php를 생성해줍니다.

 

 

 

이제 거의 다 구현이 되었다고 생각했는데 에러 메시지로 파일 업로드가 실패했다고 뜨네요

 

 


업로드 Fail 오류 해결

 

알아보니 해당 디렉토리의 소유자가 관리자이기 때문에 다른 사용자가 업로드를 할 권한이 없어서라고 합니다

 

터미널을 열고 다음 명령어를 입력해줍니다.

sudo chown -R www-data /var/www/html/upload

Ubuntu에서 아파치 이름은 www-data 라고 적어주면 됩니다.

 

 

cd로 폴더를 이동 후 ls -al로 찍어보니 소유자가 잘 바뀐 것을 확인할 수 있습니다.

 

이제 소유자도 바꿨으니 업로드가 잘 되는지 살펴보겠습니다.

 

글 작성을 누르고 항상 업로드 하던 우파루파 사진을 올리고 제목과 내용을 작성해줍니다.

 

글쓰기 완료! 목록으로 돌아가볼까요

 

드디어 첫 파일 업로드 성공 ㅠㅠㅠㅠㅠ

 

파일 업로드 success 문구가 떴습니다

 

아주 귀여운 우파루파가 타임스탬프가 찍힌 상태로 다운로드 되었습니다~


소스 참조

https://blog.naver.com/bgpoilkj/221276053999

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=questzz&logNo=220255928163