web services - What is the safest way to access CLI program in PHP

808

I'm writing a PHP library that will need to reach out to the system and access a command line program that doesn't have a PHP interface (or PHP library). As such, I was wondering what is the best (and the safest way) to access the system to retrieve output from a CLI program? I've taken a look at bothsystem() andexec(), but still not sure which is the best to use in a situation like this.

The library will get a string of user-passed text, and transmit it to the command line, retrieving back another string of text. Obviously, with passing user-provided data to the CLI, I will be doing a verification to ensure that no executable data can be passed.

817

Answer

Solution:

I would suggest together with and .


To clarify (I was on the go when I first posted this answer): The right way to secure a shell command is:

$exe = 'cat';
$args = array('/etc/passwd');

$args = array_map('escapeshellarg', $args);

$escaped = escapeshellcmd($exe . ' ' . implode(' ', $args));

Here's a legitimate demo (and a nefarious demo as well) of the above code.

The above is just a dummy example, of course. But the main idea is that you applyescapeshellarg() to each argument and then callescapeshellcmd() on the whole command string (including the path to the executable and the previously escaped arguments). This is critical in arbitrary commands.

Note: By secure, I mean making it impossible to perform shell injection attacks by escaping characters that have special meaning like>,<,&&, and more (see the Wikipedia link) while at the same time properly quoting spaces and other characters that may also have special interpretations by the shell.

With that aside, if you're already white-listing all the commands allowed, you already have the best possible security and you don't need the above functions (althought it doesn't hurt to use them anyway).


Regarding the actual calling function, they all pretty much do the same thing with a few quirks. Personally, I prefershell_exec() since its return value is more versatile (from this page):

Except from the , you can mimic the behavior of all the other functions with the return value ofshell_exec(). However, the inverse it's either harder to do, or just not possible.

I hope this clears things up for you.

871

Answer

Solution:

Ideally, you would usepassthru() from a pre-defined list of possible inputs (so that if userinput == 'operation_a' you can{ passthru('operation_a'); } without worrying about sanitizing input). Otherwise, usepassthru() with some serious sanitation of input.passthru() allows you to capture the output of the command and pass the whole lump back to the browser. This function is particularly useful if you are expecting binary output (like from image generation, &c.).

People are also looking for solutions to the problem: php - Monolith structure in bundle-less Symfony 4

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.