web-dev-qa-db-fra.com

Quelle est la différence entre EscapeShellarg et EscapeShellcmd?

PHP a 2 fonctions étroitement liées, escapeshellarg() et escapeshellcmd() . Ils semblent tous les deux faire des choses similaires, notamment aider à rendre une chaîne plus sûre à utiliser dans system()/exec()/etc.

Lequel devrais-je utiliser? Je veux juste pouvoir prendre une certaine entrée de l'utilisateur et exécuter une commande dessus et ne pas avoir tout sauf. Si PHP avait une fonction de type EXED qui a pris une gamme de chaînes (comme Argv), qui contourne la coquille, j'utiliserais cela. Semblable à Python subprocess.call() fonction.

37
Rory

De - http://ie2.php.net/manual/fr/function.escapeshellarg.php

escapeShellarg () ajoute des guillemets simples autour d'une chaîne et d'une cité/échappe à des guillemets simples existants vous permettant de transmettre une chaîne directement à une fonction de coquille et que vous devez être traité comme un argument unique.

escapeShellarg, comme son nom l'indique, est utilisé comme argument de coque de passage. Par exemple, vous souhaitez répertorier le répertoire actuel,

$dir = ".";
system('ls '.escapeshellarg($dir));
escapeshellcmd('ls $dir');

Les deux font des choses similaires et dépendent simplement de la façon dont vous gérez votre logique, assurez-vous de vous normaliser et de valider votre contribution avant de passer directement à ces méthodes pour une meilleure sécurité.

4
Jay Zeng

Généralement, vous voudrez utiliser escapeshellarg , en faisant un seul argument sur une commande de coquille en sécurité. Voici pourquoi:

Supposons que vous ayez besoin d'obtenir une liste de fichiers dans un répertoire. Vous proposez ce qui suit:

$path  = 'path/to/directory'; // From user input

$files = Shell_exec('ls '.$path);
// Executes `ls path/to/directory`

(C'est une mauvaise façon de le faire, mais pour l'illustration ours avec moi)

Cela fonctionne "super" pour ce chemin, mais supposons que le chemin donné était quelque chose de plus dangereux:

$path  = 'path; rm -rf /';

$files = Shell_exec('ls '.$path);
// Executes `ls path`, then `rm -rf /`;

Étant donné que le chemin donné a été utilisé non analicité, toute commande peut potentiellement être courue. Nous pouvons utiliser le escapeshell* Méthodes pour éviter cela.

Tout d'abord, en utilisant escapeshellcmd :

$path = 'path; rm -rf /';

$files = Shell_exec(escapeshellcmd('ls '.$path));
// Executes `ls path\; rm -rf /`;

Cette méthode n'échappe que des caractères susceptibles de conduire à exécuter plusieurs commandes, alors lorsqu'il empêche le risque de sécurité majeur, il peut encore entraîner une transmission de plusieurs paramètres.

Maintenant, en utilisant escapeshellarg :

$path = 'path; rm -rf /';

$files = Shell_exec('ls '.escapeshellarg($path));
// Executes `ls 'path; rm -rf /'`;

Cela nous donne le résultat que nous voulons. Vous remarquerez que cela a cité l'argument entier, de sorte que les espaces individuels, etc., n'ont pas besoin d'être échappés. Si l'argument devait avoir citations, ils seraient cités.

Pour résumer, escapeshellcmd garantit qu'une chaîne n'est qu'une commande, tandis que escapeshellarg rend une chaîne sans danger pour une seule argument à une commande.

95
Adam

Une solution simple pour déterminer la différence entre deux sondes similaires PHP Fonctions consiste à écrire un script de ligne de commande rapide dans PHP qui diffuse toute la recherche possible. espace et montrer simplement des différences (dans ce cas, comparer 256 valeurs):

<?php
    for ($x = 0; $x < 256; $x++)
    {
        if (chr($x) !== escapeshellcmd(chr($x)))  echo $x . " - cmd:  " . chr($x) . " != " . escapeshellcmd(chr($x)) . "\n";
    }

    echo "\n\n";

    for ($x = 0; $x < 256; $x++)
    {
        if (chr($x) !== substr(escapeshellarg(chr($x)), 1, -1))  echo $x . " - arg:  " . chr($x) . " != " . substr(escapeshellarg(chr($x)), 1, -1) . "\n";
    }
?>

Exécuter ce qui précède sous PHP 5.6 sur les sorties d'invite de commande Windows:

0 - cmd:    !=
10 - cmd:
 != ^

