J'essaie de construire une liste de fonctions pouvant être utilisées pour l'exécution de code arbitraire. Le but n'est pas de lister les fonctions qui devraient être sur la liste noire ou autrement interdites. J'aimerais plutôt avoir une liste grep
- capable de drapeaux rouges pratiques lors de la recherche de passerelles pour un serveur compromis. .
L'idée est que si vous voulez créer un script PHP malveillant polyvalent, tel qu'un script "Web Shell" comme c99 ou r57, vous devrez utiliser un ou plusieurs des un ensemble relativement petit de fonctions quelque part dans le fichier afin de permettre à l'utilisateur d'exécuter du code arbitraire. La recherche de ces fonctions vous aide à affiner plus rapidement une botte de foin de dizaines de milliers de PHP fichiers en un ensemble relativement petit de scripts nécessitant un examen plus approfondi.
Clairement, par exemple, l'un des éléments suivants serait considéré comme malveillant (ou un code terrible):
_<? eval($_GET['cmd']); ?>
<? system($_GET['cmd']); ?>
<? preg_replace('/.*/e',$_POST['code']); ?>
_
et ainsi de suite.
En recherchant un site Web compromis l’autre jour, je n’ai pas remarqué de code malveillant car je ne savais pas que _preg_replace
_ pouvait devenir dangereux en utilisant le drapeau _/e
_ ( qui, sérieusement? Pourquoi est-ce même là ?). Y a-t-il d'autres que j'ai ratés?
Voici ma liste jusqu'à présent:
Shell Execute
system
exec
popen
backtick operator
pcntl_exec
_PHP Execute
eval
preg_replace
_ (avec _/e
_ modificateur)create_function
_include
[__once
_]/require
[__once
_] ( voir la réponse de Mario pour plus de détails sur l'exploit )Il pourrait également être utile d’avoir une liste de fonctions capables de modifier des fichiers, mais j’imagine que 99% du code d’exploitation contiendra au moins une des fonctions ci-dessus. Mais si vous avez une liste de toutes les fonctions capables d’éditer ou d’afficher des fichiers, publiez-la et je l’inclurai ici. (Et je ne compte pas _mysql_execute
_, car cela fait partie d'une autre classe d'exploit.)
Pour construire cette liste, j'ai utilisé 2 sources. ne étude chez Scarlet et RATS . J'ai également ajouté une partie de moi au mélange et les gens sur ce fil ont aidé.
Edit: Après avoir posté cette liste, j'ai contacté le fondateur de RIPS et à partir de maintenant, cet outil effectue une recherche PHP code pour l'utilisation de toutes les fonctions de cette liste.
La plupart de ces appels de fonction sont classés en tant que récepteurs. Lorsqu'une variable corrompue (telle que $ _REQUEST) est transmise à une fonction de récepteur, vous avez une vulnérabilité. Des programmes tels que RATS et RIPS utilisent les fonctionnalités de grep comme pour identifier tous les puits d'une application. Cela signifie que les programmeurs doivent faire très attention lors de l'utilisation de ces fonctions, mais si elles étaient toutes interdites, vous ne pourriez pas en faire beaucoup.
" Un grand pouvoir entraîne de grandes responsabilités. "
--Stan Lee
exec - Returns last line of commands output
passthru - Passes commands output directly to the browser
system - Passes commands output directly to the browser and returns last line
Shell_exec - Returns commands output
`` (backticks) - Same as Shell_exec()
popen - Opens read or write pipe to process of a command
proc_open - Similar to popen() but greater degree of control
pcntl_exec - Executes a program
Outre eval
, il existe d'autres moyens d'exécuter PHP code: include
/require
peut être utilisé pour l'exécution de code à distance sous la forme de Fichier local Inclure et inclure dans un fichier distant vulnérabilités.
eval()
assert() - identical to eval()
preg_replace('/.*/e',...) - /e does an eval() on the match
create_function()
include()
include_once()
require()
require_once()
$_GET['func_name']($_GET['argument']);
$func = new ReflectionFunction($_GET['func_name']); $func->invoke(); or $func->invokeArgs(array());
Ces fonctions acceptent un paramètre de chaîne qui pourrait être utilisé pour appeler une fonction du choix de l'attaquant. En fonction de la fonction, l'attaquant peut ou non avoir la capacité de transmettre un paramètre. Dans ce cas, une fonction Information Disclosure
telle que phpinfo()
peut être utilisée.
Function => Position of callback arguments
'ob_start' => 0,
'array_diff_uassoc' => -1,
'array_diff_ukey' => -1,
'array_filter' => 1,
'array_intersect_uassoc' => -1,
'array_intersect_ukey' => -1,
'array_map' => 0,
'array_reduce' => 1,
'array_udiff_assoc' => -1,
'array_udiff_uassoc' => array(-1, -2),
'array_udiff' => -1,
'array_uintersect_assoc' => -1,
'array_uintersect_uassoc' => array(-1, -2),
'array_uintersect' => -1,
'array_walk_recursive' => 1,
'array_walk' => 1,
'assert_options' => 1,
'uasort' => 1,
'uksort' => 1,
'usort' => 1,
'preg_replace_callback' => 1,
'spl_autoload_register' => 0,
'iterator_apply' => 1,
'call_user_func' => 0,
'call_user_func_array' => 0,
'register_shutdown_function' => 0,
'register_tick_function' => 0,
'set_error_handler' => 0,
'set_exception_handler' => 0,
'session_set_save_handler' => array(0, 1, 2, 3, 4, 5),
'sqlite_create_aggregate' => array(2, 3),
'sqlite_create_function' => 2,
La plupart de ces appels de fonction ne sont pas des puits. Mais il s’agit plutôt d’une vulnérabilité si l’une des données renvoyées est visible par un attaquant. Si un attaquant peut voir phpinfo()
, il s'agit certainement d'une vulnérabilité.
phpinfo
posix_mkfifo
posix_getlogin
posix_ttyname
getenv
get_current_user
proc_get_status
get_cfg_var
disk_free_space
disk_total_space
diskfreespace
getcwd
getlastmo
getmygid
getmyinode
getmypid
getmyuid
extract - Opens the door for register_globals attacks (see study in scarlet).
parse_str - works like extract if only one argument is given.
putenv
ini_set
mail - has CRLF injection in the 3rd parameter, opens the door for spam.
header - on old systems CRLF injection could be used for xss or other purposes, now it is still a problem if they do a header("location: ..."); and they do not die();. The script keeps executing after a call to header(), and will still print output normally. This is nasty if you are trying to protect an administrative area.
proc_Nice
proc_terminate
proc_close
pfsockopen
fsockopen
Apache_child_terminate
posix_kill
posix_mkfifo
posix_setpgid
posix_setsid
posix_setuid
Selon RATS, tous les fonctions du système de fichiers en php sont méchants. Certaines d'entre elles ne semblent pas très utiles à l'attaquant. D'autres sont plus utiles que vous ne le pensez. Par exemple, si allow_url_fopen=On
, une URL peut être utilisée comme chemin de fichier. Par conséquent, un appel à copy($_GET['s'], $_GET['d']);
peut être utilisé pour télécharger un script PHP n'importe où sur le système. De même, si un site est vulnérable à une demande envoyée via GET, toutes les fonctions du système de fichiers peuvent être utilisées de manière abusive pour canaliser et attaquer un autre hôte via votre serveur.
// open filesystem handler
fopen
tmpfile
bzopen
gzopen
SplFileObject->__construct
// write to filesystem (partially in combination with reading)
chgrp
chmod
chown
copy
file_put_contents
lchgrp
lchown
link
mkdir
move_uploaded_file
rename
rmdir
symlink
tempnam
touch
unlink
imagepng - 2nd parameter is a path.
imagewbmp - 2nd parameter is a path.
image2wbmp - 2nd parameter is a path.
imagejpeg - 2nd parameter is a path.
imagexbm - 2nd parameter is a path.
imagegif - 2nd parameter is a path.
imagegd - 2nd parameter is a path.
imagegd2 - 2nd parameter is a path.
iptcembed
ftp_get
ftp_nb_get
// read from filesystem
file_exists
file_get_contents
file
fileatime
filectime
filegroup
fileinode
filemtime
fileowner
fileperms
filesize
filetype
glob
is_dir
is_executable
is_file
is_link
is_readable
is_uploaded_file
is_writable
is_writeable
linkinfo
lstat
parse_ini_file
pathinfo
readfile
readlink
realpath
stat
gzfile
readgzfile
getimagesize
imagecreatefromgif
imagecreatefromjpeg
imagecreatefrompng
imagecreatefromwbmp
imagecreatefromxbm
imagecreatefromxpm
ftp_put
ftp_nb_put
exif_read_data
read_exif_data
exif_thumbnail
exif_imagetype
hash_file
hash_hmac_file
hash_update_file
md5_file
sha1_file
highlight_file
show_source
php_strip_whitespace
get_meta_tags
Vous devez également analyser les commandes include ($ tmp), Requérir (HTTP_REFERER) et * _once. Si un script d’exploitation peut écrire dans un fichier temporaire, il pourra l’inclure ultérieurement. Fondamentalement, une évaluation en deux étapes.
Et il est même possible de masquer le code distant avec des solutions de contournement telles que:
include("data:text/plain;base64,$_GET[code]");
De plus, si votre serveur Web a déjà été compromis, vous ne verrez pas toujours le mal non codé. L'exploit Shell est codé en gzip. Pensez à include("zlib:script2.png.gz");
No eval ici, toujours le même effet.
Ce n'est pas une réponse en soi, mais voici quelque chose d'intéressant:
$y = str_replace('z', 'e', 'zxzc');
$y("malicious code");
Dans le même esprit, call_user_func_array()
peut être utilisé pour exécuter des fonctions obscurcies.
Je suis surpris que personne n'ait mentionné echo
et print
comme points d'exploitation de la sécurité.
Cross-Site Scripting (XSS) est un exploit de sécurité sérieux, car il est même plus courant que les exploits d'exécution de code côté serveur.
je voudrais particulièrement ajouter unserialize () à cette liste. Il existe depuis longtemps de nombreuses vulnérabilités, notamment l'exécution de code arbitraire, le déni de service et la fuite d'informations en mémoire. Il ne doit jamais être appelé sur des données fournies par l'utilisateur. Beaucoup de ces vuls ont été corrigés dans les versions au cours des dernières années de rosée, mais il conserve encore quelques vilains méchants au moment de la rédaction.
Pour plus d’informations sur les fonctions et l’utilisation douteuses de PHP, consultez le projet renforcé PHP et ses conseils. Aussi le mois récent de PHP Sécurité et le mois de 2007 de PHP projets
Notez également que, par conception, la désérialisation d'un objet entraîne l'exécution des fonctions de constructeur et de destructeur; une autre raison de ne pas l'appeler sur des données fournies par l'utilisateur.
Mon VPS est configuré pour désactiver les fonctions suivantes:
root@vps [~]# grep disable_functions /usr/local/lib/php.ini
disable_functions = dl, exec, Shell_exec, system, passthru, popen, pclose, proc_open, proc_Nice, proc_terminate, proc_get_status, proc_close, pfsockopen, leak, Apache_child_terminate, posix_kill, posix_mkfifo, posix_setpgid, posix_setsid, posix_setuid
PHP a suffisamment de fonctions potentiellement destructibles pour que votre liste soit trop grosse pour grep. Par exemple, PHP a chmod et chown, ce qui pourrait être utilisé pour simplement désactiver un site Web.
EDIT: Peut-être voudrez-vous créer un script bash qui recherche dans un fichier un tableau de fonctions groupées par danger (fonctions mauvaises, fonctions pires, fonctions à ne jamais utiliser), puis calculez la relativité du danger que le fichier impose en pourcentage. Exportez ensuite ceci dans une arborescence du répertoire avec les pourcentages marqués à côté de chaque fichier, si le seuil est supérieur à 30% de danger.
Soyez également conscient de la classe de "vulnérabilités d'interruption" qui permettent la lecture et l'écriture d'emplacements de mémoire arbitraires!
Ceux-ci affectent des fonctions telles que trim (), rtrim (), ltrim (), explode (), strchr (), strstr (), substr (), chunk_split (), strtok (), addcslashes (), str_repeat () . Ceci est en grande partie, mais pas exclusivement, dû à la fonction de référence par référence du langage, obsolète depuis 10 ans, mais non désactivée.
Pour plus d’informations, voir l’exposé de Stefan Esser sur les vulnérabilités liées aux interruptions et autres problèmes de niveau inférieur PHP sur BlackHat USA 2009 SlidesPaper
Cet article/cette présentation montre également comment dl () peut être utilisé pour exécuter du code système arbitraire.
Des vecteurs exec théoriques, spécifiques à la plate-forme mais également théoriques:
Et il y a beaucoup plus de méthodes déguisantes:
Outre la construction du langage eval
, il existe une autre fonction qui permet l'exécution de code arbitraire: assert
assert('ex' . 'ec("kill --bill")');
Une source d'exploits intéressants n'a pas été mentionnée. PHP permet aux chaînes de contenir 0x00
octets. Les fonctions sous-jacentes (libc) traitent cela comme la fin d'une chaîne.
Cela permet des situations dans lesquelles la vérification de la santé mentale (mal implémentée) dans PHP peut être trompée, par exemple. dans une situation comme:
/// note: proof of principle code, don't use
$include = $_GET['file'];
if ( preg_match("/\\.php$/",$include) ) include($include);
Cela peut inclure n’importe quel fichier - pas seulement ceux se terminant par .php
- en appelant script.php?file=somefile%00.php
Donc, toute fonction qui n'obéira pas à la longueur de chaîne de PHP peut conduire à une certaine vulnérabilité.
Qu'en est-il des éléments syntaxiques dangereux?
Le " variable variable " ($$var
) trouvera une variable dans l'étendue actuelle sous le nom de $ var. S'il n'est pas utilisé correctement, l'utilisateur distant peut modifier ou lire toute variable de l'étendue actuelle. Fondamentalement, un eval
plus faible.
Ex: vous écrivez du code $$uservar = 1;
, puis l'utilisateur distant définit $uservar
sur "admin", ce qui entraîne la configuration de $admin
sur 1
dans l'étendue actuelle.
Je suppose que vous ne pourrez pas vraiment trouver tous les exploits possibles en analysant vos fichiers source.
aussi, s'il y a de très bonnes listes fournies ici, vous pouvez manquer une fonction qui peut être exploitée
il pourrait toujours y avoir un code mal "caché" comme celui-ci
$ myEvilRegex = base64_decode ('Ly4qL2U =');
preg_replace ($ myEvilRegex, $ _POST ['code']);
vous pouvez maintenant dire, je prolonge simplement mon script pour correspondre également à cela
mais alors vous aurez que mayn "peut-être un code maléfique" qui est en outre hors de son contexte
donc pour être (pseudo) sécurisé, vous devriez vraiment écrire du bon code et lire tout le code existant vous-même
Opérateur de Backtick Backtick sur le manuel php
Je sais que move_uploaded_file
a été mentionné, mais le téléchargement de fichiers est en général très dangereux. La seule présence de $_FILES
devrait susciter certaines inquiétudes.
Il est tout à fait possible d'incorporer le code PHP dans tout type de fichier. Les images peuvent être particulièrement vulnérables avec des commentaires de texte. Le problème est particulièrement gênant si le code accepte l'extension trouvée dans les données $_FILES
telles quelles.
Par exemple, un utilisateur peut télécharger un fichier PNG valide avec le code PHP incorporé sous le nom "foo.php". Si le script est particulièrement naïf, il peut en fait copier le fichier sous le nom "/uploads/foo.php". Si le serveur est configuré pour autoriser l'exécution de scripts dans les répertoires de téléchargement de l'utilisateur (ce qui est souvent le cas et constitue un terrible oubli), vous pouvez instantanément exécuter n'importe quel code PHP arbitraire. (Même si l'image est enregistrée au format .png, il pourrait être possible d'exécuter le code via d'autres failles de sécurité.)
Une liste (non exhaustive) d'éléments à vérifier sur les téléchargements:
Ajoutons pcntl_signal
et pcntl_alarm
à la liste.
Avec l'aide de ces fonctions, vous pouvez contourner toute restriction set_time_limit créée dans le fichier php.ini ou dans le script.
Ce script, par exemple, fonctionnera pendant 10 secondes malgré set_time_limit(1);
(Nous remercions Sebastian Bergmanns Tweet et Gist :
<?php
declare(ticks = 1);
set_time_limit(1);
function foo() {
for (;;) {}
}
class Invoker_TimeoutException extends RuntimeException {}
class Invoker
{
public function invoke($callable, $timeout)
{
pcntl_signal(SIGALRM, function() { throw new Invoker_TimeoutException; }, TRUE);
pcntl_alarm($timeout);
call_user_func($callable);
}
}
try {
$invoker = new Invoker;
$invoker->invoke('foo', 1);
} catch (Exception $e) {
sleep(10);
echo "Still running despite of the timelimit";
}
Ces fonctions peuvent également avoir des effets désagréables.
str_repeat()
unserialize()
register_tick_function()
register_shutdown_function()
Les deux premiers peuvent épuiser toute la mémoire disponible et le dernier maintient l'épuisement ...
Il y a des tas d'exploits PHP qui peuvent être désactivés avec les paramètres du fichier PHP.ini. Register_globals est un exemple évident, mais en fonction des paramètres, il peut également être possible d'inclure ou d'ouvrir des fichiers de machines distantes via HTTP, ce qui peut être exploité si un programme utilise des noms de fichiers variables pour l'une de ses fonctions include () ou de gestion de fichiers.
PHP autorise également l'appel de fonction de variable en ajoutant () à la fin du nom d'une variable - par exemple, $myvariable();
appellera le nom de fonction spécifié par la variable. C'est exploitable; Par exemple, si un attaquant peut obtenir que la variable contienne le mot 'eval' et puisse contrôler le paramètre, il peut faire tout ce qu'il veut, même si le programme ne contient pas réellement la fonction eval ().
Je crains que ma réponse ne soit un peu trop négative, mais ...
IMHO, chaque fonction et méthode peuvent être utilisées à des fins néfastes. Considérez-le comme un effet de néfiance: une variable est affectée à un utilisateur ou à une entrée distante, la variable est utilisée dans une fonction, la valeur de retour de la fonction utilisée dans une propriété de classe, la propriété de classe utilisée dans une fonction de fichier, et ainsi de suite. Rappelez-vous: une adresse IP falsifiée ou une attaque de l'homme du milieu peut exploiter l'intégralité de votre site Web.
Votre meilleure option est de tracer du début à la fin toute entrée utilisateur ou distante possible, en commençant par $_SERVER
, $_GET
, $_POST
, $_FILE
, $_COOKIE
, include(some remote file)
(if ()allow_url_fopen
est activé), toutes les autres fonctions/classes traitant des fichiers distants, etc. Vous créez par programme un profil de trace de pile de chaque utilisateur ou fournisseur valeur. Cela peut être fait par programme en obtenant toutes les instances répétées de la variable et des fonctions ou méthodes affectées, puis en compilant de manière récursive une liste de toutes les occurrences de ces fonctions/méthodes, etc. Examinez-le pour vous assurer qu'il passe d'abord par les fonctions de filtrage et de validation appropriées par rapport à toutes les autres fonctions qu'il touche. Ceci est bien sûr un examen manuel, sinon vous aurez un nombre total de commutateurs case
égal au nombre de fonctions et de méthodes dans PHP (y compris défini par l'utilisateur).
Sinon, pour gérer uniquement les entrées utilisateur, faites initialiser une classe de contrôleur statique au début de tous scripts qui 1) valide et stocke toutes les valeurs d'entrée fournies par l'utilisateur par rapport à une liste blanche des objectifs autorisés; 2) efface cette source d’entrée (c.-à-d. $_SERVER = null
). Vous pouvez voir où cela devient un peu naziesque.
Il y a eu quelques discussions à ce sujet sur security.stackexchange.com récemment
fonctions pouvant être utilisées pour l'exécution de code arbitraire
Eh bien, cela réduit un peu la portée - mais puisque "print" peut être utilisé pour injecter du javascript (et donc voler des sessions, etc.), il est encore quelque peu arbitraire.
n'est pas de lister les fonctions qui devraient être mises sur la liste noire ou autrement interdites. Plutôt, j'aimerais avoir une liste grep -able
C'est une approche raisonnable.
Cependant, envisagez d'écrire votre propre analyseur: très bientôt, vous allez trouver une approche basée sur grep qui devient incontrôlable (awk serait un peu mieux). Bientôt, vous souhaiterez également avoir mis en place une liste blanche!
En plus des éléments évidents, je recommanderais de signaler tout ce qui fait une inclusion avec un argument autre que le littéral de chaîne. Méfiez-vous de __autoload () aussi.
Voici une liste des fonctions que mon fournisseur désactive pour des raisons de sécurité:
La plupart des attaques dans le code utilisent plusieurs sources d'accès ou plusieurs étapes pour s'exécuter elles-mêmes. Je voudrais rechercher non seulement un code, ou une méthode ayant un code malveillant, mais toutes les méthodes, la fonction l’exécutant ou l’appelant. La meilleure sécurité inclurait également le codage et la validation des données de formulaire à l’entrée et à la sortie.
Veillez également à ne pas définir les variables système, elles peuvent ensuite être appelées à partir de n’importe quelle fonction ou méthode du code.
Plusieurs dépassements de mémoire tampon ont été découverts à l'aide de fonctions de caractères 4 bits interprétant le texte. htmlentities () htmlspecialchars ()
en haut, une bonne défense consiste à utiliser mb_convert_encoding () pour convertir en encodage simple avant interprétation.
Vous pouvez trouver une liste constamment mise à jour de récepteurs sensibles (fonctions php exploitables) et de leurs paramètres dans RIPS /config/sinks.php, un analyseur de code source statique permettant de détecter les vulnérabilités dans PHP. _ applications qui détectent également PHP backdoors.