# PHP page running a bash script.

## GurliGebis

I want a PHP page to run a script every time it is loaded, the script is going to reload iptables, since there has been changed something in a file it uses.

I know there might be possible security problems with this, but the script is safe, it just has to be run everytime ok.php is run.

----------

## splooge

Does this help?

----------

## GurliGebis

Nahh, Isn't there a single line in PHP, that makes the server run a bash script, as if I had run it from a tty?

----------

## jnewland

http://www.php.net/manual/en/ref.exec.php

you can use

```
exec("sh /full/path/to/script.sh");
```

which will not show the output. the following will print the output to the page 

```
system("sh /full/path/to/script.sh");
```

the link above should clarify everything and give you some more info

----------

## GurliGebis

Thank you very much  :Smile: 

----------

## jukka

 *GurliGebis wrote:*   

> I want a PHP page to run a script every time it is loaded, the script is going to reload iptables, since there has been changed something in a file it uses.

 

if you're not using php's safe mode, put the path to your script in backticks (you might also want to follow the references for escapeshellcmd(), exec(), passthru(), popen(), shell_exec(), and system()).

hth, jukka

----------

## jukka

 *GurliGebis wrote:*   

> the script is going to reload iptables

 

hmm, does that mean your webserver has root privileges? wow, brave  :Wink: 

----------

## GurliGebis

no.

The script has SUID set.

Since the script is going to be run in the php code,  how should anyone be able to change the path to the script, and that way make it run another command?????

----------

## jukka

 *GurliGebis wrote:*   

> no. The script has SUID set.

 

if the suid bit is set for a script file, it gets stripped by the kernel before execution. only compiled executables may have the suid bit set. you'll have to write a wrapper in C or so.

 *Quote:*   

> Since the script is going to be run in the php code,  how should anyone be able to change the path to the script, and that way make it run another command?????

 

php bugs  :Wink: 

----------

## mmealman

Here's a sample C wrapper:

```

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

int main(int argc, char* argv[])

{

   

     uid_t euid;

     euid = geteuid();

    if(euid == 33) 

     {

        printf("Mirroring forms.\n");

        system("/usr/local/bin/mirrordir --verbose --password xxxx /var/forms mc://root@host/var/forms");

     } else 

     {

        printf("Invalid user error.\n");

     }

   

   

}

```

This is on Debian box where Apache runs as www-data, or user 33. The above will only execute for that user.

----------

## jukka

you'll probably rather need something like

```
#include <stdio.h>

#include <stdlib.h>

#include <sys/types.h>

#include <unistd.h>

int main(void)

{

  extern char **environ;

  const char *PROG = "/path/to/your/script";

  char *const arglist[2] = { "script_name", NULL };

  if (setuid(geteuid())) {

    perror("setuid()");

    exit(8);

  }

  execve(PROG, arglist, environ);

  fprintf(stderr, "ERROR: execve() failed\n");

  exit(9);

}
```

the compiled program should be owned by root:apache, and have mode 4750. so, only apache is allowed to execute this file (except root...), your script is run with an effective user id (euid) of 0.

----------

## GurliGebis

Now I just have to make the page.

I need one more thing:

A bash script that does export all values in a row in a mysql table to a file.

so, all values in the row "macs" in the "blp" table has to be exported to /etc/mac.allow .

Will somebody make that script for me?  :Smile: 

----------

## jukka

 *GurliGebis wrote:*   

> Will somebody make that script for me? 

 

maybe you, for a change?  :Wink: 

----------

## GurliGebis

Now I got all this working, there is just one little problem.

The script it executes is not able to run this command:

/etc/init.d/iptables restart

but if I run the script from the tty, it runs without any problems.

I think there might be some premission problems.

How shall the premissions for the binary file, the script and /etc/init.d/iptables be set???

----------

## jukka

 *GurliGebis wrote:*   

> The script it executes is not able to run this command [...] but if I run the script from the tty, it runs without any problems.

 

how do you run the script when it fails? from cron? if yes, run it as root, i.e. in root's crontab.

----------

## GurliGebis

ok, here is how I do it:

the PHP script run the compiles program (source in this tread)

the script it runs, executes these commands:

echo "testing" > /home/test

/etc/init.d/iptables restart

The first command is run correct (/home/test gets created), but iptables restart doesn't work (I have changed it a little, so it touches /home/test2).

What might be wrong?

----------

## jukka

 *GurliGebis wrote:*   

> the PHP script run the compiles program (source in this tread)

 

which one?

 *Quote:*   

> the script it runs, executes these commands:
> 
> echo "testing" > /home/test
> 
> /etc/init.d/iptables restart
> ...

 

no error message? add the following line to your script, just before the iptables command, an post the result:

```
echo "script runs as $EUID"
```

 *Quote:*   

> What might be wrong?

 

hmm, maybe the script  :Wink: 

----------

## GurliGebis

Going to try that when I get home.

----------

## mmealman

Which of the below are you doing:

1> PHP runs a C program which executes iptables.

2> PHP runs a C program which calls a bash script that runs iptables.

If it's 2, try doing 1.

----------

## GurliGebis

hehe, then I have to change something in the iptables script, since it reads something from a mysql database.

But I'm going to try that in an hour or so.

 :Shocked:  <-- hmm

----------

## GurliGebis

