Home > Web Application Penetration Testing > Secure file upload in PHP WebApp

Secure file upload in PHP WebApp


I. GIỚI THIỆU

Ứng dụng Web hỗ trợ cho phép người sử dụng thực hiện upload file lên server hiện tại có rất nhiều. Ví dụ như upload image(*.gif, *.jpg), *.pdf, *.doc, …Trong bài này seamoun sẽ trình bày một số lỗi khi lập trình file upload mà kẻ xấu có thể lợi dụng để upload những mã độc lên server. Những phương thức khai thác mà seamoun trình bày chỉ mang tính tham khảo không ủng hộ các bạn khai thác đối với những server bị mắc lỗi.

II. KHAI THÁC LỖI UPLOAD FILE

1) Trường hợp sử dụng JavaScript để kiểm tra file upload

Giả sử ta có kịch bản gồm 2 file như sau:

<html>

<title>Secure file upload PHP Web Applications</title>

<head>

<script language=javascript>

function chkFileExtension()

{

var str=document.upload.userfile.value;

var ext=str.substring(str.length,str.length-3);

if ( ext != “gif”)

{

alert(“File is invalid”);

return false;

}

else

{

return true;

};

}

</script>

</head>

<body>

<form name=”upload” action=”upload1.php” method=”POST” ENCTYPE=”multipart/form-data”  onSubmit=”return chkFileExtension()”>

Select the file to upload: <input type=”file” name=”userfile”>

<input type=”submit” name=”upload” value=”upload”>

</form>

</body>

</html>

Tên file: upload1.html

<?php

$uploaddir = ‘uploads/’;

$uploadfile = $uploaddir . basename($_FILES[‘userfile’][‘name’]);

if (move_uploaded_file($_FILES[‘userfile’][‘tmp_name’], $uploadfile)) {

echo “File was successfully uploaded.\n”;

} else {

echo “File uploading failed.\n”;

}

?>

Tên file: upload1.php

Ví dụ trên cho thấy người lập trình kiểm tra phần mở rộng file cho phép file upload bằng cách sử dụng một đoạn mã Javascript trong file upload1.html. Chỉ chấp nhận những file có phần mở rộng là *.gif thì mới được phép upload, cách này một kẻ tấn công dễ dàng vượt qua bằng cách sử dụng một intercepting proxy hoặc có thể viết một đoạn mã bằng Perl, Python,… mà đệ trình trực tiếp đến file upload1.php với những tham số cần thiết.

Trong demo sau seamoun sử dụng Burp Suite là một tool rất mạnh khi thực hiện Web Application. Có thể download tại :http://portswigger.net/

Demo: Lab1

Download file Lab1.rar

2) Trường hợp không sử dụng JavaScript để kiểm tra mà thực hiện kiểm tra trên server với đoạn mã sau:

<?php

if($_FILES[‘userfile’][‘type’] != “image/gif”) {

echo “Sorry, we only allow uploading GIF images”;

exit;

}

$uploaddir = ‘uploads/’;

$uploadfile = $uploaddir . basename($_FILES[‘userfile’][‘name’]);

if (move_uploaded_file($_FILES[‘userfile’][‘tmp_name’], $uploadfile)) {

echo “File is valid, and was successfully uploaded.\n”;

} else {

echo “File uploading failed.\n”;

}

?>

Tên file: upload2.php

Với đoạn mã trên người lập trình hy vọng ngăn chặn được kẻ tấn công upload file độc hại lên server bằng cách sử dụng kiểm tra type=image/gif. Tức là kiểu file cho phép upload ở đây chỉ có thể là file gif. Điều này cũng không an toàn bởi vì kẻ tấn công có thể thay đổi kiểu type=image/gif cho phù hợp với sự kiểm tra của đoạn mã trên nhưng nội dung vẫn chứa mã độc.

Demo: Lab2

Download file Lab2.rar

3) Trường hợp kiểm tra mime – kiểm tra phần nội dung của file upload với đoạn mã sau:

<?php

$imageinfo = getimagesize($_FILES[‘userfile’][‘tmp_name’]);

if($imageinfo[‘mime’] != ‘image/gif’ && $imageinfo[‘mime’] != ‘image/jpeg’) {

echo “Sorry, we only accept GIF and JPEG images\n”;

exit;

}

$uploaddir = ‘uploads/’;

$uploadfile = $uploaddir . basename($_FILES[‘userfile’][‘name’]);

if (move_uploaded_file($_FILES[‘userfile’][‘tmp_name’], $uploadfile)) {

echo “File is valid, and was successfully uploaded.\n”;

} else {

echo “File uploading failed.\n”;

}

?>

Tên file: upload3.php

Như vậy liệu có cải thiện hơn ? An toàn hơn ? Trả lời: có cái thiện hơn nhưng vẫn chưa an toàn. Mặc dù với đoạn mã trên kẻ tấn công không thực hiện thành công như ở Lab2, khi thay đổi type=image/gif vì lúc này người lập trình đã kiểm tra nội dung file upload có đúng là gif hay không ?. Nhưng nếu kẻ tấn công sử dụng một file gif và chèn mã độc vào thì thế nào ? Khai thác sẽ thành công !!!!

Demo: Lab3

Download file Lab3.rar

4) Trường hợp kiểm tra phần mở rộng của file trên server với đoạn mã sau:

<?php

$blacklist = array(“.php”, “.phtml”);

foreach ($blacklist as $item) {

if(preg_match(“/$item\$/i”, $_FILES[‘userfile’][‘name’])) {

echo “We do not allow uploading PHP files\n”;

exit;

}

}

$uploaddir = ‘uploads/’;

$uploadfile = $uploaddir . basename($_FILES[‘userfile’][‘name’]);

if (move_uploaded_file($_FILES[‘userfile’][‘tmp_name’], $uploadfile)) {

echo “File is valid, and was successfully uploaded.\n”;

} else {

echo “File uploading failed.\n”;

}

?>

Tên file: upload4.php

Như vậy với đoạn mã người lập trình đã ngăn chặn kẻ tấn công không thể upload file *.php lên server. Tuy nhiên trường hợp này cũng chưa an toàn với những server mà có cấu hình file *.gif, *.jpg cho phép xử lý PHP. Do vậy kẻ tấn công vẫn upload file gif, jpg lên server nhưng có chèn thêm mã độc vào.

III. CÁCH PHÒNG CHỐNG

Mấu chốt giải quyết vấn để làm thế nào an toàn trong file upload đó là lưu giữ file upload lên một nơi mà không thể truy cập bởi user thông qua URL. Điều này có thể thực hiện được bằng cách lưu file upload bên ngoài thưc mục webroot hoặc trên web server nhưng từ chối truy cập đến thư mục đó.

+ Tài liệu tham khảo: “Secure File Upload In PHP Web Applications – ScanIt

+ Công cụ sử dụng: Burp Suite (http://portswigger.net/ )

+ Tất cả file demo các bạn có thể download tại đây

  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: