I've set up a small web app that passes user data to a python script. Python is supposed to go to work, create a file on the webserver, and allow the user to download it. However, the script execution seems to stop where the Python write() command is issued.
Python:
print("Writing to '" + filename + "'")
f = open('backups/' + filename, 'w')
f.write(self.output())
f.close()
print("Done!")
PHP:
$user = escapeshellarg($_POST['user']);
$password = escapeshellarg($_POST['password']);
$command = './backup.py '.$user.' '.$password;
print(exec($command));
Actual result:
- Python does create a file in the desired directory but it remains empty. 2. Python never outputs "Done!" (Because permissions are denied)
Expected result:
- Python creates a file with data
- Python proceeds to print "Done!" which is output to the calling PHP script
I've done the following:
- www-data has group write permissions (
drwxrwsr-x) for the directory./backup - The
#!/usr/bin/env python3shebang is present in the python file - The python file is executable
- When I change to user www-data with
sudo su www-dataand then start the php commandline, and enter the above command invoking my Python script, the file is created correctly! - If I start a builtin php server, it also works fine, only if the php script is handled through apache, it doesn't work
1 Answer 1
I have officially wasted an entire day of my life on this.
The permissions were all right. What was happening is that the python script failed ONLY if it was being invoked through my php script and ONLY if that was being served by Apache.
Looking through the Apache error log revealed that the python script failed because it could not write bytes to the file and ascii conversion failed because there was unicode data in the output.
So doing f = open(filename, 'wb') solved the issue.
This behaviour was not observed on my development machine or through the built-in PHP server. Still wonder why there's a difference in file handling. Would appreciate an answer if anyone has one.
escapeshellargcalls should be sufficient.escapeshellcmdmight add additional escaping that breaks things.escapeshellarglike you did before. The second call toescapeshellcmdwas the one that was erroneous. I'd test this with filenames likeProgram Files/(Untitled 2).txtand; touch ~/hacked.txt