0

I am trying to create a file when a user submits a form, using
exec("sudo touch a.cpp") or die("Unable to create file)";
Output: Unable to create file

I have checked following answers:
1: sudo in php exec()
2: https://askubuntu.com/questions/139723/sudo-does-not-ask-for-password/139733#139733
3: https://askubuntu.com/questions/810462/nopasswd-option-not-working-in-sudo?noredirect=1&lq=1
4: also tried exec("echo <password> | sudo -S touch a.cpp");

Added www-data ALL=(ALL) NOPASSWD: /var/www/html/<project-folder> in visudo

Nothing seems to work.

Update: As mentioned in comment by @Rolfie using fopen() resolves this issue but still i am unable to use any command using exec(), for example compiling a file again shows same error.

kayush
  • 111
  • 7
  • 1
    I don't think you should ever use sudo in an exec() function. Just make sure the directory is owned by the same user php uses. And make sure it has the rights to be edited. – Rolfie Oct 08 '18 at 12:07
  • I think you should use fopen() to create the file in stead of exec(). Once again the right of the directory should be correct. chmod and chown the directory in linux to the correct user. – Rolfie Oct 08 '18 at 12:12
  • @Rolfie using `exec('fopen("a.cpp", "w")') or die("Unable to create file!");` doesn't work also, file has rights to be edited but is there a way to check and change ? – kayush Oct 08 '18 at 12:18
  • 1
    fopen() is a php function and not a linux function. So there is no need for exec. Just fopen("a.cpp", "w"); check http://php.net/manual/en/function.fopen.php. – Rolfie Oct 08 '18 at 12:23
  • Also touch() is a php function, check http://php.net/manual/en/function.touch.php . This should also do what you want to do. fopen is mostly used when you want to write something in the file, like a txt file. So maby touch() is the better option for you. – Rolfie Oct 08 '18 at 12:24
  • Maybe this will help https://stackoverflow.com/questions/17914402/php-exec-is-not-executing-the-command – Anton Oct 08 '18 at 12:37
  • Which linux are you using? If it's centos it might have sudo or exec() locked down by selinux, – ourmandave Oct 08 '18 at 12:39
  • I am using ubuntu 18.04 – kayush Oct 08 '18 at 12:44
  • Its working now, thanks to all – kayush Oct 08 '18 at 12:56

1 Answers1

1

You don't have to run as root! My answer below does not require you to give root permissions to www-data.

This works - I tested on Ubuntu 20.04 LTS Server August 2021.

Let's begin:

Create a "sudocmds.txt" and "results.txt" text files outside of the web root path i.e.

If your webroot is /var/www/html/ then place your text files in /var/www/cmds/

Set permissions on the files to www-data:

sudo chown www-data /var/www/cmds/sudocmds.txt
sudo chown www-data /var/www/cmds/results.txt

I'll use iptables as an example to show "iptables -L" via a button press:

Create a form:

<form method="post">
<input type="hidden" name="cmd"> <br>
<input type="submit" name="cmd" value="CMD";">
</form>

Use PHP code to write a "1" to the sudocmds.txt file when the 'CMD' button is pressed:

<?php 
  if(isset($_POST['cmd']))
      {
       $data=$_POST['cmd'];
       file_put_contents("../cmds/sudocmds.txt", "1");
       sleep(1);
       echo nl2br( file_get_contents('../cmds/results.txt') );
      }
?>

Now create a service to run on your host that will monitor the file and look for that 1 to appear then exec a command.

For this I will use inotify-tools as an example:

sudo apt install inotify-tools -y

Create the script:

sudo nano /opt/cmd-watcher.sh

#!/bin/bash

inotifywait -mqr -e close_write "/var/www/cmds/sudocmds.txt" | while read line
do
if grep -q 1 "/var/www/cmds/sudocmds.txt"; then
  sudo iptables -L > /var/www/cmds/results.txt
fi
done

Make the script executable

sudo chmod +x /opt/cmd-watcher.sh

Run the script in the background

sudo sh /opt/cmd-watcher.sh &

Now go to your webpage refresh it and press the button, you will see the results of the command appear after 1 second :)

I know it's a bit of a process but it means that you don't have to have the security risk of running commands as root with www-data.

halfer
  • 19,824
  • 17
  • 99
  • 186
confused
  • 139
  • 1
  • 11