echo writes successfully on 8 bytes input but failed for others - php

Thought a lot but could not find a suitable title ... so also suggest on title.
Also I am not showing HTML code to avoid making post larger. With PHP variables names and part of figure shown, its easy to understand the situation.
Actual problem is described here -
Here is a code snippet which is just a small part of a large code. The confusion is b/w two situations. Both are mentioned below. -
PHP Code :
while($npacket>=1) {
$count=0;
$out_file=fopen("packet.txt","w");
while($count<$payload_length ) {
$c=fgetc($file);
fputs($out_file,$c);
$count++;
}
$data_file=`cat packet.txt`;
if($datatyp=="ascii")
$fpayload="-f packet.txt";
else if($datatyp=="hex")
$fpayload="-d0x$data_file";
$random="";
if( $ip=="tcp" || $ip=="udp" )
exec("sendip -v -p ipv6 $fpayload $random $adv_cont -6s $sip $optext -p $proto $cont -$s $sapp_port -$d $dapp_port $dip ");
else {
Problem is Here ....
echo "this is $fpayload it";
exec(" echo sendip -v -p ipv6 $fpayload $random $adv_cont -6s $sip $optext -p icmp $icmp_cont $dip > sample ");
}
usleep("$igap");
if(!$flag)
$npacket--;
}
fclose($out_file);
fclose($file);
}
For 1 packet and payload specified as a input,
1) Input : 616263646566
Output :
$ cat payload.txt
616263646566
$ cat packet.txt
616263646566
$ cat sample
$
2) Input : 6162636465666768
Output :
$ cat payload.txt
6162636465666768
$ cat packet.txt
6162636465666768
$ cat sample
sendip -v -p ipv6 -d0x6162636465666768 -6s 2001::100 -p icmp 2001::200
Please help me find out where does exactly problem lies ?
EDIT:
Permission of files :
$ ls -l payload.txt packet.txt sample
-rwxrwxrwx 1 udit udit 13 Nov 17 20:57 packet.txt
-rwxrwxrwx 1 udit udit 13 Nov 17 20:57 payload.txt
-rwxrwxrwx 1 udit udit 0 Nov 17 20:57 sample

Problem was actually presence of whitespaces and null characters at the end of $fpayload variable. Just needed to add one regular expression syntax in else part.
.........
else if($datatyp=="hex") {
$fpayload="-d0x$data_file";
$fpayload=preg_replace('/\s+/', '', $fpayload);
}
....

Related

Kubeclt exec issues with variable via php script

New to kubernetes and php, so I'm having some issues. Any and all help is greatly appreciated!
<?php
$postgres = 'kubectl get pods -n migrationnamespace | grep postgres | cut -d " " -f1 2>&1';
$postgres_pod = shell_exec($postgres);
echo $postgres_pod;
$list2 = 'kubectl exec -it -n migrationnamespace ' . $postgres_pod . ' -- psql -U postgres -c \'SELECT * FROM mywhales\'; 2>&1';
echo "<pre>";
echo shell_exec($list2);
echo "<pre>";
?>
results in error
postgres-7957478b7d-tmw6m
error: you must specify at least one command for the container
sh: line 1: --: command not found
When switching '.$postgres_pod.' for postgres-7957478b7d-tmw6m as below - it executes fully
$list2 = 'kubectl exec -it -n migrationnamespace postgres-7957478b7d-tmw6m -- psql -U postgres -c \'SELECT * FROM mywhales\';';
postgres-7957478b7d-tmw6m
whale
---------
16:117
......
561:539
(17 rows)
Thanks - Mike
There can sometimes be extra whitespace before or after strings, especially return characters which don't always show up when echoing the result.
Using trim($postgres_pod) will ensure they are removed.

www-data in sudo with mount

