3

Sorry if the title is worded badly, but I'm very new to this, and still learning. I spent about an hour googling and couldn't find the answer, so I figured I'd post my issue. I have a web server with a php script on it, and I'm trying to be able to send a post request from powershell that uploads a file, and the file will be saved to the web server. Here is the script I have right now:

<?php
$file = date("Hism") . ".txt";
file_put_contents($file, file_get_contents("php://input"));
?>

This works, but it always sets the file extension to txt, and the file name to the date. I found some things that I didn't fully understand about $_FILES["file"]["name"] but replacing the date("Hism") . ".txt" part with that gives the error:

PHP Notice:  Undefined index: file in /home/ubuntu/phpServer/i.php on line 2
PHP Notice:  Trying to access array offset on value of type null in /home/ubuntu/phpServer/i.php on line 2
PHP Warning:  file_put_contents(): Filename cannot be empty in /home/ubuntu/phpServer/i.php on line 3

If it matters, the PowerShell script I am using to send the post request is:

iwr $ip/i.php -method POST -infile C:\test.txt
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Fun840
  • 107
  • 1
  • 7
  • Why don't you echo out what `date('Hism')` gives you? To ensure the filename isn't empty – a.mola Mar 16 '21 at 20:16
  • @a.mola `date('Hism')` just gives me the date, for example Tuesday Mar 16 20:26:49 2021 gives a file called `20264903.txt`. When I try it with that, it works. – Fun840 Mar 16 '21 at 20:28
  • Define `$file` yourself like `$file = 'filename.txt'` and replace `file_get_contents('php://input')` with an empty string (''). Just for testing reasons – a.mola Mar 16 '21 at 21:58

2 Answers2

1

I suggest you printing out what exactly your server is receiving, so you can handle it properly. For example use var_dump($_FILES); to debug the contents of the $_FILES variable and see, how the filename is actually saved.

Chris
  • 21
  • 2
  • Now it returns `array(0) { }`, this is a step in the right direction, but do you know what this problem might be/how to fix it? – Fun840 Mar 16 '21 at 21:45
  • 1
    I think your PowerShell command just sends a POST request to your PHP file and sends the contents of your "-infile C:\test.txt" as body of this request. In the end, the body of the request will not properly formatted to access the data via PHP variables. Using `file_get_contents("php://input")` will give you the plain body of the request. However, you cannot access anything on $_POST or $_FILES as you are sending the request with the wrong body. You need to change your PowerShell command in order to upload a file correctly via this PHP script. – Chris Mar 16 '21 at 22:01
  • 1
    Maybe this might be working. Using `curl` might be the right choice anyways: https://stackoverflow.com/questions/36268925/powershell-invoke-restmethod-multipart-form-data – Chris Mar 16 '21 at 22:02
  • Thanks, that works! It turned out that the type wasn't `"multipart/form-data"` but I tried using insomnia and that worked, then I came back here and the powershell script worked. Huge help! – Fun840 Mar 16 '21 at 22:26
  • Sorry, I know I already said it was fixed, but for some reason `$_FILES["file"]["name"]` is just `temp.txt`, do you know why this is / how I could fix it? Google just came up with a bunch of unrelated problems. – Fun840 Mar 16 '21 at 22:44
  • Whats the problem with that? Isn't your file called temp.txt when you upload it? You'll also have to move the file from the temporarily folder to the current working directory in order the access it properly. https://www.php.net/manual/en/function.move-uploaded-file.php – Chris Mar 16 '21 at 23:08
1

I see that answer is a little vague, so Here is the complete answer. For your i.php

<?php

// Outputs the files variable array
// var_dump($_FILES);
if (empty($_FILES)) return '$_FILES is empty';

// Why file? and name? please note that if you perform var_dump($_FILES) as stated above you will get
// the array that makes up $_FILES request.
// Also note in our request:  name=`"file`"; filename=`"test.txt`"" Try to change and then see what var_dump dispalys.
$fileName = $_FILES['file']['name'];

// Note that tmp files are saved elese where check using var_dump($_FILES)
$fileTmpName = $_FILES['file']['tmp_name'];

// Now move to the current directory where the script is running from
move_uploaded_file($fileTmpName, $fileName);
?>

That script should handle the preservation of extension and name of file. Sources for above script and since your new please have a look at:

Lets now move to iwr. Your are using Invoke-WebRequest do help iwr for more info. Now this question has been answered many times but here goes: (sources below)

$Uri = 'http://my-ip/Stackoverflow/i.php'
$fileBytes = [System.IO.File]::ReadAllBytes('c:\test.txt');
$fileEnc = [System.Text.Encoding]::GetEncoding('UTF-8').GetString($fileBytes);
$boundary = [System.Guid]::NewGuid().ToString();

$LF = "`r`n";

$bodyLines = ( 
    "--$boundary",
    "Content-Disposition: form-data; name=`"file`"; filename=`"test.txt`"",
    "Content-Type: application/octet-stream$LF",
    $fileEnc,
    "--$boundary--$LF" 
) -join $LF

The above script code is from powershell invoke-restmethod multipart/form-data I recommend that you look at that as well.

iwr -Uri $Uri -Method Post -ContentType "multipart/form-data; boundary=`"$boundary`"" -Body $bodyLines

Note I am using iwr the source mentioned above uses irm. You can read more on help iwr or help irm or visit Invoke-WebRequest

ziaahsan
  • 34
  • 5