Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Безопасное копирование (https://javascript.ru/forum/misc/71523-bezopasnoe-kopirovanie.html)

Sonya 26.11.2017 12:41

Безопасное копирование
 
Здравствуйте! С помощью функции copy копирую картинки в папку. Будет ли достаточной защитой от возможных подмен или других возможных внедрений записей кодов в картинку, если я явно запрещу выполнение в папке с картинками скриптов, с переименованием файлов при копировании и установлении определенного расширения, например, gif для всех копированных файлов?

laimas 26.11.2017 13:19

А почему вопрос в разделе JS?
Смотря как вы принимаете изображения, по крайней мере функцию copy применять не рекомендуется при сохранении файлов принятых по HTTP.
А вот запрещать выполнение скриптов в этой папке да, это правильно, да и от внедренного мусора можно тоже избавиться посредством GD.

Sonya 26.11.2017 13:34

Цитата:

Сообщение от laimas (Сообщение 471235)
А почему вопрос в разделе JS?

Извиняюсь, писала в разделе своей последней темы, не посмотрела.

Sonya 26.11.2017 13:42

Цитата:

Сообщение от laimas (Сообщение 471235)
от внедренного мусора можно тоже избавиться посредством GD.

А можно поподробнее, как именно. Библиотека подключена.

Lion777 26.11.2017 13:49

Например, функция getimagesize() возвращает массив данных о изображении, а если ошибка, то не изображение..

---
Но есть такой вариант
http://php.net/manual/ru/function.finfo-file.php
---
Можно так же самому по сигнатуре файла определять, что за файл

Sonya 26.11.2017 13:56

Lion777,
Да, о функции читала, но там тоже есть какие-то ухищрения.
laimas,
А как загружать файл из ссылки, без использования copy, через file_get_contents?

Lion777 26.11.2017 14:13

file_get_contents('http://ссылка');
для проверки используйте расширение fileinfo, должно быть включенно
---
http://php.net/manual/ru/ref.fileinfo.php
---
echo mime_content_type('image.jpg');

laimas 26.11.2017 14:18

Цитата:

Сообщение от Lion777
Например, функция getimagesize()

Это не то, да обмануть ее, да и взлом через нее возможен.

laimas 26.11.2017 14:19

Цитата:

Сообщение от Sonya
А как загружать файл из ссылки, без использования copy, через file_get_contents?

А что за файлы и откуда вы загружаете?

Sonya 26.11.2017 14:25

Цитата:

Сообщение от laimas (Сообщение 471243)
А что за файлы и откуда вы загружаете?

Файл картинок, ссылку на картинку указывает пользователь. У меня реализовано так: через copy сохраняется файл с рандомным именем и расширением gif. Файл принимается только через ссылку (без загрузок с компьютера).

laimas 26.11.2017 14:28

Что только GIF? А если будет не этот формат?

Sonya 26.11.2017 14:37

Пользователь может загрузить только файлы с расширением png, jpg и gif (который в приоритете), на выходе получиться только gif. Читала, что и в целях безопасности это помогает. Читала, что и использование copy, не рекомендуется, но без примеров и указания в каких именно случаях. Посчитала, что в данном случае, это приемлемо, т.к. не увидела "подводных камней" (хотя, это и не говорит о том, что их там нет).

laimas 26.11.2017 14:50

Сохранить JPEG, а тем более PNG в GIF, это урезать изображение до безобразия, да еще все и вслепую.

Если к изображению и "приклеят" непотребное, то от exif можно и избавиться, это не проблема. И сам по себе код вклеенный не выполнится, нужен "помощник".

Если загрузка по ссылке, то так (используя GD):

if($im = imagecreatefromstring(file_get_contents('url'))) {
    //обработка изображения $im, можно уменьшить его на один пиксель по ширине/высоте,
    //все что вклеили будет удалено
    //можно узнать палитру изображения, если индексированная, то сохранять в GIF
    //иначе сохранять как JPEG
    //все это функциями GD
    //стоит учесть, что если GIF анимация, то она будет утеряна, сохранится только первый ее кадр 
} else {
    //мусор
}

Lion777 26.11.2017 15:01

<?php
$addrImage = 'https://javascript.ru/forum/images/ca_serenity/misc/logo.gif';
$testImage = exif_imagetype($addrImage);
if ($testImage > 0 AND $testImage < 18) echo 'Данный файл изображение';

так можно и сделать что-бы корректно расширение создавалось, не наугад, а какое должно быть.

Sonya 26.11.2017 15:05

laimas, спасибо, но дело в том, что это, как раз и есть анимированная картинка, поэтому ... Переформатирование картинок из png и jpg, не столь разительно в данном случае, поэтому особой роли не играет, тем более, что пользователь об этом предупрежден.

laimas 26.11.2017 15:20

Цитата:

Сообщение от Sonya
это, как раз и есть анимированная картинка

Тогда не проблема, открыли изображение из строки, узнали палитру - если truecolor, значит сохранили посредством GD. Exif при этом не сохраняется, а если вклеили в тело (есть умельцы), то можно изменить размер.
В противном случае сохраняем как GIF - file_put_contents(скачанное посредством file_get_contents).

imagecreatefromstring здесь для того, чтобы отсеять мусор. Имейте ввиду и возможные большие размеры, это будет проблемой уже для file_get_contents, не говоря уже о GD.

Если у вас на хосте доступен ImageMagick, то все операции лучше проделать в нем, он на гораздо большее способен, чем GD, включая и поддержку GIF анимации. GD же ее непосредственно не поддерживает, хотя можно и в нем, но писать свое уже.

Sonya 26.11.2017 15:22

Lion777,
exif_imagetype - определяет расширение файла?

Sonya 26.11.2017 15:25

laimas,
Спасибо, буду пробовать.

laimas 26.11.2017 15:26

Цитата:

Сообщение от Sonya
определяет расширение файла?

Определяет тип файла, но не надейтесь на это, эта функция считывает начальные байты и проверяет их сигнатуру. А речь то идет о подделке.

imagecreatefromstring же, пытается открыть ресурс из строки, если прислали не изображение, то вернет false.

Lion777 26.11.2017 15:27

по сигнатуре определяет тип файла, только изображения, посмотрите на php.net синтаксис.

Lion777 26.11.2017 15:29

laimas, вы хотите сказать, что если подделают сигнатуру, то вы взломаете сайт ?

laimas 26.11.2017 15:30

Lion777,
это ничем не отличается от getimagesize в плане обдурить.

laimas 26.11.2017 15:31

Цитата:

Сообщение от Lion777
что если подделают сигнатуру, то вы взломаете сайт ?

Читайте тему еще раз, есть примечание и о взломе, что повторить еще раз? Речь идет о мусоре, это в первую очередь, и во вторую о возможных вставках.

Lion777 26.11.2017 16:04

Сервер не будут грузить такие осторожности ? )) Это так, чуть дальше от темы )), ведь об этом автор не спрашивал, ну у автора конечно то врятли, а вообще ?

