Skip to content

Kévin Dunglas

Founder of Les-Tilleuls.coop (worker-owned cooperative). Creator of API Platform, FrankenPHP, Mercure.rocks, Vulcain.rocks and of some Symfony components.

Menu
  • Talks
  • Resume
  • Sponsor me
  • Contact
Menu

Exécuter des applications critiques avec PHP sous Unix

Posted on August 8, 2005 by Kévin Dunglas

suPHP permet d’exécuter des scripts PHP avec les droits de leur propriétaire ! Alors qu’avant si l’on voulais utiliser une commande critique dans un script PHP (avec un bit suid par exemple ou avec sudo) tous les utilisateurs du serveur web pouvait l’exécuter et donc compromettre le serveur, nous pouvons maintenant le faire sans risques !

Voyons ça en détails !

Pour atteindre notre but nous utiliserons tout simplement sudo et la fonction PHP exec () (on peut aussi utiliser system () ou encore passthru) !

Nous allons créer un script PHP qui ajoutera un utilisateur système grâce à la commande useradd. Vous obtiendrez toutes les informations nécessaire à l’utilisation de cette commande en tapant man useradd.

Pour cet exemple, nous considérerons que vous avez un serveur web avec PHP et suPHP d’installer correctement (voir ce How-To). L’utilisateur que nous utiliserons pour nos tests s’appellera très originalement Kévin, nous supposerons que ce compte existe et qu’il est fonctionnel. Le script que nous créerons ce nommera useradd.php et se trouvera dans le répertoire /var/www/Kévin/. Nous utiliserons un formulaire pour indiquer le nom d’utilisateur a ajouter ainsi que son mot de passe, ce formulaire sera dans la page useradd.html du le même répertoire.

Notez que pour une sécurité maximum il est judicieux de créer un utilisateur sans shell (indiquez /bin/false ou /sbin/nologin comme shell) pour exécuter nos scripts PHP critiques. De plus il faudra veiller à ce que votre script soit exempt de failles de sécurités, celle-ci pouvant compromettre gravement votre système ! Enfin veillez bien entendu à ce que les scripts ne soient pas ouvert en écriture (pas de chmod 777 !!!) !

Les règles sudo

Définissons tout d’abord les règles sudo nécessaire pour lancer la commande useradd depuis notre script. Lancez la commande visudo en tant que root et ajoutez cette règle: Kévin ALL= NOPASSWD: /usr/sbin/useradd * Nous indiquons que l’utilisateur Kévin peut exécuter le programme /usr/sbin/useradd sans avoir à indiquer de mot de passe.

Vous obtiendrez plus d’information sur la configuration de sudo en tapant $ man sudoers ou en consultant ce document sur Lea-linux.

Maintenant que sudo est configuré, codons !

Le formulaire

Ce formulaire n’est qu’une simple page web: /var/www/Kévin/useradd.html. Cette page se contente de transmettre le login et le mot de passe du compte a ajouter à useradd.php via la méthode POST.

<?xml version="1.0" encoding="ISO-8859-15"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//En" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="fr" lang="fr"> <head>  <title>Ajouter un utilisateur</title> </head> <body>  <h1>Ajouter un utilisateur système</h1>  <form action="useradd.php" method="post">    <p>      <label for="login">Nom d'utilisateur</label>: <input type="text" name="login" id="login" /><br />      <label for="pass">Mot de passe</label>: <input type="password" name="pass" id="pass" /><br />      <input type="submit" />    </p>  </form> </body> </html>

Le script PHP

Maintenant examinons le code de useradd.php (licence GPL):

<?php exec ('/usr/bin/sudo /usr/sbin/useradd -m -p ' . escapeshellarg (crypt ($_POST['pass'])) . ' ' . escapeshellarg ($_POST['login']), $sortie, $retour);

if ($retour == 0) echo 'L\'utilisateur <strong>' . $_POST['login'] . '</strong> a bien été créé.'; else echo 'Erreur ! Impossible de créer l\'utilisateur <strong>' . $_POST['login'] . '</strong>.'; ?>

Ce script est en réalité très simple:
Nous commençons par lancer la commande sudo (configurée plus haut) qui nous permet d’exécuter useradd. Commencez par consulter la documentation des fonctions PHP permettant l’exécution de programmes externes et la page man de useradd.
Remarquez que l’on utilise les chemins complets des exécutables sudo et useradd. C’est dans le but d’éviter des bugs et/ou problèmes de sécurité liés à la mauvaise configuration, ou à l’absence de la variable d’environnement PATH.
Chaque paramètre est vérifié à l’aide de la fonction escapeshellarg (). Cette fonction permet d’éviter que le système soit compromis suite au passage d’arguments volontairement erronés. Il est impératif de l’utiliser pour chaque argument fourni par l’utilisateur.
De même chaque commande provenant de l’extérieur (variable $_POST, $_GET, base de donnée, …) doit être vérifiée avec escapeshellcmd () !
Nous ajoutons un utilisateur grâce à la commande useradd. -m spécifie que le répertoire personnel (home) doit-être créé, -p permet de définir un mot de passe (indiquer sous forme cryptée avec crypt ()). Les deux dernières lignes effectuent une petite gestion des erreurs. Si le code de statut de réponse UNIX est égal à 0 alors tout c’est bien passé sans quoi une erreur c’est produite.

Le principal est dit ! Grâce à cet exemple vous pouvez entrevoir les possibilités que vous offre suPHP, à vous de les exploiter !

Related posts:

  1. Using the “103 Early Hints” Status Code in Go Applications
  2. suPHP: php4 et php5 sur le même serveur et exécution des scripts PHP avec les droits de leur propriétaire
  3. Un formulaire de création de compte avec Symfony et sfGuard
  4. EasyUbuntu: Ubuntu fonctionnelle (mp3, vidéos, plugins Firefox, P2P, …) en deux clicks !

Leave a ReplyCancel reply

Social

  • Bluesky
  • GitHub
  • LinkedIn
  • Mastodon
  • X
  • YouTube

Links

  • API Platform
  • FrankenPHP
  • Les-Tilleuls.coop
  • Mercure.rocks
  • Vulcain.rocks

Subscribe to this blog

Top Posts & Pages

  • JSON Columns and Doctrine DBAL 3 Upgrade
  • Securely Access Private Git Repositories and Composer Packages in Docker Builds
  • Preventing CORS Preflight Requests Using Content Negotiation
  • FrankenPHP: The Modern Php App Server, written in Go
  • Symfony's New Native Docker Support (Symfony World)
  • Develop Faster With FrankenPHP
  • How to debug Xdebug... or any other weird bug in PHP
  • HTTP compression in PHP (new Symfony AssetMapper feature)
  • PHP and Symfony Apps As Standalone Binaries
  • Generate a Symfony password hash from the command line

Tags

Apache API API Platform Buzz Caddy Docker Doctrine FrankenPHP Go Google GraphQL HTTP/2 Hydra hypermedia Hébergement Javascript JSON-LD Kubernetes La Coopérative des Tilleuls Les-Tilleuls.coop Lille Linux Mac Mercure Mercure.rocks Messagerie Instantanée MySQL performance PHP Punk Rock Python React REST Rock'n'Roll Schema.org Security SEO SEO Symfony Symfony Live Sécurité Ubuntu Web 2.0 webperf XML

Archives

Categories

  • DevOps (84)
    • Ubuntu (68)
  • Go (17)
  • JavaScript (46)
  • Mercure (7)
  • Opinions (91)
  • PHP (170)
    • API Platform (77)
    • FrankenPHP (9)
    • Laravel (1)
    • Symfony (97)
    • Wordpress (6)
  • Python (14)
  • Security (15)
  • SEO (25)
  • Talks (46)
© 2025 Kévin Dunglas | Powered by Minimalist Blog WordPress Theme