일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- active recon
- SQLi
- Server Side Request Forgery
- Reconnaissance
- War Game
- active reconnaissance
- Recon
- overthewire
- tryhackme
- php
- sql injection
- privilege escalation
- BANDiT
- php 파일 업로드하기
- Leviathan
- Cookie
- Cryptography
- php file upload
- file upload
- THM
- OS Command Injection
- FTZ
- Authentication
- 파일 업로드 취약점
- over the wire
- php To Do List
- access control
- php login page
- php 로그인 페이지 만들기
- ssrf
- Today
- Total
R's Hacking Daily Log
php - File Upload (2) 본문
업로드할 파일을 골랐으니 SUBMIT 버튼을 눌렀을 때 서버로 파일을 업로드할 기능을 구현해 보자.
form tag - action 값이 다음 페이지 경로이기 때문에 이번에 작성할 코드의 이름은 file_upload.php가 된다.
[ file_upload.php ]
<?php
$uploads_dir = './uploads';
$allowed_ext = array('jpg','jpeg','png','gif');
if(!is_dir($uploads_dir)) {
if(!mkdir($uploads_dir, 0777)) {
die("fail to make upload directory");
}
}
if(!isset($_FILES['myfile'])) {
die("not exist uploaded file");
}
$error = $_FILES['myfile']['error'];
$name = $_FILES['myfile']['name'];
$result = match($error) {
UPLOAD_ERR_OK => "UPLOAD COMPLETE ($error)",
UPLOAD_ERR_INI_SIZE => "EXCEED SIZE ($error)",
UPLOAD_ERR_FORM_SIZE => "EXCEED HTML SIZE($error)",
UPLOAD_ERR_PARTIAL => "LOADS PARTIAL($error)",
UPLOAD_ERR_NO_FILE => "FILE NOT EXISTS ($error)",
UPLOAD_ERR_NO_TMP_DIR => "TEM DIRECOTY NOT EXIST ($error)",
UPLOAD_ERR_CANT_WRITE => "CAN'T WRITE FILE ON WEB SERVER ($error)",
UPLOAD_ERR_EXTENSION => "EXTENSION FUNCTION ERROR ($error)"
};
if($error != UPLOAD_ERR_OK) {
echo $result;
exit;
}
$upload_file = $uploads_dir.'/'.$name;
$fileinfo = pathinfo($upload_file);
$ext = strtolower($fileinfo['extension']);
$i = 1;
while(is_file($upload_file)) {
$name = $fileinfo['filename']."-{$i}".$fileinfo['extention'];
$upload_file = $uploads_dir.'/'.$name;
$i++;
}
if(!in_array($ext, $allowed_ext)) {
echo "not confirmed extension";
exit;
}
if(!move_uploaded_file($_FILES['myfile']['tmp_name'], $upload_file)) {
echo "file doesn't uploads";
exit;
}
?>
<html>
<head>
<title>FILE Upload</title>
</head>
<body>
<h1>FILE UPLOAD EXAMPLE</h1>
<h1>file informaiton</h1>
<ul>
<li>result : <?php echo $result; ?></li>
<li>filename : <?php echo $name; ?></li>
<li>file extension : <?php echo $ext; ?></li>
<li>file type : <?php echo $_FILES['myfile']['type']; ?></li>
<li>file size : <?php echo $_FILES['myfile']['size']; ?>byte</li>
</ul>
<a href="./file_download.php?file=<?php echo $name; ?>">DOWMLOAD</a>
</body>
</html>
전체 코드는 위와 같다.
html 코드부터 보면 php 태그로 변숫값을 출력하는 아이템들과
a tag로 파일을 다운로드할 수 있는 링크(= DOMNLOAD)가 설정되어 있다.
* a tag - href 속성은 form tag - action처럼 DOWNLOAD문구를 클릭했을 때 이동하게 될 경로를 나타낸다.
* 글로벌 변수 $_FILES는 input tag - type = file로 전달한 파일 정보를 담고 있다.
예를 들어
<input type='file' name='myfile'>
myfile으로 전달한 파일의 오류 코드는 $_FILES['myfile']['error']로 얻을 수 있다.
myfile의 크기는 $_FILES['myfile']['size'], myfile의 이름은 $_FILES['myfile']['name'] ..
이제는 본격적으로 php 코드를 살펴보자.
$uploads_dir = './uploads';
$allowed_ext = array('jpg','jpeg','png','gif');
변수 uploads_dir & allowed_ext를 정의한다.
uploads_dir는 업로드된 파일이 들어갈 directory 이름으로 사용하고
allowed_ext는 파일의 허용할 확장자명을 배열로 정의한다.
if(!is_dir($uploads_dir)) {
if(!mkdir($uploads_dir, 0777)) {
die("fail to make upload directory");
}
}
if(!isset($_FILES['myfile'])) {
die("not exist uploaded file");
}
첫 번째 if문에서는 파일을 업로드할 directory가 존재하는지 확인하고
존재하지 않는 경우 모든 사용자가 접근 가능한 권한으로 directory를 만든다. (mkdir command)
두 번째 if문에서는 key-myfile인 파일이 존재하는 지의 여부를 확인한다.
만약 파일이 선택되지 않았다면 업로드할 파일이 없다는 문구가 출력될 것이다.
$error = $_FILES['myfile']['error'];
$name = $_FILES['myfile']['name'];
$result = match($error) {
UPLOAD_ERR_OK => "UPLOAD COMPLETE ($error)",
UPLOAD_ERR_INI_SIZE => "EXCEED SIZE ($error)",
UPLOAD_ERR_FORM_SIZE => "EXCEED HTML SIZE($error)",
UPLOAD_ERR_PARTIAL => "LOADS PARTIAL($error)",
UPLOAD_ERR_NO_FILE => "FILE NOT EXISTS ($error)",
UPLOAD_ERR_NO_TMP_DIR => "TEM DIRECOTY NOT EXIST ($error)",
UPLOAD_ERR_CANT_WRITE => "CAN'T WRITE FILE ON WEB SERVER ($error)",
UPLOAD_ERR_EXTENSION => "EXTENSION FUNCTION ERROR ($error)"
};
if 문에서 에러가 나지 않았다면 파일을 업로드할 directory가 존재하며, 선택한 파일이 존재한다는 의미이다.
그런 다음 $_FILES에서 업로드한 파일의 에러와 이름값을 가져온다.
match문에서는 error 코드가 무엇이냐에 따라 result 변수 값을 설정해 준다.
if($error != UPLOAD_ERR_OK) {
echo $result;
exit;
}
$upload_file = $uploads_dir.'/'.$name;
$fileinfo = pathinfo($upload_file);
$ext = strtolower($fileinfo['extension']);
만약 파일이 성공적으로 업로드되지 않았다면 result를 출력하고 코드를 종료하고
파일이 성공적으로 업로드되었다면 변수 upload_file & fileinfo & ext 값을 할당한다.
$i = 1;
while(is_file($upload_file)) {
$name = $fileinfo['filename']."-{$i}".$fileinfo['extention'];
$upload_file = $uploads_dir.'/'.$name;
$i++;
}
if(!in_array($ext, $allowed_ext)) {
echo "not confirmed extension";
exit;
}
파일의 이름이 중복될 수 있음을 방지하여 i 값을 1부터 증가시키면서 name 값을 설정하고 있다.
if 문에서는 처음에 정의했던 확장자 배열 안에 업로드한 파일의 확장자가 있는 지의 여부를 확인한다.
즉, 허용되는 파일 확장자가 아니라면 문구를 출력하고 코드를 종료시키는 흐름인 것
if(!move_uploaded_file($_FILES['myfile']['tmp_name'], $upload_file)) {
echo "file doesn't uploads";
exit;
}
?>
마지막으로 myfile로 업로드된 파일을 tmp directory에서 설정한 경로로 이동시켜 준다.
이전 글에서도 언급했듯이 move_uploaded_file() 함수를 사용하여 파일을 임시 폴더에서 지정된 경로로 이동시키는 데
이 과정에서 문제가 발생하면 파일을 업로드하지 못했다는 문구를 출력하고 종료한다.
php code가 성공적으로 실행되고 난 후,
html 내용이 구현되면 업로드된 파일의 정보를 출력하는 것으로 file_upload.php 내용이 마무리된다.
'PHP' 카테고리의 다른 글
php - Mini Project 1 - (1) (0) | 2023.07.30 |
---|---|
php - File Upload (3) (0) | 2023.07.26 |
php - File Upload (1) (0) | 2023.07.25 |
php - HTML Form으로 데이터 전송하기 (2) (0) | 2023.07.24 |
php - HTML Form으로 데이터 전송하기 (1) (0) | 2023.07.23 |