Issue in secure file upload script using command line AV - php

I have a secure file upload function that's part of my website
and I'm using an antivirus to help me checking the file a user trying to upload.
This is my uploadprocess.php file
$target_tmp = "D:\avscan\u\\";
$file = basename( $_FILES['uploaded_file']['name']) ;
if($file != "")
$_SESSION['file'] = $file;
$target = 'C:\xampp\htdocs\ssd\Uploads\\';
$file_path = $target_tmp.$file;
if(move_uploaded_file($_FILES['uploaded_file']['tmp_name'], $file_path))
{
$safe_path = escapeshellarg($file_path);
$command = 'scancl'. $safe_path. ' --stdout';
$out = '';
$int = -1;
$output = exec($command, $out, $int);
echo "The output is" .$output;
echo $int;
exit(0);
//Checking for Virus.
if ($int == 0) {
$target = $target.$file;
//echo $target; exit(0);
copy($file_path, $target);
$uploaded = "The file ". $_SESSION['file']. "has been uploaded";
$clean = 'File is Clean.';
$_SESSION['status'] = $clean;
$_SESSION['upload'] = $uploaded;
header("location: ../upload.php");
exit(0);
}
// File is a virus.
else {
$mal = 'Contains Malware';
$deny_up = "Unable to Upload Your File!";
$_SESSION['status'] = $mal;
$_SESSION['upload'] = $deny_up;
header("location: ../upload.php");
exit(0);
}
}
else
{
echo "SORRY, There was a Problem Uploading Your File."; exit(0);
$err_upload = "SORRY, There was a Problem Uploading Your File.";
$_SESSION['err'] = err_upload;
header("location: ../upload.php");
exit(0);
}
It prints me value of 1 for the $int for all files (malicious and non ones) This is my second try with a different AV now I'm using Avira and before I was using clamscan
can someone share me some hints, and tell me what's going on
PS the system is installed on XAMPP if that makes any difference

Can you be more specific about what's not working here? In theory what you doing seems fine at least for ClamAV since it has these return codes (from man clamscan):
RETURN CODES
0 : No virus found.
1 : Virus(es) found.
2 : Some error(s) occured.
Maybe it want to log the output of the exec call, if you are not getting the exit code you expect the reason should be in the output (like missing a command line flag).

Related

Redirection not working with various methods

