我读了一些关于上传文件的文章,人们可以上传恶意程序(php,exe,...)来攻击服务器和网站,最安全的保护方式是什么,避免对网站和服务器造成任何危险,这是我正在使用的一个类,如果要添加任何内容,请告诉我(禁用clamav扫描,扫描文件需要时间):
<html xmlns="http://www.w3.org/1999/xhtml" dir="rtl">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<?php
final class uploadFiles {
// params
private $uErrors=array(), $aErrors=array(), $dErrors=array();
/*
# uErrors = Show errors to the user
# aErrors = Show errors to the admin ONLY
# dErrors = Send delete file error to admin
*/
// get user group, level and id
public function __construct($fileField) {
$fileName = basename($_FILES['fileName']['name']); // get file name
$this->fileName = trim($fileName);
$this->fileField = $fileField;
# extract file info
// get file name before the dot sign
//$info = pathinfo($this->fileName);
//$fileInit = basename($this->fileName,'.'.$info['extension']);
$this->fileTmp = $_FILES[$this->fileField]['tmp_name']; // get temp name
$this->fileSize = basename($_FILES[$this->fileField]['size']); // get file size
$this->fileType = basename($_FILES[$this->fileField]['type']); // get file type
$this->fileError = basename($_FILES[$this->fileField]['error']); // list error codes
//$this->fileInit = $fileInit;
} // end function __construct
// check if file_uploads is set to ON or OFF
public final function checkUploads() {
if(ini_get('file_uploads')){
return true;
}
return false;
} // end checkUploads
// get file extension
public final function getFileExt() {
$getInfo = pathinfo($this->fileName);
$fileExt = basename($getInfo['extension']);
$fileExt = strtolower($fileExt);
$this->fileExt = $fileExt;
return $this->fileExt;
} // end getFileExt
// allowed file extensions
public final function allowedFileExt($extArray=array()) {
$this->extArray = $extArray;
$authExtList = implode(' ،',$this->extArray);
$this->authExtList = $authExtList;
if((in_array($this->getFileExt(), $this->extArray)) && (!empty($this->fileName)))
{
return true;
}
$this->uErrors[] = 'إمتداد الملف غير مقبول، المرجو إختيار أحد الإمتدادات التالية: '.$this->authExtList;
return false;
} // end allowedFileExt
// allowed file size
public final function allowedFileSize($maxFileSize) {
$this->maxFileSize = $maxFileSize;
if($this->fileSize > $this->maxFileSize)
{
$this->uErrors[] = 'حجم الملف كبير جدا';
return false;
}
return true;
} // end allowedFileSize
// create a new folder
public final function newDir($dirname) {
$this->dirname = $dirname;
// check if the directory exists or not
if(is_dir($this->dirname))
{
// if exists, check whether is writable or not
if(!is_writable($this->dirname)) {
// NB: You need to have enough permissions to perform this action
// set proper chmod, DO NOT user umask
if(chmod($this->dirname, 0755)) { // change the chmod to 755
return true;
} else {
//$this->uErrors[] = 'ليس لديك صلاحيات كافية لتغيير صلاحيات المجلد';
return false;
}
} // end is_writable
return true;
} else {
// if not, create it with 755 persmission
// NB: You need to have enough permissions to perform this action
if(mkdir($this->dirname, 0755))
{
return true;
}
//$this->uErrors[] = 'لا تملك الصلاحيات الكافية ﻹنشاء مجلد جديد';
return false; // in case of not enough permission
} // end is_dir
return false;
} // end newDir
/*
# Scanning file from any malware / virus using Clamav (Clam Anti Virus)
# Works with Ubuntu ==> sudo apt-get install clamav
*/
public final function scanFile(){
//$safe_path = escapeshellarg($this->fileTmp);
$safe_path = escapeshellarg($this->dirname.'/'.$this->fileName);
$cmd = '/usr/bin/clamscan 2>&1' . $safe_path;
$result = $cmd;
//echo $result.'<br />';
$out = '';
$int = -1;
$return = exec($cmd, $out, $int);
// if a malware / virus found
if ($int != 0)
{
return true;
}
return false;
}
// delete file if a virus / malware found
public final function delFile(){
// if true
//if($this->scanFile()){
/*
$this->uErrors[] = 'لم نتمكن من رفع الملف، المرجو المحاولة لاحقا';
// get current URL
$curURL = $_SERVER['REQUEST_URI'];
// refresh after 5 secs
//echo '<meta http-equiv="refresh" content="5; '.$curURL.'" />';
*/
$delFile = unlink($this->fileTmp); // Delete the file
if($delFile)
{
return true;
//$this->dErrors[] = 'ملف يحتوي على فيروس، تم المسح بنجاح';
}
return false;
//else
//{
//$this->dErrors[] = 'ملف يحتوي على فيروس، فشلت عملية المسح';
//} // end if($delFile)
//} // end if($this->scanFile()){
} // end delFile()
// upload the file
public final function uploadFile($target){
$this->target = $target;
if(file_exists($this->target)){
$moveFile = $this->target.'/'.$this->fileName;
echo $moveFile.'<br />';
$upFile = move_uploaded_file($this->fileTmp, $moveFile);
echo $upFile.'<br />';
if($upFile) {
//echo 'تم رفع الملف '.$this->fileName.' بنجاح';
//$eMsg = 'تم رفع الملف '.$this->fileName.' بنجاح';
return true;
}
//echo 'لم يتم رفع الملف '.$this->fileName.' بنجاح';
//$eMsg = 'لم يتم رفع الملف '.$this->fileName.' بنجاح';
}
else{
$this->newDir($this->target);
}
//$this->eMsg = $eMsg;
} // end uploadFile
// after uploading, for security reason, rename the uploaded file
public final function renameFile($location){
$this->location = $location;
// for security reason and better classification, use today date and time
$todayDate = date('Y-m-d'); // get today date as a string
$todayTime = date('h-i-s'); // get today time as a string
$now = time(); // get timestamp
$this->todayDate = $todayDate;
$this->todayTime = $todayTime;
$this->now = $now;
$renameFrom = $this->location.'/'.$this->fileName;
$renameTo = $this->todayDate.'_'.$todayTime.'_'.$this->now.'.'.$this->fileExt; // i.e: 2013-05-29_08-21-14_1369808474.htm
$fileDestination = $this->location.'/'.$renameTo;
$fileNewName = rename($renameFrom, $fileDestination);
$this->renameFrom = $renameFrom;
$this->renameTo = $renameTo;
$this->fileDestination = $fileDestination;
// set proper chmod, DO NOT use umask
chmod($fileDestination, 0644);
} // end renameFile
// filter file
public final function filterFile(){
// list disable functions, get it from your php.ini
$disFunctions = array('curl_multi_exec', 'parse_ini_file', 'readfile', 'symlink', 'shell_exec', 'exec', 'proc_close', 'proc_open', 'popen', 'show_source', 'system', 'dl', 'passthru', 'escapeshellarg', 'escapeshellcmd', 'pcntl_alarm', 'pcntl_fork', 'pcntl_waitpid', 'pcntl_wait', 'pcntl_wifexited', 'pcntl_wifstopped', 'pcntl_wifsignaled', 'pcntl_wexitstatus', 'pcntl_wtermsig', 'pcntl_wstopsig', 'pcntl_signal', 'pcntl_signal_dispatch', 'pcntl_get_last_error', 'pcntl_strerror', 'pcntl_sigprocmask', 'pcntl_sigwaitinfo', 'pcntl_sigtimedwait', 'pcntl_exec', 'pcntl_getpriority', 'pcntl_setpriority');
$this->disFunctions = $disFunctions;
// get file content
$cFile = file_get_contents($this->fileDestination, FILE_USE_INCLUDE_PATH);
foreach($this->disFunctions as $kkeys)
{
if(preg_match('#'.$kkeys.'#i', $cFile))
{
$this->aErrors[] = 'ملف يحتوي على دوال خطيرة';
//echo count($this->aErrors).'<br />';
//echo 'exists<br />';
//return false;
}
} // end foreach
} // end filterFile
####################### Global Functions Start ###############################
// mail function
public final function mailMsg($from, $to, $subject, $message){
// params
$sensivity = "Sensitivity: Private\n";
$priority = "X-Priority: 1 (Higuest)\n";
$this->from = $from;
$this->to = $to;
$this->subject = $subject;
$this->message = $message;
$this->sensivity = $sensivity;
$this->priority = $priority;
// headers
$headers = "From:=?UTF-8?B?".base64_encode($this->subject)."?=<'.$this->from.'>\r\n";
$headers .= $this->sensivity;
$headers .= $this->priority;
$this->headers = $headers;
mail($this->to, $this->subject, $this->message, $this->headers);
} // end mailMsg()
// mail function end
// getIP function
public final function chkip() {
$ip = "";
$proxy = "";
if (isset($_SERVER)) {
if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
$ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
$proxy = $_SERVER["REMOTE_ADDR"];
} elseif (isset($_SERVER["HTTP_CLIENT_IP"])) {
$ip = $_SERVER["HTTP_CLIENT_IP"];
} else {
$ip = $_SERVER["REMOTE_ADDR"];
}
} else {
if ( getenv( 'HTTP_X_FORWARDED_FOR' ) ) {
$ip = getenv( 'HTTP_X_FORWARDED_FOR');
$proxy = $_SERVER["REMOTE_ADDR"];
} elseif ( getenv( 'HTTP_CLIENT_IP' ) ) {
$ip = getenv( 'HTTP_CLIENT_IP' );
} else {
$ip = getenv( 'REMOTE_ADDR' );
}
}
if (strstr($ip, ',')) {
$ips = explode(',', $ip);
$ip = $ips[0];
}
if ($proxy != '') {
$ip = $ip . '(Proxy: '.$proxy.')';
}
return $ip;
}
################# Global Functions EnD #####################
public final function banIPTables() {
$this->getIP = $this->chkip();
$cmd = '/sbin/iptables -A INPUT -s '.$this->getIP.' -j DROP';
//echo $cmd.'<br />';
$run = exec($cmd .' 2>&1');
echo 'run '.$run.'<br />';
} // end banIPTables
public final function banDB($tableName, $fieldName) {
$this->getIP = $this->chkip();
$this->tableName = $tableName;
$this->fieldName = $fieldName;
/*
// assuming connection to host and db are already done
$sql = 'INSERT INTO '.$this->tableName.' VAlUES ('.$this->fieldName.');';
// you should proceed the query later, depends on you :)
$this->sql = $sql;
$query = $connexion->query($sql);
*/
} // end banIPTables
// get uErrors
public final function getError(){
//http://www.php.net/manual/en/features.file-upload.errors.php
switch($this->fileError)
{
case 1: // Server side (php.ini)
case 2: // Form side (MAX_FILE_SIZE)
$this->uErrors[] = 'الملف كبير الحجم';
break;
case 3:
$this->uErrors[] = 'لم يتم رفع الملف كاملا';
break;
case 4:
$this->uErrors[] = 'المرجو إختيار ملف لرفعه';
break;
case 6:
$this->uErrors[] = 'لا يوجد مجلد مؤقت بالسيرفر';
break;
case 7:
$this->uErrors[] = 'لا يمكن رفع الملف على السيرفر';
break;
default:
$this->uErrors[] = 'خطأ غير معروف';
break;
} // end switch
} // end getError()
// check if any uErrors
public final function checkErrors(){
$countuErrors = count($this->uErrors);
if((IsSet($this->uErrors) && (is_array($this->uErrors) && ($countuErrors > 0))))
{
return true;
}
return false;
} // end checkErrors()
// print user errors
public final function printErrors(){
$countuErrors = count($this->uErrors);
if((IsSet($this->uErrors) && (is_array($this->uErrors) && ($countuErrors > 0))))
{
//echo $this->eMsg;
echo 'لم يتم رفع الملف '.$this->fileName.' بنجاح';
echo '<ul>';
foreach($this->uErrors as $uV)
{
echo '<li>';
echo $uV;
echo '</li>';
}
echo '</ul>';
}
} // end printErrors()
// mail dangerous errors to the admin
public final function mailErrors(){
$countaErrors = count($this->aErrors);
if((IsSet($this->aErrors) && (is_array($this->aErrors) && ($countaErrors > 0))))
{
// extract errors
/*
foreach($this->aErrors as $aV)
{
echo '<li>';
echo $aV;
echo '</li>';
}
*/
echo 'mail it<br />';
echo 'transfert to qurantine';
}
} // end printErrors()
} // end class
############## USAGE Start ################
$fileField = 'fileName';
$sendName = 'Send';
$maxUpSize = 200000; // max file size: 2KB
$authExt = array('png', 'gif', 'jpg', 'jpeg', 'docx', 'htm', 'ogv'); // authorized files
$authExtList = implode(' ،',$authExt);
$current_url = $_SERVER['REQUEST_URI'];
$target = 'Images';
if(IsSet($_POST[$sendName])) {
// initialize the class
$up = new uploadFiles($fileField);
// check if file uploads is set to ON (1) OR OFF(0) => active or not
if($up->checkUploads()){
//$up->getFileInfo(); // get file information (size, temp name,..)
$up->allowedFileExt($authExt); // list authorized files
$up->allowedFileSize($maxUpSize); // Input max file size
//$up->checkDir('/home/aburayane/www/Images');
$up->newDir('Images');
//echo 'del '.$up->delFile();
//if($up->scanFile()) { // scan file: malware / virus found
// actions: what to do
//$up->banIPTables(); // ban throw IPTables
/*
$up->banDB('banIPs', 'ip'); // ban into DB
if($up->delFile()){ // id deleted
$eMsg = 'ملف يحتوي على فيروس، تم المسح بنجاح';
} else {
$eMsg = 'ملف يحتوي على فيروس، فشلت عملية المسح';
$up->renameFile('Qurantine'); // move the suspecious file to quarantine
}
$up->mailMsg('Guard', 'aburayane@gmail.com', 'Virus / Malware Found', $eMsg); // mail admin
*/
//}
if($up->checkErrors() === TRUE)
{
$up->getError(); // get uErrors
$up->printErrors(); // print uErrors
}
else
{
$up->uploadFile($target); // upload
//$up->scanFile();
$location = 'Images';
$up->renameFile($location); // rename
//$up->filterFile(); // filter file
$up->mailErrors(); // print all uErrors
//$up->printErrors(); // get uErrors
} // end if($up->checkErrors() === TRUE)
} else {
echo 'عملية رفع الملفات غير مفعلة في السيرفر<br />';
} // end if($up->checkUploads()){
} // end if(IsSet($_POST['Send'])) {
################# USAGE EnD #######################
?>
<fieldset style="width: 700px; margin-right: auto; margin-left: auto; border-width: 0px;">
<form name="formUp" method="POST" action="<?php echo $current_url; ?>" enctype="multipart/form-data">
<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $maxUpSize; ?>" />
<ul>
<li style="list-style: none;">
<label for="file" style="width: 130px; display: inline; float: right; margin-right: 1em; font-weight: bold;">إختر الملف المناسب</label>
<input type="file" name="<?php echo $fileField; ?>" class="fileName" />
</li>
<li style="list-style: none;">
<span style="margin-right: 2em;">
<input type="submit" name="<?php echo $sendName; ?>" class="submitFile" value="باسم الله" />
</span>
<span>حجم الملف لا يتعدى 200 كيلو بايت</span>
<br />
الإمتدادات المقبولة: <span style="color: red; font-weight: bold;"><?php echo $authExtList; ?>.</span>
</li>
</ul>
</form>
</fieldset>
</body>
</html>
感谢您的平常支持
答案 0 :(得分:0)
使用finfo函数,您可以检查mime /类型,只允许几个mime /类型,如image / jpeg,text / plain等。要使用这些函数,您需要在phpinfo中使用fileinfo扩展。 请注意,它不会返回$ _FILES或临时文件的准确数据,最好先物理保存文件,如果mime无效则删除文件。见http://php.net/manual/en/function.finfo-file.php
有关mimetypes的列表,请参阅https://gist.github.com/nimasdj/801b0b1a50112ea6a997