Unable to launch the mount command via php and exec
Of course :
The file sudo toto.sh works
and
www-data is allowed in sudoers to ALL so all processes
www-data ALL = (ALL) NOPASSWD: ALL
toto.sh:
Machine = "L1069"
machine="L1069"
mount -t cifs //$ipaddr/c$ /mnt/pc-backup/$machine -o "vers=2.0,username=agent-back-ws,password=Bcth2,ro,iocharset=utf8
,noserverino"
In the go.php file:
$outputShell=passthru('sudo cat /etc/passwd');
$output=exec('sudo /var/www/html/toto.sh 2>&1');
var_dump ($output);
var_dump ($outputShell);
When I run php go.php (as root) I get:
<pre> </ pre> string (0) ""
and mount is done and the content of / etc / passwd is displayed
On the other hand via the browser I launch www / go.php so in www-data: I get:
string (0) ""
no mount and the content of / etc / passwd is displayed
Why the mount does not work is the problem seems the script with php7 and latest Debian version ...
Help !!!!!!! works in debian 8 and php 5.5
> L106529
passe dans gosuite.sh ....
Machine : L106529 - IP: xxx.xxx.250.185
Commande passee : /bin/mount -t cifs //xxx.xxx.250.185/c$ /mnt/pc-backup/L106529 -o "vers=2.0,username=agent-backup-ws,password=BcK312Eth2,ro,iocharset=utf8,noserverino"
execve("/bin/mount", ["/bin/mount", "-t", "cifs", "//xxx.xxx.250.185/c$", "/mnt/pc-backup/L106529", "-o", "vers=2.0,username=agent-backup-w"...], [/* 16 vars */]) = 0
[pid 26704] mount("//xxx.xxx.250.185/c$", ".", "cifs", MS_RDONLY, "ip=xxx.xxx.250.185,unc=\\\\xxx.xxx.2"...) = 0
[pid 26704] capset({_LINUX_CAPABILITY_VERSION_3, 26704}, {CAP_SYS_ADMIN, CAP_DAC_OVERRIDE|CAP_DAC_READ_SEARCH|CAP_SYS_ADMIN, 0}) = 0
not works in debian 9 php 7 :
L106529
passe dans gosuite.sh ....
Machine : L106529 - IP: xxx.xxx.250.185
Commande passee : /bin/mount -t cifs //xxx.xxx.250.185/c$ /mnt/pc-backup/L106529 -o "vers=2.0,username=agent-backup-ws,password=BcK312Eth2,ro,iocharset=utf8,noserverino"
execve("/bin/mount", ["/bin/mount", "-t", "cifs", "//xxx.xxx.250.185/c$", "/mnt/pc-backup/L106529", "-o", "vers=2.0,username=agent-backup-w"...], [/* 16 vars */]) = 0
brk(NULL) = 0x5565ff8c5000
pid 14506] capget({version=0 /* _LINUX_CAPABILITY_VERSION_??? */, pid=0}, NULL) = 0
[pid 14506] gettid() = 14506
[pid 14506] open("/proc/sys/kernel/cap_last_cap", O_RDONLY) = 3
[pid 14506] read(3, "37\n", 7) = 3
[pid 14506] close(3) = 0
When you run the script from your "root context", you do not have to use the full paths to the executables you use.
You should use the full path to the binary in your scripts.
Machine = "L1069"
machine="L1069"
/bin/mount -t cifs //$ipaddr/c$ /mnt/pc-backup/$machine -o "vers=2.0,username=agent-
back-ws,password=Bcth2,ro,iocharset=utf8
,noserverino"
and
$outputShell=passthru('sudo /bin/cat /etc/passwd');
$output=exec('sudo /var/www/html/toto.sh 2>&1');
var_dump ($output);
var_dump ($outputShell);
To identify the correct path, use whereis mount and whereis cat

How to limit 1 instance of a PHP script, what's wrong with my solution

