PHP exec() function and escapeshellarg function still allowing command injection - php

i have been trying to fix a vulnerablity where input from a user is passed through to the php exec function. The input is sanitized using escapeshellarg but it seems like it still allows code to be injected and executed. I tested this using Burp Suite's collaborator functionality by doing a nslookup.
I am unable to provide the exact code but below is a pretty close example. Can someone please shed some light why this works?
$input = 'filename$(whoami).pdf';
$cmd = 'rm -rf ' . escapeshellarg($input) . ' 2>&1';
exec($cmd);

Related

Playing something with cvlc on linux via php

i have the following PHP Code:
if(isset($_GET["href"]) && isset($_GET["name"])) {
exec("cvlc " . $_GET["href"] . " &");
}
the href is definitively a valid URL, and the exec function is also called (i tried via echo), also the cvlc command works fine when i type it into the console, however once i run it through the browser, it's just loading forever.
The exec command is also working fine, i just tested it.
Edit: The url i tried to play was http://dradio.de/streaming/dlf.m3u, but i tried a few others too.
Thanks!
Try to run the command inserting a double quote to the url:
exec("cvlc \"" . $_GET["href"] . "\" &");
(also please note, that this code is vulnerable to RCE, so keep attention!)

Trouble getting PHP to execute Lua script

So I'm working with PHP to attempt to execute a script I have in the same directory. The script runs fine locally and the permissions for the http-data user are set to be able to execute the script referenced in this block of PHP
$cmd = system('th neural_style.lua -style_image'.' ~/'.$style.'.jpg '.'-content_image '.$content_image.' -gpu 0 -backend cudnn -save_iter 1 -cudnn_autotune -output_image /var/www/html/processed/'.$email.'/out.png 2>&1', $retval);
echo '
</pre>
<hr />Recent output: ' . $last_line . '
<hr />Return value: ' . $retval;
The script should execute fine using the system method from what I understand, I know the variables look messy though this is the error I get from PHP:
sh: th: command not found
I set my default interpreter to bash instead of dash thinking that might be an issue, no dice. Torch is in the same directory, and like I said runs fine as my login.
I know what I'm trying to do in a way is like sacrilege, if there is a better way to run a script that takes 8 minutes roughly to complete using some user input from the web, I want to know. This is just what came natural to me. I'm looking to notify the user when the process is complete with an email anyways so any way of executing it is just dandy.
Edit: any mention of "http-data" was supposed to say "www-data".
Change the default shell for your http-data user to bash or dash. It is currently using sh.
Check what your $PATH variable is inside the PHP environment.

Executing powershell script from PHP with arguments

I have been wracking my brain and my pc on this one, hoping someone can help me out here.
I have a PHP site that needs to execute a powershell script which in turn executes and executable.
the PHP that calls the .ps1 is
define('updaterPath','C:\\artemis\\DbUpdateUtility1.0.12.2');
define('outputLocation',updaterPath.'\\Output');
$CMD = updaterPath . '\\ArtemisXmlUtil.exe';
$action = 'import';
$args= ' -f' . outputLocation;
$psScriptPath = '.\\get-process.ps1';
$query = shell_exec("powershell -command $psScriptPath -cmd '$CMD' -action '$action' -paras '$args' < NUL");
my .ps1 script is:
param(
[string]$CMD,
[string]$action,
[string]$paras
)
& $CMD $action $paras
Right now, when I echo the full command, it looks perfect and can be copied and pasted into powershell and runs successfully, but when I try to actually execute it from php, it runs with only the $CMD variable and ignores the $action and $paras.
I tried concactenating the variables all into 1 string, but that fails as not even being able to see the executable.
the full command shouls look like:
C:\artemis\DbUpdateUtility1.0.12.2\ArtemisXmlUtil.exe import -fC:\artemis\DbUpdateUtility1.0.12.2\Output
Ok, figured this one out on my own.
The problem is how the command was being executed. Using the "&" forced powershell to ignore the parameters being pass into the script. The correct way, since the command is an executable anyhow, was to build the entire command as a string and pass it all at once to the ps1 file and then change the ps1 file to use the invoke-expression commandlet.
param(
[string]$CMD
)
Invoke-expression $CMD

How to run a linux command to compile a c program, from php script