Script is running as 81 (apache)

Can I do it with sudo?

----------

## mr-simon

if you really must run a script as root, try using runsuid - this lets you configure which users are allowed to run which script as which other user, and handles the wrapper for you.

Really, really do check the script eleventeen times, as well as your web site, to make sure you know you're not going to leave a bigger security hole than you need to though.

----------

## jukka

 *GurliGebis wrote:*   

> Script is running as 81 (apache)

 

i thought you were using a wrapper... but you don't.

 *Quote:*   

> Can I do it with sudo?

 

maybe this thread helps...

seriously: with sudo, you would have to allow apache to execute commands as root without a password. i think that's not a very good idea...

use the tiny c wrapper i posted two days ago (in this thread). put the binary in your web servers cgi directory, change the file owner to root and the group to your web servers primary gid. then set the file mode to 4750.

if the cgi (the wrapper) is executed, it runs with an effective user id of 0 --> it runs your script as root --> your script is allowed to change iptables rules (because it's root). that's it. lucky?  :Wink: 

----------

## GurliGebis

I got it working using SUID, but I would like to know, which things apache should have the rights to, to run:

/etc/init.d/iptables restart.

----------

## GurliGebis

Problem there, i used the wrapper to call the script, and the script returns EUID 81.

----------

## jukka

 *mr-simon wrote:*   

> if you really must run a script as root, try using runsuid

 

runsuid basically uses the same technique as the wrapper above. i'd use the wrapper, because it's more straightforward, and i don't have to search for bugs for more than ten seconds.

----------

## jukka

 *GurliGebis wrote:*   

> Problem there, i used the wrapper to call the script, and the script returns EUID 81.

 

please post output of 'ls -l /your/cgi/script' (the wrapper)

----------

## jukka

 *GurliGebis wrote:*   

> I got it working using SUID, but I would like to know, which things apache should have the rights to, to run:
> 
> /etc/init.d/iptables restart.

 

must be root (uid 0) to use iptables.Last edited by jukka on Thu Jan 09, 2003 10:39 pm; edited 1 time in total

----------

## mr-simon

 *jukka wrote:*   

>  *mr-simon wrote:*   if you really must run a script as root, try using runsuid 
> 
> runsuid basically uses the same technique as the wrapper above. i'd use the wrapper, because it's more straightforward, and i don't have to search for bugs for more than ten seconds.

 

Aye... Either will work. But with runsuid you specify which user can run the script, on a per-script basis... So for example, only apache can run the script rather than any user with shell access. Admittedly with apache, that's fairly academic... But it's still a slight advantage.

----------

## GurliGebis

-rwsrwxrwx    1 apache   apache       5943 Jan  8 04:34 /home/httpd/htdocs/updatefirewall.bin

That should allow apache to do anything with it.

----------

## jukka

 *mr-simon wrote:*   

> Aye... Either will work. But with runsuid you specify which user can run the script, on a per-script basis... So for example, only apache can run the script rather than any user with shell access. Admittedly with apache, that's fairly academic... But it's still a slight advantage.

 

if the file has mode 4750, you can chose which users may run it by adding/removing allowed users to/from the group of the file. e.g.:

```
$ ls -l /cgi-dir/script

-rwsr-x---    1 root    apache         135 Jan  9 03:45 script
```

----------

## jukka

 *GurliGebis wrote:*   

> -rwsrwxrwx    1 apache   apache       5943 Jan  8 04:34 /home/httpd/htdocs/updatefirewall.bin
> 
> That should allow apache to do anything with it.

 

the file has to be owned by root...

```
$ chmod 4750 file

$ chown root:apache file
```

Last edited by jukka on Thu Jan 09, 2003 10:47 pm; edited 1 time in total

----------

## GurliGebis

Well, since I have giving the file 4777 rights (for now, going to change that when I get i working), the rights shouldn't be the problem.

But for now, I'm using iptables to block port 80 on the external NIC, and I'm the only one using it on the internal NIC, so there is no security problem with that for now.

----------

## GurliGebis

hehe, now it works without the sudo.

Thanks, it seemed to help changing to root:apache and 4750.

----------

## jukka

 *GurliGebis wrote:*   

> Well, since I have giving the file 4777 rights (for now, going to change that when I get i working), the rights shouldn't be the problem.

 

you don't understand what i'm talking about. even if all permission bits are set, apache is not allowed to use iptables, EXCEPT if the file owner has uid 0.

 *Quote:*   

> But for now, I'm using iptables to block port 80 on the external NIC, and I'm the only one using it on the internal NIC, so there is no security problem with that for now.

 

why don't you just run apache only on the internal interface? there is a listen directive: Listen [IP-address:]port

----------

## jukka

 *GurliGebis wrote:*   

> hehe, now it works without the sudo.
> 
> Thanks, it seemed to help changing to root:apache and 4750.

 

strange... i only told you about five times...  :Wink: 

----------

## GurliGebis

hehe, I know  :Smile: 

btw. while we are talking PHP, is there a way to get the MAC address of the client that connect to the pages NIC?

I trying to make my webpage as userfriendly, and right now, people has to write their mac address on the webpage, to be allowed to access the internet.

It would be easies it the PHP page was able to grab the MAC, so the user didn't had to write the MAC by them self.

Can I do that?

----------