<?PHP
define('TEMPPATH', '/tmp/');
$fp = fopen(TEMPPATH.'abc.php.lock', 'a+');
if(!flock($fp, LOCK_EX | LOCK_NB))
exit;
I use the above codes to limit the script from running multiple instances, and it's OK when I test it, but today when I logged in to my server (CentOS 6) and I saw two instances running, how could that happen?
[root#server user]# ps aux | grep abc
root 21061 0.0 0.1 103284 2016 pts/0 S+ 15:45 0:00 grep abc
user 22560 0.0 1.2 154608 12788 ? Ss Nov10 1:35 /usr/bin/php /path/abc.php
user 25106 0.0 1.3 154896 13336 ? Ss Nov06 2:51 /usr/bin/php /path/abc.php
The script was started from crontab jobs, crontab tries to run it every minute, is there any better ways to do this ?
Very elaborate instance control :).
Take a look at mine:
function par_processes($name = null,$ownPids = array(),$dbg = false){
exec("ps x | grep $name", $ProcessState);
$modifier = 0;
while (list($idp,$procs) = each($ProcessState)){
if (preg_match("/grep/i",$procs)) {
unset($ProcessState[$idp]);
}else{
if (!empty($ownPids)){
if (in_array(strstr(trim($procs)," ",true),$ownPids)){
unset($ProcessState[$idp]);
}
}
}
}
if (!$dbg){
return (count($ProcessState) - $modifier);
}else{
return array(0=>(count($ProcessState) - $modifier),1=>$ProcessState,2=>$ownPids);
}
}
And in the php daemon before I go any further I use this:
# INSTANCE CHECK
if (par_processes("MYSOFTWARENAME",array(getmypid()))){
error_log("SOME ERROR"); die();
}
Quite frankly it can be done quicker and more effective (probably) but it does the job.
Of course you need to be able to run exec() for this to work.

PHP script to execute a bash script

I have 3 scripts (I have removed the help_page function from the networkstats.sh script when I pasted here to save some space):
api3.php
<?php
output = shell_exec('/bin/bash /usr/share/nginx/status/getnetworkstatsin.sh');
echo $output;
?>
getnetworkstatsin.sh
#!/bin/bash
ssh -i /tmp/id_rsa1 root#centos7clone bash -s -- -I < ./networkstats.sh
networkstats.sh
#!/bin/bash
interface=enp0s3
read -r inbytesold outbytesold < <(awk -v dev="^$interface:" '$1 ~ dev {
sub(/[^:]*:/,""); print $1, $9; exit }' /proc/net/dev)
sleep 1
read -r inbytesnew outbytesnew < <(awk -v dev="^$interface:" '$1 ~ dev {
sub(/[^:]*:/,""); print $1, $9; exit }' /proc/net/dev)
kilobitsin=$(( ( ( inbytesnew - inbytesold ) * 8 ) / 1024 ))
kilobitsout=$(( ( ( outbytesnew - outbytesold ) * 8 ) / 1024 ))
show_outgoing() {
echo $kilobitsout
}
show_all() {
echo "kilobits in: $kilobitsin"
echo "kilobits out: $kilobitsout"
}
if [[ $# -eq 0 ]];
then
help_page
exit 1
fi
for arg in "$#"
do
case $arg in
-h|--help)
help_page
;;
-I)
show_incoming
;;
-O)
show_outgoing
;;
-A|--all)
show_all
;;
esac
done
The problem I have is that when I execute the api3.php script from console, it is able to execute and return a value.
However when I try and execute from a webpage it fails to return anything.
I believe it is not even executing when I load it via the webpage by navigating to localhost/api3.php. Can someone help, what is the reason behind this? I have added
nginx ALL=NOPASSWD: /usr/share/nginx/status/getnetworkstatsin.sh
To my visudo section, I have tried to change permissions of all files involved to 777 (temporally) without success.
EDIT: I should also mention that all these scripts are located inside /usr/share/nginx/status which nginx has access to.

standard output impact SIGKILL?