I've the following PHP script launching on click of a submit form button :
<?php
//header('Location: video_download.html');
$target_dir = "uploads/";
$target_file = $target_dir . basename($_FILES["logo"]["name"]);
$uploadOk = 1;
$imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
$new_name = 'logo'.'.'.$imageFileType;
$target_file = $target_dir . $new_name;
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["logo"]["tmp_name"]);
if($check == false) {
echo "File is not an image.\n";
$uploadOk = 0;
}
}
// Check file size
if ($_FILES["logo"]["size"] > 5000000) {
echo "Sorry, your file is too large.\n";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "png") {
echo "Sorry, only PNG files are allowed.\n";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.\n";
if (file_exists("config.txt")) {
unlink("config.txt");
}
if (file_exists("upload/logo.png")) {
unlink("upload/logo.png");
}
// if everything is ok, try to upload file & create config.txt
} else {
if (move_uploaded_file($_FILES["logo"]["tmp_name"], $target_file)) {
$template = $_POST['template'] . "\n";
$club = $_POST['club'] . "\n";
$stats = $_POST['stats'];
if (file_exists("config.txt")) {
unlink("config.txt");
}
file_put_contents("config.txt", $template . $club . $stats);
echo '<meta http-equiv="Refresh" content="0; url=video_download.html">';
shell_exec("./blender_lite/bin/blender -b -P blender.py");
exit();
} else {
echo "There was an error uploading your file.\n";
exit();
}
}
?>
I want it to redirect the browser to another html page after executing all script's content. I've tried two different approach : the header (commented in the above code) and echoing an html meta tag with a redirection.
Both doesn't work for unknown reasons and I can't find it (already passed many hours trying to find other methods and resolve the issue without success, so I guess it's kind of a specific issue with a part of my php script). Any help is welcome, thanks :)
You would use the header function.
header("Location: http://www.website.com/page.php");
exit();
Replace the part of your code where you echo the meta refresh with the header location command and place it at the end of your logic. This will only redirect when everything else is complete then.
Example:
if (move_uploaded_file($_FILES["logo"]["tmp_name"], $target_file)) {
$template = $_POST['template'] . "\n";
$club = $_POST['club'] . "\n";
$stats = $_POST['stats'];
if (file_exists("config.txt")) {
unlink("config.txt");
}
file_put_contents("config.txt", $template . $club . $stats);
shell_exec("./blender_lite/bin/blender -b -P blender.py");
header('Location: video_download.html'); // <-- put redirect here
exit();
} else {
echo "There was an error uploading your file.\n";
exit();
}
Found out that the redirection worked fine as I did on my first post. The issue was that PHP waits for the shell_exec to be over. Thus, since I was launching a blender rendering with shell_exec, it was taking several minutes to end so I thought the redirection was not working.
Using exec('bash -c "exec nohup setsid ./blender_lite/bin/blender -b -P blender.py > /dev/null 2>&1 &"');
instead of shell_exec("./blender_lite/bin/blender -b -P blender.py");
so the PHP script doesn't wait for the command to end is the solution, the redirection is now immediate.

Read all lines on file uploaded

I know this subject already exist but in my case is a little more difficult.
I'm reading .EDI files (current succeed) on PHP, the process:
1.- I upload a .edi file from a html form.
2.- I send those attributes from the form to read on my php code.
I got the code like this:
if(isset($_FILES['ufile']['name'])){
$tmpName = $_FILES['ufile']['tmp_name'];
$newName = "" . $_FILES['ufile']['name'];
if(!is_uploaded_file($tmpName) ||
!move_uploaded_file($tmpName, $newName)){
echo "<table><tr><td><strong>Failed to read file ".$_FILES['ufile']['name']."</strong></td></tr></table>";
} else {
echo "<br>";
//coloca o conteudo do arquivo para a variavel $arquivo
$ponteiro = fopen ($_FILES['ufile']['name'],"r");
$arquivo = '';
while (!feof ($ponteiro)) {
$arquivo = $arquivo.fgets($ponteiro,4096);
}
fclose ($ponteiro);
if (unlink($_FILES['ufile']['name']) != 1) echo "Erro ao deletar arquivo!";
$padrao = fnc_resgata_padrao($arquivo);
if ($padrao == "COARRI"){
$a = fnc_processa_coarri(trim($arquivo));
prc_mostra_coarri($a);
}
elseif ($padrao == "CODECO") {
$a = fnc_processa_codeco(trim($arquivo));
prc_mostra_codeco($a);
}
else {
echo "<table><tr><td><strong>Invalid file</strong></td></tr></table>";
}
}
} else {
echo "You need to select a file. Please try again.";
}
The problem is, in this way only read the first line of the .EDI file and not all lines. I'm trying to understand that i must print an array but i don't know how to do it because my $a has the values i'm interested.
If the post is hard to understand, please let me know.
update 1
I just deleted some lines of the code, nothing important.

How to check if file handle still points to file

Is there any way in PHP to test if a fileHandle resource still points to the file in the file system that it opened? e.g. in this code:
<?php
$filename = './foo.txt';
$fileHandle = fopen($filename, 'c');
$unlinked = unlink($filename);
if (!$unlinked) {
echo "Failed to unlink file.";
exit(0);
}
file_put_contents($filename, "blah blah");
// The file $filename will exist here, but I want to check that
// the $fileHandle still points to the file on the filesystem name $filename.
?>
At the end of that code, the fileHandle still exists but no longer references the file './foo.txt' on the filesystem. It instead still holds a reference to the original file that has been unlinked, i.e. it has no active entry in the filesystem, and writing data to the fileHandle will not affect the contents of the file called $filename.
Is there a (preferably atomic) operation to determine that $fileHandle is now 'invalid' in the sense that it no longer points to the original file?
It's not an atomic operation but on Linux (and other Unix systems) it's possible to check using stat on the filename, and fstat on the fileHandle, and comparing the inodes returned from each of those functions.
This doesn't work on Windows, which is less than optimal.
<?php
$filename = './foo.txt';
$fileHandle = fopen($filename, 'c');
$locked = flock($fileHandle, LOCK_EX|LOCK_NB, $wouldBlock);
if (!$locked) {
echo "Failed to lock file.";
exit(0);
}
$unlinked = unlink($filename);
if (!$unlinked) {
echo "Failed to unlink file.";
exit(0);
}
// Comment out the next line to have the 'file doesn't exist' result.
file_put_contents($filename, "blah blah ");
$originalInode = null;
$currentInode = null;
$originalStat = fstat($fileHandle);
if(array_key_exists('ino', $originalStat)) {
$originalInode = $originalStat['ino'];
}
$currentStat = #stat($filename);
if($currentStat && array_key_exists('ino', $currentStat)) {
$currentInode = $currentStat['ino'];
}
if ($currentInode == null) {
echo "File doesn't currently exist.";
}
else if ($originalInode == null) {
echo "Something went horribly wrong.";
}
else if ($currentInode != $originalInode) {
echo "File handle no longer points to current file.";
}
else {
echo "inodes apparently match, which should never happen for this test case.";
}
$closed = fclose($fileHandle);
if (!$closed) {
echo "Failed to close file.";
exit(0);
}

PHP unlinking not working with variable

Going out of my mind with php unlinking
Here is my delete file script
$pictures = $_POST['data'];
//print_r ($pictures);
$imageone = $pictures[0];
$filename = "file:///Users/LUJO/Documents/CODE/REVLIVEGIT/wp-content/uploads/dropzone/" . $imageone;
echo $filename;
if (is_file($filename)) {
chmod($filename, 0777);
if (unlink($filename)) {
echo 'File deleted';
} else {
echo 'Cannot remove that file';
}
} else {
echo 'File does not exist';
}
The above does not work, error response is file does not exist
however if i change the filename path to this (the echo data from the echo above)
$filename = "file:///Users/LUJO/Documents/CODE/REVLIVEGIT/wp-content/uploads/dropzone/1420291529-whitetphoto.jpeg "
works fine and deletes the image.
Why can i not use the $imageone variable?
Do a print_r($pictures) to see if $pictures[0] is indeed the filename you're looking for.
Also note that if $pictures[0] is "//windows/*" you'll loose your windows if the user running PHP has administrative rights... so just using $pictures=$_POST["data"] is very VERY unsafe!

PHP - Redirect After File is Uploaded to Server

I have been looking around for a solution to this problem, and thus haven't found one. I'm hoping someone will be able to help me out with this problem.
I have this PHP script that gets the posted file, uploads, renames, and moves into a directory:
<?php
$fileName = $_POST['fileName'];
if (!$fileName) $fileName = $distFile.rand(1,999)."-".basename($_COOKIE["email"]);
$distFile = dirname(__FILE__).'/audio/'.$fileName.'.wav';
$error = 'N';
$message = 'Your song was uploaded!';
if (!isset($_FILES['wav']) || $_FILES['wav']['error'] > 0) {
$error = 'Y';
$message = 'Error while uploading. Error code: '.$_FILES['wav']['error'];
} else {
$res = #move_uploaded_file($_FILES['wav']['tmp_name'], $distFile);
if (!$res) {
$error = 'Y';
$message = 'Unable to create the file.';
}
}
echo '
<?xml version="1.0"?>
<response>
<error value="'.$error.'" />
<message>'.htmlspecialchars($message).'</message>
</response>
';
?>
That all works fine, however whenever I try to implement a header redirect (like so):
<?php
$fileName = $_POST['fileName'];
if (!$fileName) $fileName = $distFile.rand(1,999)."-".basename($_COOKIE["email"]);
$distFile = dirname(__FILE__).'/audio/'.$fileName.'.wav';
$error = 'N';
$message = 'Your song was uploaded!';
if($filename) {
header('Location: http://google.co.uk');
}
I am unable to refresh the page. I must point out that this script is located in a different file than the page I am trying to reload. This script is located in the file saveWav.php and I am trying to reload index.php.
I want you to replace your code to this
$fileName = $_POST['fileName'];
if (!$fileName)
{
$fileName = $distFile.rand(1,999)."-".basename($_COOKIE["email"]);
$distFile = dirname(__FILE__).'/audio/'.$fileName.'.wav';
$error = 'N';
$message = 'Your song was uploaded!';
}
else
{
header('Location: http://google.co.uk');
}

Categories