Crazy PHP fopen / fwrite / file_put_contents / move_uploaded_file bug with binary mode writing on CentOS Linux Adding 0x0D to every 0x0A

青春壹個敷衍的年華 提交于 2020-06-13 05:01:27

问题


Seems the file keeps adding 0x0D to my saved binary files no matter what setting I put in the fopen mode flag.

It's not only affecting fopen/fwrite.. but also file_put_contents.

file_get_contents I thought was the problem to begin with.. but it turns out this one is actually working okay.. because when I dumped the file using bin2hex() it came out good.

I was blaming at first the std::string in C++ for this bug.. but it turns out it doesn't even have anything to do with C++ but it's in fact a bug with PHP or maybe with only CentOS linux and I have yet to find a solution to store my file in binary.. best I could do is hexstring dump file which works..

Look at my code and screenshots.

$target_file = "/privatefiles/" . basename($_FILES["a"]["name"]);
$fileTypeExtension = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));

//Check file extension.
if($fileTypeExtension != "dll" && $fileTypeExtension != "exe" ) die("ER");

// Check file size
if ($_FILES["a"]["size"] > 10*(1024*1024)) //10 MB cap
  die("ER");

//To decode a base64 encoded file (this was a quickfix to fix binary file encoding in C++ part).
$fileContent = file_get_contents($_FILES['a']['tmp_name']);
$fileContent = base64_decode($fileContent);

//fail
$fh = fopen("wtf1.bin", "wb");
fwrite($fh, $fileContent, strlen($fileContent));
fclose($fh);

//fail (exact result as top)
$fh = fopen("wtf2.bin", "wb");
$fileContent = bin2hex($fileContent);
for($i=0;$i<strlen($fileContent);$i+=2)
    fwrite($fh, chr(hexdec(substr($fileContent,$i,2))));
fclose($fh);

//good result.. but not binary
$fh = fopen("wtf3.bin", "w");
$fileContent = bin2hex(base64_decode(file_get_contents($_FILES['a']['tmp_name'])));
fwrite($fh, $fileContent);
fclose($fh);

//good result but not binary
file_put_contents($target_file, $fileContent); //good bin2hex.

//fail same as the top 2 fail's.
file_put_contents($target_file."_", file_get_contents($_FILES['a']['tmp_name'])); //bad same as wtf1.bin or wtf2.bin


Here are my screenshots (proof of what is happening from running the code above), and initiating a file upload using C++ application (which cannot be bugged because at first I sent using raw binary mode.. then after this 0x0D 0x0A bug I changed it to base64 encoding to fix the transfer problem.. and it turns out that wasn't even the problem, but in fact a PHP problem I believe..

Here is the original binary file (not altered) this is what I upload (as you can see I stop at 0x0A 0x40 to show you the bug). original

Here is wtf1.bin (Just a simple 1 liner of base64_decode to file) at same offset. wtf1

Here is wtf2.bin (Some hackery I tried to do to fix this problem using bin2hex which dumps it good) at same offset. wtf2

Here is wtf3.bin (bin2hex) which works good at same offset. (0x846 / 2 = 0x423) (same offset confirmed!) wtf3

phpversion

Even this simple upload script, uploads corrupted files with 0xA,0xD

<!DOCTYPE html>
<html>
<head>
  <title>Upload your files</title>
</head>
<body>
  <form enctype="multipart/form-data" action="test.php" method="POST">
    <p>Upload your file</p>
    <input type="file" name="uploaded_file"></input><br />
    <input type="submit" value="Upload"></input>
  </form>
</body>
</html>
<?php
  if(!empty($_FILES['uploaded_file']))
  {
    $path = basename( $_FILES['uploaded_file']['name']);
    print_r($_FILES);
    $size = filesize($_FILES['uploaded_file']['tmp_name']);
    echo "<br>size uploaded = " . $size . "<br>";
    if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $path)) {
      echo "The file ".  basename( $_FILES['uploaded_file']['name']). 
      " has been uploaded<br>";
      echo "path = " . $path . "<br>";
      echo "size stored = " . filesize($path);
    } else{
        echo "There was an error uploading the file, please try again!";
    }
  }
?>

Bug happens when I just upload these bytes in binary format

BC 09 00 00 83 C4 04 BA E8 57 40 00 8D 64 24 00 8A 08 88 0A 40 42 84 C9

I get back on server

BC 09 00 00 83 C4 04 BA E8 57 40 00 8D 64 24 00 8A 08 88 0D 0A 40 42 84 C9


回答1:


Thanks CBroe and IVO GELOV, The issue was in my FTP/SFTP Client WinSCP. I attached a screenshot which setting you need to turn off so this problem doesn't happen.



来源:https://stackoverflow.com/questions/62144562/crazy-php-fopen-fwrite-file-put-contents-move-uploaded-file-bug-with-binar

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!