I have a script to limit the execution time length of commands.
limit.php
<?php
declare(ticks = 1);
if ($argc<2) die("Wrong parameter\n");
$cmd = $argv[1];
$tl = isset($argv[2]) ? intval($argv[2]) : 3;
$pid = pcntl_fork();
if (-1 == $pid) {
die('FORK_FAILED');
} elseif ($pid == 0) {
exec($cmd);
posix_kill(posix_getppid(), SIGALRM);
} else {
pcntl_signal(SIGALRM, create_function('$signo',"die('EXECUTE_ENDED');"));
sleep($tl);
posix_kill($pid, SIGKILL);
die("TIMEOUT_KILLED : $pid");
}
Then I test this script with some commands.
TEST A
php limit.php "php -r 'while(1){sleep(1);echo PHP_OS;}'" 3
After 3s, we can find the processes were killed as we expected.
TEST B
Remove the output code and run again.
php limit.php "php -r 'while(1){sleep(1);}'" 3
Result looks not good, the process created by function "exec" was not killed like TEST A.
[alix#s4 tmp]$ ps aux | grep whil[e]
alix 4433 0.0 0.1 139644 6860 pts/0 S 10:32 0:00 php -r while(1){sleep(1);}
System info
[alix#s4 tmp]$ uname -a
Linux s4 2.6.18-308.1.1.el5 #1 SMP Wed Mar 7 04:16:51 EST 2012 x86_64 x86_64 x86_64 GNU/Linux
[alix#s4 tmp]$ php -v
PHP 5.3.9 (cli) (built: Feb 15 2012 11:54:46)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
Why the processes killed in TEST A but not in TEST B? Does the output impact the SIGKILL?
Any suggestion?
There is a PIPE between php -r 'while(1){sleep(1);echo PHP_OS;} (process C) and it's parent (process B), posix_kill($pid, SIGKILL) sends KILL signal to process B, then process B is terminated, but process C doesn't know anything about the signal and continues to run and outputs something to the broken pipe, when process C receives the SIGPIPE signal but has no idea how to handle it so it exits.
You can verify it with strace (run php limit.php "strace php -r 'while(1){sleep(1); echo PHP_OS;};'" 1), and you will see something like this:
14:43:49.254809 write(1, "Linux", 5) = -1 EPIPE (Broken pipe)
14:43:49.254952 --- SIGPIPE (Broken pipe) # 0 (0) ---
14:43:49.255110 close(2) = 0
14:43:49.255212 close(1) = 0
14:43:49.255307 close(0) = 0
14:43:49.255402 munmap(0x7fb0762f2000, 4096) = 0
14:43:49.257781 munmap(0x7fb076342000, 1052672) = 0
14:43:49.258100 munmap(0x7fb076443000, 266240) = 0
14:43:49.258268 munmap(0x7fb0762f3000, 323584) = 0
14:43:49.258555 exit_group(0) = ?
As to php -r 'while(1){sleep(1);}, because there is no broken pipe occurs after it's parent dies, so it continues to run as expected.
Generally speaking, you should kill the whole process group but not only the process itself if you want to kill it's children too, with PHP you can add process B to its own process group, and kill the whole group then, here is the diff with your code:
--- limit.php 2012-08-11 20:50:22.000000000 +0800
+++ limit-new.php 2012-08-11 20:50:39.000000000 +0800
## -9,11 +9,13 ##
if (-1 == $pid) {
die('FORK_FAILED');
} elseif ($pid == 0) {
+ $_pid = posix_getpid();
+ posix_setpgid($_pid, $_pid);
exec($cmd);
posix_kill(posix_getppid(), SIGALRM);
} else {
pcntl_signal(SIGALRM, create_function('$signo',"die('EXECUTE_ENDED');"));
sleep($tl);
- posix_kill($pid, SIGKILL);
+ posix_kill(-$pid, SIGKILL);
die("TIMEOUT_KILLED : $pid");
}
You send the kill signall to your forked process, but that does not propagate to it's children or grandchildren. As such they are orphaned and continue running until something stops them from doing so. (In this case, any attempts to write to stdout should cause an error that then forces them to exit. Redirection of output would also probably result in indefinitely-running orphans.)
You want to send a kill signal to the process and all it's children. Unfortunately I lack the knowledge to tell you a good way to do that. I'm not very familiar with the process control functionality of PHP. Could parse the output of ps.
One simple way I found that works though is to send a kill signal to the whole process group with the kill command. It's messy, and it adds an extra "Killed" message to output on my machine, but it seems to work.
<?php
declare(ticks = 1);
if ($argc<2) die("Wrong parameter\n");
$cmd = $argv[1];
$tl = isset($argv[2]) ? intval($argv[2]) : 3;
$pid = pcntl_fork();
if (-1 == $pid) {
die('FORK_FAILED');
} elseif ($pid == 0) {
exec($cmd);
posix_kill(posix_getppid(), SIGALRM);
} else {
pcntl_signal(SIGALRM, create_function('$signo',"die('EXECUTE_ENDED');"));
sleep($tl);
$gpid = posix_getpgid($pid);
echo("TIMEOUT_KILLED : $pid");
exec("kill -KILL -{$gpid}"); //This will also cause the script to kill itself.
}
For more information see: Best way to kill all child processes

Categories