Thursday, February 17, 2011

Upload File อย่างปลอดภัย เช็คจากประเภทของไฟล์ หรือนามสกุลของไฟล์ดี

ทุกคนคงเคยเขียนโปรแกรม webboard ที่สามารถทำการ upload รูปขึ้นมาได้กันบ้างแล้ว และแต่ละคนคงจะมีวิธีการตรวจสอบว่าเป็น file รูปภาพหรือไม่ แตกต่างกันออกไปแล้วแต่ความถนัด ในเรื่องนี้ผมจะเปรียบเที่ยบความแตกต่างระหว่างการตรวจสอบชนิดของ file ที่ upload ขึ้นมาผ่านทาง file type กับ นามสกุลของ file มาดูจิว่า แบบไหนน่าใช้กว่ากัน

ในช่วงแรกๆ ที่ผมหัดเขียนโปรแกรมเพื่อทำการ upload file ขึ้นมาที่ server ผมจะใช้วิธีการตรวจสอบ ว่าเป็น file ชนิดอะไรจาก
นาม สกุลของ file แต่หลังจากนั้นผมก็เริ่มเขียนโปรแกรมโดยการตรวจสอบชนิดของ file จาก file type ซึ้งผมคิดว่ามันน่าจะดีกว่าแบบแรก แต่ผมก็พบว่ามันไม่ได้ดีอย่างที่ผมคิด มาดูกันแต่ละแบบแล้วกันว่ามีความแตกต่างและจุดบกพร้องอย่างไรบ้าง
ในการตรวจสอบชนิดของ file จากการตรวจสอบจากนามสกุลของ file ที่ upload ขึ้นมานั้นสามารถที่จะเขียน code ได้ง่ายๆ ดังนี้
# copy แล้ว save เป็นupload1.php เพื่อใช้ในการทดสอบ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
 
// รับเฉพาะ .gif กับ .jpg นะครับ
 
print $file_name;
 
if(strtoupper(substr($file_name, -4)) == ".JPG" || strtoupper(substr($file_name, -4)) == ".GIF"){
       copy($file,"/www/upload/".$file_name);
}
 
?>
<form action="upload1.php" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><input type="submit">
</form>
โดยที่ ช่อง input ที่ใช้ select file มี name = file แบบนี้นะ <input type="file" name="file">
และตัวแปร $file_name จะแทนชื่อของ file ที่ upload ขึ้นมา หรืออาจจะใช้ $_FILES['file']['name'] ก็ได้
ซึ่ง จากตัวอย่างจะเห็นว่ามี การ copy ข้อมูลไปไว้ที่ folder /www/upload/ โดยวิธีนี้จะดีตรงที่สามารถทำการ ตรวจสอบได้ง่าย แต่หากว่า file ที่ upload ขึ้นมาไม่ใช้ file รูปภาพ ก็ไม่สามารถที่จะตรวจสอบได้แล้ว อย่างเช่น ถ้า user ทำการเปลี่ยน นามสกุลของ file เป็น .gif ก่อนที่จะทำการ upload ขึ้นมาเราก็ตรวจสอบโดยวิธีนี้ไม่ได้ แต่ก็ดีตรงที่ file ที่ save ไปนั้นไม่ว่าจะเป็น file อะไร ก็จะมีนามสกุล เป็น .jpg กับ gif เสมอ
วิธีการตรวจสอบชนิดของ file โดยการ ตรวจสอบ จาก file type คือการตรวจสอบชนิดของ file จริงๆว่าเป็น file ชนิดอะไร ไม่ว่าจะทำการเปลี่ยน นามสกุลของ file ไปเป็นอะไร ก็ตามเจ้า file type ก็ยังเหมือนเดิม มาดู code กันเลย
# copy แล้ว save เป็น upload2.php เพื่อใช้ในการทดสอบ
1
2
3
4
5
6
7
8
9
10
11
12
<?php
 
print $file_type;
 
if($file_type == "image/jpeg" || $file_type == "image/gif"){
      copy($file,"/www/upload/".$file_name);
}
 
?>
<form action="upload2.php" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><input type="submit">
</form>
จาก code ที่ผ่านมาคุณคงจะคิดว่า แหม่ ตรวจสอบจากเจ้า file type นี้มันดีกว่านะ เพราะว่าไม่ว่าจะทำการเปลี่ยน นามสกุลของ file อย่างไร เราก็สามารถที่จะตรวจได้หมด เลยว่ามันเป็น อะไร กันแน่
อันที่จริง จะคิด แบบนี้ ก็จริงอยู่ครับว่ามันสามารถที่จะตรวจสอบได้ว่า เป็น file อะไรกันแน่ถ้าหากว่า user ทำการเปลี่ยน นามสกุล ของ file ก่อนที่จะทำการ upload ขึ้นมา
แต่ลองมาคิดดูอีกที่ หากว่าข้อมูลที่เขาส่งขึ้นมามันไม่ได้ มาจาก form ที่เราเขียนขึ้นละ มันกลับมาจากโปรแกรมที่สามารถทำการเปลี่ยน header ได้ละ จะเป็นยังไง ผลนะเหรอครับ ระวังให้ดีเราอาจจะโดน hack ง่ายๆ แน่ๆๆ
ตัวอย่างเช่นผมสร้าง file ชื่อ xx.php จากนั้นผมก็เขียน code php ตามปกติ อาจจะเขียน phpinfo(); ดูก็ได้ จากนั้นผมก็ทำการ upload file นี้เข้ามาโดยผ่านทาง โปรแกรม upload file ที่เราสร้างกันตะกี่นี้ อะอะ แต่ว่าผมไม่ได้ ทำการ upload ผ่านทาง form ที่คุณสร้าง นะ แต่ว่าผมจะเขียนโปรแกรม เพื่อทำการ upload มาที่ upload2.php ของคุณเอง โดยที่โปรแกรมของ ผมจะทำการหลอก header ด้วยว่าเป็น file .gif แค่นี้ ผมก็สามารถที่จะทำการ upload xxx.php มาที่ server ของคุณได้แล้ว ลองคิดดูเอง นะถ้าใน file xx.php ไม่ได้มีแค่ phpinfo() ละจะเป็นยังไง
คุณอาจจะคิดว่า จะหลอกมันได้ยังไง ในเมื่อขนาดว่าเราเปลี่ยน นามสกุลมาเป็น .gif มันยังรู้เลยว่า file type ที่แท้จริง คืออะไร
ซึ่งในการ เขียนโปรแกรมเพื่อหลอก header ตรงนี้ผมจะนำมาบอก อีกครั้งหนึ่ง วันนี้ดึกแล้ว ง่วงมากๆๆ นอนก่อน…ครับ

0 comments:

Post a Comment

 
Design by sutoday | Bloggerized by storesu - suvachai | laikeng