I am trying to make an online judge for c programming. When user enters the c code and submits it, my form redirects to judge.php which is the action file for the form.
Here is what I have written in judge.php
<?php
$text=$_POST['code'];
//echo $text;
$var_str = var_export($text, true);
file_put_contents('code.c', $text);
$ans=exec('pwd');
$ans= exec('gcc code.c');
echo $ans;
?>
I have captured user input in $text and wrote it to a c file(code.c). Till now, it is fine.
But exec(gcc code.c) is not working and not giving any output. I tried other linux commnads like pwd, date, etc. They are working fine. What may be the reason for this and how to fix it?
It is not a directory issue i tried exec(pwd) and it gave the output as the same directory in which code is present.
I tried to run same code.c file from terminal and it is running fine. So, it is also not a 'permission' problem.
One more thing, how to echo the error message generated if any exec() command is not working properly?
After getting suggestion from the answer below, i tried
$cmd="gcc -std=c99 code.c -g -Wall mysql_config --libs --cflags -o db_obj.o --pedantic";
exec($cmd,$out,$status);
But it is also not working. The status returned is 1
Most probably it is permission issue. "whoami" says nobody. Please tell how to change the owner from nobody to root or how to assign the permission to execute gcc from nobody
Three main aspects to my answer
improper use of the exec function.
Look at the man pages. First, the exec function's signature is:
string exec ( string $command [, array &$output [, int &$return_var ]] )
So exec can take up to 3 arguments. It returns the last line of the command's output, like the docs state quite clearly:
The last line from the result of the command. If you need to execute a command and have all the data from the command passed directly back without any interference, use the passthru() function.
To get the output of the executed command, be sure to set and use the output parameter.
So in your case:
$lastLine = exec($command, $fullOutput, $status);
Is what you're looking for. If $status is anything else than 0, your command was unsuccessful. That's what you should check to react accordingly.
The full output of any command can be found in $fullOutput as a line-per-line array.
Output like:
all went well
except for this
Will look like this in the $fullOutput array:
array('all went well', 'except for this');
permissions can be an issue, still.
You say permissions aren't likely to be the cause of the problem, because you can run gcc from the command-line. All fine and dandy, but what user is running the PHP script on the server?
In the case of web-servers, that user is often called nobody, apache or something, and that user is very likely not permitted to run gcc. It's PHP that runs a new instance of whatever default shell it has set up (bash, probably), and it's PHP's user that logs in to that shell, and it's that user that is calling gcc...
Know who you are, and what groups you belong to. Try adding this to your script:
echo 'Script is running under user: ', exec('whoami'), '<br>', PHP_EOL;
echo 'member of the following groups: ', exec('groups'), '<br>', PHP_EOL;
And before you ask: yes, those are comma's... no need to concatenate, you can pass multiple variables/values to echo, separated by a comma. It's actually faster (think of it as C++'s std::cout << some_var << another_var;)
general issues + security
This all said and done: compiling C code from a php script isn't as simple as you seem to think it is. Suppose I were to write this:
#include <stdio.h>
#include <time.h>
int main ( void )
{
time_t t = time(NULL);
if (t%2)
{
float val = (float) t/2.0;
//do stuff with float...
}
else
{
unsigned long long val = t/2;
//do stuff with unsigned long long...
}
}
Your gcc test.c command would fail, because you failed to pass the argument -std=c99, for example.
If I wanted a script to compile a given file, I'd also expect that script to allow me to choose which arguments I compiled my code with, too -g, -Wall and, not to mention: cflags and libs (the output of pkg-config or mysql_config --cflags --libs, to name a specific example I recently used).
Basically, your script simply cannot deal with my wanting to compile something with a commind like
gcc -std=c99 code.c -g -Wall `mysql_config --libs --cflags` -o db_obj.o --pedantic
Which still is a simplified version of what many compilation commands look like, especially when debugging code under development. For stable releases, you'd probably drop -g and --pedantic, but you get my point...
Just think of what it means, allowing the user to pass a set of cli arguments, along with the code. They might pass an argument like -DSOME_MACRO or -O0, which means they might also pass -O0 && rm -Rf *. That means you'll have to call escapeshellcmd or escapeshellarg. Both of which will prohibit me from passing a valid argument, being:
`mysql_config --libs --cflags`
Which contains back-ticks, and thus will be escaped.
To be frank, I struggle to see the point of this exercise... and I'm leaving a lot out, still: the dangers of compiling (let alone running) user-provided code on your machine, for example, are not to be overlooked. You can't just compile code, and run it on your server: memory leaks, segfaults... heck, pure evil code is all getting compiled on your server unchecked if this is the code you have. Really, save yourself a lot of tears, and include an iframe that loads codepad or some similar service...
Recap:
always check the man for a function, see if you're getting all information it returns
check the permissions and runtime for the user that is actually executing the commands
Never trust the network, don't blindly assume people will submit valid, harmless code for you to compile.
Don't reinvent the wheel: compilation services exist, just forward those (but ask for permission first)
Try this code to execute c program from PHP file
<?php
// used to compile the c file using exec() in php
exec('gcc helloworld.c -o helloworld', $out, $status);
if (0 === $status) {
var_dump($out);
// used to execute the c file using exec() in php
exec('./helloworld', $out, $status);
if (0 === $status) {
var_dump($out);
} else {
echo "Command failed with status: $status";
}
} else {
echo "Command failed with status: $status";
}
?>

MySQL commands (not SQL statements) from PHP

Is it possible to, from within a PHP script, execute the same commands you could with the MySQL client?
I know I could theoretically call 'system' to invoke the mysql client installed on the system, but I am not sure how to avoid interactivity (I don't want a REPL/shell, I just want to fire a command). Is there a way to execute commands via the mysql client without going into the shell? In either case this approach seems a bit sketchy.
To clarify, when I say command I am referring to the follow: http://dev.mysql.com/doc/refman/5.0/en/mysql-commands.html
while ($obj = mysql_fetch_object($res)) {
$file = $path.$obj->base.".sql";
$cmd = "rm -f ".$file;
exec($cmd);
$cmd = "nice -19 mysqldump -h".$host." -u".$login." -p".$pass." ".$obj->base." > ".$file;
exec($cmd);
$sql = "update save_mysql set last_daily=NOW() where base = '".$obj->base."'";
mysql_query($sql);
}
Are you looking for something like this.
using exec function you can call mysql command`
Sounds hacky. There's Expect to handle "programming interactivity", i.e. a way to wait for the prompt to say particular things. I don't think exec will work, unless you can pass specific switches and run mysql in a non-interactive mode. Depending on what you're trying to do I'd say it best to try and figure out a SQL command you can send through the regular client libs.

Categories