laimas 26.11.2017 16:13

Цитата:

Сообщение от Lion777
Сервер не будут грузить такие осторожности ?

Серверу вообще по барабану чего вы там грузите, ответственность полностью на разработчике. Это как сплошь и рядом при загрузке файла, проверяют то, что после точки, считая, что таким образом все проблемы решены. А то, что можно даже и не напрягаться в таком случае, а просто всякому мусору проставить расширения картинок, и сервер горе разработчика его схавает. Если и вы так будете считать, то и ваш сервер можно завалить мусором.

Sonya 26.11.2017 16:34

Не получается. С самого начала, в этот код вставить,
if($im = imagecreatefromstring(file_get_contents('url'))) {

} else {

}

а главное как узнать "узнали палитру - если truecolor"?
И далее:
"В противном случае сохраняем как GIF - file_put_contents(скачанное посредством file_get_contents)."

<?php
$file = 'https://site.ru/img/image.gif';
$current = file_get_contents($file);
$current .= "imgage/1.gif";
file_put_contents($file, $current);
?>


так не получается, тогда как?

laimas 26.11.2017 17:10

if($f = @file_get_contents('https://site.ru/img/image.gif')) {
    if($im = imagecreatefromstring($f)) {
        //это изображение
        imageistruecolor($im) 
            ? imagejpeg($im, 'path/name.jpg', $quality) //сохранение JPEG/PNG -> JPEG
            : file_put_contents('path/name.jpg', $f); //сохранение GIF/PNG8 -> GIF
        imagedestroy($im);
    } else {
        //иначе мусор
    }
} else //ошибка загрузки

Sonya 26.11.2017 17:24

laimas,
спасибо. А переменная $quality устанавливает качество изображения?

Sonya 26.11.2017 17:28

Анимация сохранилась в формате jpg - name.jpg Причем работает, может оставить так?

laimas 26.11.2017 17:57

Цитата:

Сообщение от Sonya
А переменная $quality устанавливает качество изображения?

Да, по умолчанию 75%, но можете указать свое, например чтобы уменьшить размер на выходе.

Цитата:

Сообщение от Sonya
Анимация сохранилась в формате jpg