33 - cmd:  ! != ^!
34 - cmd:  " != ^"
35 - cmd:  # != ^#
36 - cmd:  $ != ^$
37 - cmd:  % != ^%
38 - cmd:  & != ^&
39 - cmd:  ' != ^'
40 - cmd:  ( != ^(
41 - cmd:  ) != ^)
42 - cmd:  * != ^*
59 - cmd:  ; != ^;
60 - cmd:  < != ^<
62 - cmd:  > != ^>
63 - cmd:  ? != ^?
91 - cmd:  [ != ^[
92 - cmd:  \ != ^\
93 - cmd:  ] != ^]
94 - cmd:  ^ != ^^
96 - cmd:  ` != ^`
123 - cmd:  { != ^{
124 - cmd:  | != ^|
125 - cmd:  } != ^}
126 - cmd:  ~ != ^~
255 - cmd:    != ^ 


0 - arg:    !=
33 - arg:  ! !=
34 - arg:  " !=
37 - arg:  % !=
92 - arg:  \ != \\

Exécuter le même script sous PHP 5.5 pour les sorties Linux:

0 - cmd:   !=
10 - cmd:
 != \

34 - cmd:  " != \"
35 - cmd:  # != \#
36 - cmd:  $ != \$
38 - cmd:  & != \&
39 - cmd:  ' != \'
40 - cmd:  ( != \(
41 - cmd:  ) != \)
42 - cmd:  * != \*
59 - cmd:  ; != \;
60 - cmd:  < != \<
62 - cmd:  > != \>
63 - cmd:  ? != \?
91 - cmd:  [ != \[
92 - cmd:  \ != \\
93 - cmd:  ] != \]
94 - cmd:  ^ != \^
96 - cmd:  ` != \`
123 - cmd:  { != \{
124 - cmd:  | != \|
125 - cmd:  } != \}
126 - cmd:  ~ != \~
128 - cmd:   !=
...
255 - cmd:  ÿ !=


0 - arg:   !=
39 - arg:  ' != '\''
128 - arg:   !=
...
255 - arg:  ÿ !=

La principale différence est que PHP EscapeShellcmd () sous Windows préfixe des caractères avec un caret ^ au lieu d'une barre oblique inverse \. Les bizarreries sous Linux à partir de CHR (128) à la chr (255) pour les deux EscapeShellcmd ( ) et EscapeShellarg () On peut s'expliquer par l'utilisation de points de code UTF-8 non valides supprimés, tronqués ou mal interprétés.

Aussi de note que EscapeShellarg () s'échappe beaucoup moins de caractères et obtient toujours le travail.

En termes de sécurité globale et de sécurité et de sécurité des applications, vous préférez utiliser ESCAPESHellarg () et échapper individuellement à chaque argument consiste en une entrée utilisateur.

Un dernier exemple:

echo escapeshellarg("something here") . "\n";
echo escapeshellarg("'something here'") . "\n";
echo escapeshellarg("\"something here\"") . "\n";

Sorties Windows:

"something here"
"'something here'"
" something here "

Sorties Linux:

'something here'
''\''something here'\'''
'"something here"'

Php escapeshellarg () sur Windows entoure la chaîne avec le "caractère à double citation" pendant que Linux utilise le caractère de citation unique. PHP sur Windows remplace complètement les guillemets internes (ce qui pourrait être un problème dans certains cas). PHP sur Linux va un peu hors de sa manière pour échapper à des guillemnes et de backslashes\sont échappés \\ sur Windows. PHP = escapeshellarg () sur Windows remplace également! et% de caractères avec des espaces. Toutes les plates-formes remplacent\0 avec des espaces.

Notez que le comportement n'est pas nécessairement cohérent entre PHP Versions et le PHP Documentation ne reflète pas toujours la réalité. Écrire un script rapide ou lire le code source de = PHP sont deux façons de déterminer ce qui se passe dans les coulisses.

4
CubicleSoft

Le PHP Docs sortez la différence:

EscapeShellcmd :

Les caractères suivants sont précédés d'une barre oblique inverse: # &; `| *? ~ <> ^ () [] {} $\X0a et\xff. "et" ne sont échappés que s'ils ne sont pas jumelés. Sous Windows, tous ces caractères plus% sont remplacés par un espace à la place.

EscapeShellarg :

ajoute des guillemets simples autour d'une chaîne et d'une citation/échappe à des guillemets simples existants vous permettant de transmettre une chaîne directement à une fonction de coquille et que vous devez être traité comme un seul argument sûr.

La source:

http://www.php.net/manual/fr/function.escapeshellcmd.phphttp://www.php.net/manual/fr/function.escapeshellarg.php

4
mph