JPEG формат не поддерживает анимацию, разберитесь что у вас сохранилось.


PS. Это file_put_contents('path/name.jpg', $f); //сохранение GIF/PNG8 -> GIF - результат моего копирования, а должно быть file_put_contents('path/name.gif', $f);

В зависимости от программы просмотра/браузера, не смотря на расширение ПО покажет анимацию так как опирается не на расширение файла, а на его заголовок.

Sonya 26.11.2017 18:13

Цитата:

Сообщение от laimas (Сообщение 471268)
JPEG формат не поддерживает анимацию, разберитесь что у вас сохранилось.

Да, я знаю, но не один раз встречала именно анимацию в формате jpg. Теперь Вы мне пояснили почему. Причем у меня показывает анимацию в трех разных браузерах.
Я так понимаю теперь все вшивки в exif, будут отсечены, а изменением размера можно уничтожить и в теле картинке? Но если размер изображения равен необходимому, можно это сделать двойным ресайзом, например, сначала увеличить на несколько пикселей, а потом вернуть к исходному. Или суть здесь, именно в измененном от начального размере.

laimas 26.11.2017 18:21

Цитата:

Сообщение от Sonya
не один раз встречала именно анимацию в формате jpg

Такой анимации нет, нет поддержки. Можно посредством JS устроить анимацию из нескольких jpeg изображений, либо спрайт таких изображений со встроенным SVG, который и занимается анимацией. Понятное дело, что попадись вам такой, GD его не откроет корректно, а если и сможет, то не сохранит.

Sonya 26.11.2017 18:26

Да, и хостинг поддерживает ImageMagick, код от этого меняется?

laimas 26.11.2017 18:33

Цитата:

Сообщение от Sonya
Я так понимаю теперь все вшивки в exif, будут отсечены

Да, сохранится чистый ресурс, хотя при наличии exif их можно прочесть. Проверьте.

Цитата:

Сообщение от Sonya
а изменением размера можно уничтожить и в теле картинке?

Да. При выводе на экран изображений посредством GD, в случае предупреждений/ошибок в браузер будут выведено не изображение, а его бинарные данные. На это и расчет такого встраивания - запуск РНР кода встроенного в тело изображения. Для этого еще надо постараться, но ...

Цитата:

Сообщение от Sonya
Но если размер изображения равен необходимому, можно это сделать двойным ресайзом, например, сначала увеличить на несколько пикселей, а потом вернуть к исходному.

Я не знаю чего вы сохраняете и насколько требования к размерам, но конечно можно изменить, затем опять изменить.

laimas 26.11.2017 18:38

Цитата:

Сообщение от Sonya
Да, и хостинг поддерживает ImageMagick, код от этого меняется?

Конечно код будет иной. Причем API для работы с ImageMagick есть как расширение (во многом пока экспериментальное), но не поставляется вместе с РНР. Как у вас на хосте сказать не могу. Если нет поддержки со стороны РНР, то значит из командной строки запуск будет.

С GD просто проще, но она и более прожорлива и уступает во многом ImageMagick, хотя для вашей задачи вполне хватит.

Sonya 26.11.2017 18:41

Цитата:

Сообщение от laimas (Сообщение 471274)
Я не знаю чего вы сохраняете и насколько требования к размерам, но конечно можно изменить, затем опять изменить.

Размер анимации 100х100, например, пользователь загружает её, я увеличиваю до 101х101, потом возвращаю к размеру 100х100 (будет незначительная потеря качества), таким образом я удалю вредоносный код из тела картинки?

laimas 26.11.2017 19:04

Цитата:

Сообщение от Sonya
пользователь загружает её, я увеличиваю до 101х101, потом возвращаю к размеру 100х100

Не получится - GD не работает с GIF анимацией, exif в данном файле нет, встраивать что-то в тело не имеет смысла, у данного типа сложный заголовок и не одна секция описания. Менять размеры не надо - проверили палитру - индексированная, значит просто сохраняем file_put_contents(...);

Lion777 26.11.2017 19:06

дадите ссылочку на ваше творение, хочется помотреть как не будет грузить сервер

Sonya 26.11.2017 19:14

laimas, спасибо.
Lion777, пока некондиция.

laimas 27.11.2017 06:08

Sonya,
сохранение в GIF, тоже некорректно:

file_put_contents('path/name.jpg', $f); //сохранение GIF/PNG8 -> GIF

Если исходное, это GIF, то все будет нормально, если же PNG8, то нет. Нужно дополнительно здесь проверять тип изображения и сохранять под соответствующим расширением.


Часовой пояс GMT +3, время: 18:48.