Niveau :
Résumé : alias / /%{username}
Aujourd'hui je voudrais faire un serveur web qui se comporterait comme un serveur FTP ou SFTP. Lorsqu'un utilisateur unix se connecte à un serveur FTP avec un login et un mot de passe, il lui est présenté un contenu qui lui est propre (son $HOME par exemple).
Comment faire l'équivalent avec apache ?
Dit autrement, je voudrais que les 2 commandes suivantes renvoient un contenu différent :
$ wget http://userA@www.monserveur.com/ # répertoire A $ wget http://userB@www.monserveur.com/ # répertoire B
Pour cela il faut jouer avec les RewriteRules, mais c'est plus balaise que ça en a l'air.
Premièrement il faut une authentification. J'ai choisi ldap, mais prenez la méthode que vous préférez : http://httpd.apache.org/docs/2.2/mo... tout ce qui commence par mod_authn est valable. Voici comment on la met en place :
<Location /> AuthType basic AuthName "My server" AuthBasicProvider ldap AuthLDAPURL ldap://serveur.ldap.com/dc=domaine,dc=com?uid?sub AuthLDAPBindDN cn=user,ou=technical,dc=domaine,dc=com AuthLDAPBindPassword password Require valid-user </Location>
Ensuite on joue avec RewriteRule, les variables s'appellent sous la forme %{ENV:VARIABLE}
# utilisez %{ENV:USER_AUTH} pour ceux qui n'ont pas choisi l'authent LDAP RewriteRule ^(.*) /%{ENV:AUTHENTICATE_uid}/$1
Mais ça ne marche pas. Tout d'abord on apprend qu'il faut mettre les règles dans le Location sinon les variables d'authentification ne sont pas disponibles. Ensuite on a oublié d'activer le rewrite engine. Et enfin dans un location (ou un directory) on ne matche plus la request uri mais le chemin créé à partir de cette uri. Cela qui une fois corrigé nous donne quelque chose comme ça :
<Location /> RewriteEngine On # le résultat sera automatiquement préfixé par le DocumentRoot si on ne le fait pas nous même # notez l'absence du / initial dans le pattern ... RewriteRule ^var/www/html/(.*) /%{ENV:AUTHENTICATE_uid}/$1 </Location>
Mais ça ne marche toujours pas. En effet, le rewrite engine d'apache est réentrant, quelle que soit la modification et quel que soit le flag utilisé, si une url est modifiée, apache fait une redirection interne et relance toute la machinerie (dont les redirections). Pour les petits malins, non [L] n'est pas fait pour ça, par contre la doc évoque un [END] qui aurait cette fonctionnalité mais je ne l'ai pas trouvé.
Il nous faut donc un moyen de détecter qu'une url a déjà été transformée par une RewriteRule. Malheureusement les variables (comme %{ENV:AUTHENTICATE_uid}) ne sont valables que dans la partie gauche de RewriteCond ou dans la partie droite de RewriteRule ce qui nous limite sévèrement. On ne peut pas matcher le chemin en pour détecter qu'il contient le répertoire de l'utilisateur. De plus on ne peut pas utiliser une autre racine, apache ajouterait automatiquement le DocumentRoot en cours.
J'ai essayé en utilisant des variables d'environnement temporaire (avec [E=VAR:VALUE]), mais le rewrite engine l'évalue trop tard et ne détecte pas la nouvelle valeur de la variable modifiée par lui-même.
Ma solution est donc de mettre en place un unique répertoire contenant les utilisateurs avec un nom improbable car il ne pourra pas être utilisé comme nom de répertoire dans les répertoires utilisateurs. Et d'utiliser ce nom de répertoire comme marqueur d'url déjà traitée. Ce qui nous donne :
# mon répertoire s'appelle ____data____ RewriteRule ^var/www/html/(?!____data____/)(.*) /____data____/%{ENV:AUTHENTICATE_uid}/$1
C'est bien joli, mais ça n'empercherait pas un utilisateur d'aller voir dans le répertorie de son voisin. En effet, ce ne sont que des rewrite rules, pas des droits d'accès. Puisqu'on ne peut pas utiliser les noms de répertoire utilisateur dans les require pour le matcher avec les nom d'utilisateur (on se mordrait la queue (et ça fait mal (au dos))). Il nous faut donc le garantir d'une autre façon, en forçant tout utilisateur a n'accéder qu'à son répertoire avec une autre règle.
# ce qu'on veut c'est éviter l'utilisateur qui voudrait bypasser la première règle avec un http://www.monserveur.com/____data____/userX RewriteRule ^var/www/html/____data____/.*?/(.*) /var/www/html/____data____/%{ENV:AUTHENTICATE_uid}/$1 # et on voudrait ausst éviter que l'utilisateur puisse scanner la racine RewriteRule ^var/www/html/____data____/?$ /var/www/html/____data____/%{ENV:AUTHENTICATE_uid}/
Notez l'ajout de /var/www/html dans les chaines de remplacement, c'est pour éviter qu'apache pense qu'on a modifié le chemin si on n'a rien changé.
Et c'est gagné, on a enfin trouvé !
Je vous laisse donc profiter du résultat :
Edit : la version finale minimise l'appel aux règles, prend en compte les chemins qui se terminent par / et les tentatives d'accès à des répertoires non autorisés.
<Location /> AuthType basic AuthName "My server" AuthBasicProvider ldap AuthLDAPURL ldap://serveur.ldap.com/dc=domaine,dc=com?uid?sub AuthLDAPBindDN cn=user,ou=technical,dc=domaine,dc=com AuthLDAPBindPassword password Require valid-user # make http behave like ftp RewriteEngine On # create home dir var RewriteRule .* - [E=USER_ROOT:/var/www/html/____data____/%{ENV:AUTHENTICATE_homeDirectory}] RewriteCond %{ENV:USER_ROOT} !-d RewriteRule .* - [E=USER_ROOT:/var/www/html/forbidden] # redirection vers les repertpoires utilisateur RewriteCond %{REQUEST_FILENAME} !^/var/www/html/____data____ RewriteRule ^var/www/html/(.*) %{ENV:USER_ROOT}/$1 [L,DPI] # impossibilite de lire la racine RewriteCond %{REQUEST_FILENAME} ^/var/www/html/____data____/?$ RewriteRule .* %{ENV:USER_ROOT} [L,DPI] # impossibilite de lire le repertoire d'un autre RewriteCond %{ENV:AUTHENTICATE_homeDirectory}|%{REQUEST_FILENAME} !^(.*?)\|/var/www/html/____data____/\1 RewriteRule ^var/www/html/____data____/?[^/]*/?(.*) %{ENV:USER_ROOT}/$1 [L,DPI] </Location> <Directory /var/www/html/forbidden> deny from all </Directory>
Note : et pour ceux qui voudraient vraiment faire du FTP avec apache il y a mod_ftp.
Tags:apache, planet-libre, planete-libre, ServeurSi vous avez aimé, il y a aussi :
... désolé
Niveau :
Résumé : gdisk /dev/sda
Guid partition table est un format de partitionnement de disque.
Il ne faut pas confondre un format de partitionnement avec le formatage d'une partition avec système de fichier. Il y a de nombreux formats de système de fichier : ext4, swap, xfs ... Mais il n'existe que peu de format de partitionnement, les plus connus étant :
Ce format a pour but de palier les différents problèmes de son prédécesseur direct le MBR :
Attention, on stocke des adresses de secteur (LBA comme en MBR depuis un certain temps) et non d'octets, et la taille d'un secteur peut varier d'un disque à l'autre, il faut faire attention à ne pas copier les tables GPT trop littéralement.
GPT est indiqué comme nécessaire pour le support du boot sur EFI, bien qu'il soit théoriquement possible de faire sans.
Pour partitionner en GPT vous avez le choix entre deux familles d'outil :
Le moins dangereux est de ne partitionner que vos nouveaux disques en GPT, mais il y a moyen de refaire la table de partition d'anciens disques s'il y a suffisament de place pour stocker la table GPT (16kio en début et en fin de disque plus le MBR). Si l'espace est disponible, c'est simple, il vous suffit de reporter les adresses de début et de fin de chaque partition du MBR vers le GPT.
Tout d'abord je vous recommande d'aligner vos partition sur 1Mio, le minimum recommandé étant de 4kio. Le minimum de 4ko s'explique par le fait que de plus en plus de disques ont des secteurs de 4ko, et si vos écritures ne sont pas alignées sur 4kio vous allez voir vos performances dégringoler.
Il faut ajouter que de plus en plus de disques sont des SSD. Les SSD ont des pages sur lesquelles il est aussi intéressant de se caler et elles peuvent aller jusqu'à 1Mio.
Donc ne vous posez plus la question et prenez la valeur par défaut de l'outil qui aligne sur le Mio.
Dans la notion de MBR (un unique secteur de 512 octets) il faut différencier le code et la table des partitions.
Si vous utilisez un BIOS classique, le code du MBR restera le même (grub/lilo/boot windows ...).
Si vous utilisez EFI, le code du MBR peut être vide (ce que fait en général gdisk), mais il peut être intéressant de mettre un code fonctionnel avec un avertissement.
La table des partitions du MBR doit elle être protégée pour éviter à un outil d'édition de cette table de tenter d'y faire des modifications et d'effacer vos précieuses données. C'est pour cela qu'on y inscrit un "protective MBR" qui indique que le disque est entièrement utilisé par une partition unique de type GPT.
Tags:Disque, planet-libre, planete-libre, SystèmeSi vous avez aimé, il y a aussi :
Republié par http://lesjoiesdusysadmin.tumblr.co...
Aucun tag pour cet article.Niveau :
Résumé : stats
Howdy ho !
Tout le monde sait à peu près qu'il y a moyen de stocker plus de fichiers et des fichiers plus gros que dans ext3. Bon c'est gentil, mais quand on ne s'appelle pas google ou la NSA, stocker des fichiers de plus de 2To n'est pas vraiment notre priorité.
De plus l'usage des extents, qui permet ce genre de choses, a l'avantage de réduire la fragmentation. Bien.
Passons à des choses plus sympathiques, savez-vous que ext4 peut stocker la liste des blocs inutilisés ? Ça n'a l'air de rien, mais du coup la durée de fsck n'est plus proportionnelle à la taille du volume, mais à la quantité de données stockées ! Enfin une bonne nouvelle.
Ext4 supporte la méthode discard, c'est à dire l'indication au block device que certains blocs ne sont plus utilisés. Cette fonctionnalité est indispensable pour conserver les performances des SSD sur le long terme.
Parlons des dates maintenant. Le format de stockage des dates a changé, ce qui veut dire deux choses : on est maintenant Y2038 safe et on peut maintenant stocker des dates précises à la nanoseconde.
De plus il est possible de stocker une date supplémentaire : la date de création (crtime). Cette information était un gros manque pour les habitués du système de Microsoft. En effet, il est trop facile et fréquent de toucher aux fichiers et par là même mettre à jour les dates du fichier. La date de création elle est immuable et permet de savoir quand est apparu un fichier.
Ceux-ci dépendent d'une nouvelle fonctionnalité d'ext4 : les inodes de 256 octets. On ne peut donc avoir les timestamps à la nanoseconde et la date de création que sur des systèmes de fichiers fraîchement créés et pas sur des systèmes upgradés depuis ext3 s'ils avaient été créés avec la taille par défaut.
Pour pouvoir les stocker, il faut passer l'option -I 256 à la création du système de fichier.
$ mkfs.ext4 -I 256 /dev/sdXY
Et pour les utiliser ?
Sachant qu'il s'agit de fonctionnalités d'un système de fichiers, il faut passer par le VFS pour les utiliser. Le problème c'est que le VFS n'avait pas prévu ce cas. Il y a donc de nombreuses modifications à faire avant de les voir arriver dans ls : modifier le VFS pour avoir une fonction permettant de récupérer ces données, modifier l'appel système stat, modifier la libc, modifier ls et ses amis pour qu'ils affichent l'information.
C'est trop bête, nous avons l'information sur le disque et nous n'y avons pas accès. Heureusement, si on est root, un disque ça se lit, il suffit juste de savoir où est l'info et d'aller la chercher.
Je rappelle que les autres dates directement disponibles avec stat sont : atime (dernier accès), mtime (dernière modification du contenu) et ctime (dernière modification de métadonnées).
On récupère l'inode du fichier
$ stat -c%i fichier
On récupère la partition sur laquelle est stockée le fichier
$ df fichier | awk 'NR==1 {next} {print $1; exit}'
Et enfin on lit les infos directement sur le disque avec debugfs (il faut être root)
$ debugfs -R "stat <$inode>" /dev/sdaX
Ce qui agrégé en une ligne de commande donne pour le fichier $file :
$ file=/bin/ls; debugfs -R "stat <$(stat -c%i "$file")>" $(df "$file" | awk 'NR==1 {next} {print $1; exit}') | grep timeTags:Disque, Système
Si vous avez aimé, il y a aussi :
Niveau :
Résumé : hdparm -z /dev/used_device
Comment repartitionner un disque contenant une partition indispensable (par exemple /) sans rebooter ?
Si l'intégralité de votre disque est en LVM, cet article ne vous concerne pas puisque vous pouvez simplement redimensionner vos volumes LVM. Mais supposons que vous ayez au moins une "partition" que vous voulez redimensionner.
Posons une limite : il ne vous sera pas possible de toucher à une partition en cours d'utilisation et de prendre en compte cette modification sans rebooter ou la désactiver temporairement.
Une partition est dite utilisée si elle est montée ou activée en tant que swap, utilisée dans un MD lancé ou présente comme PV (physical volume) dans un VG (volume group) actif.
Maintenant nous avons un disque dont une partition au moins est utilisée, et une autre (celle qu'on veut redimensionner ou déplacer) ne l'est pas.
Modifions la table des partitions avec fdisk (cfdisk ou parted feront l'affaire). Attention, pour toute autre opération qu'une création ou un changement du secteur de fin (déplacement), fdisk ne suffira pas.
Lorsque vous quittez l'outil et que vous écrivez sur le disque, celui-ci tente de relire la table des partitions. Puisqu'une des partitions est en cours d'utilisation, il vous indique qu'il n'a pas pu le faire.
Si vous pouvez libérer la partition temporairement, alors il suffit d'utiliser la commande suivante pour que sa table des partitions soit relue :
$ hdparm -z /dev/sdX
Supposons que vous ne puissiez pas libérer la partition. La solution est simplement d'utiliser un loopback ! Pour cela, récupérez l'offset à utiliser depuis la table de partition :
$ fdisk -lu /dev/sda | grep sda2 > /dev/sda2 1026048 286515199 142744576 83 Linux
Ici l'offset de début est 1026048*512 et celui de fin 286515199*512. Il n'y a plus qu'à créer le loopback. Attention pour la taille la formule est "secteur de fin - secteur de début + 1" car ces secteurs sont inclus :
# unités : octet $ losetup -o $(($start*512)) --sizelimit $((($end-$start+1)*512)) -f --show /dev/sda # un message d'erreur apparait, mais il peut être ignoré
Et voilà, vous pouvez maintenant faire un resize2fs sur le device de loopback et/ou un mount directement !
PS :
On pourrait croire qu'on peut faire mieux avec device mapper et dmsetup. Mais en fait ce n'est pas possible car device mapper considère que le disque complet est en cours d'utilisation si une de ses partitions est utilisée.
Si vous avez aimé, il y a aussi :
Niveau :
Résumé : syslog | openssl dgst
Vous êtes vous déjà posé la question de la sécurisation de vos logs ? Sont-ils accessibles ? modifiables ? Peut-on détecter une falsification ?
Comment faire pour que les logs ne soient pas altérés par une personne de peu de principes ? Je vous propose une solution qui n'est pas une solution miracle, mais c'est une solution qui sera une brique de plus dans votre défense en profondeur.
Nous allons signer cryptographiquement les logs pour que tout altération devienne visible comme le nez au milieu de la figure.
Je vous au préparé pour cela deux programmes (lien en fin d'article), l'un pour signer les logs, l'autre pour les valider. Bien sûr, on ne va pas signer les fichiers de logs directement, ça laisserait tout le temps à un attaquant de les modifier avant la signature. Nous allons plutôt nous insérer dans le système syslog pour disposer des lignes au fur et à mesure. Mais nous n'allons pas non plus signer toutes les lignes, ce serait trop lourd. Nous allons plutôt signer des blocs de lignes, par exemple une signature toutes les 100 lignes, sans oublier un timeout pour éviter que 99 lignes restent en mémoire trop longtemps..
Enfin une des fonctionnalités importante de ces outil est le chaînage. Le chaînage est le fait d'utiliser la signature du bloc précédent comme faisant partie du bloc suivant. Ceci garanti qu'il ne peut y avoir suppression ou ajout d'un bloc eu milieu d'une chaîne de blocs. Et tant qu'on y est nous pouvons aussi chaîner les fichiers pour obtenir le même résultat au niveau fichier.
Au final toute modification, ajout ou suppression de ligne entraine l'invalidation de la signature. Toute modification, ajout ou suppression de bloc ou de fichier de log entraine l'invalidation de la signature.
Voici donc un exemple d'usage sous forme de pipe :
$ openssl genrsa -out key.pem 1024 # il nous fait une clé de signature $ echo "Log important" | signlogger -k key.pem -f logfile
Notez que c'est utilisable avec syslog puisque celui-ci vous permet d'utiliser un pipe à la place d'un fichier. Je ne détaille pas cela ici car cela dépend du sylog que vous utilisez (syslogd, syslog-ng, rsyslog ...).
Et pour vérifier que votre fichier de log n'a pas été modifié ?
$ openssl rsa -in key.pem -pubout > pubkey.pem # on récupère la version publique de la clé $ signvalidator -k pubkey.pem -f logfile
Si vous voulez utilisez cet outil avant logger ou avant l'envoi à un serveur centralisé, il faudra modifier signvalidator pour qu'il ignore les éléments ajoutés par syslog dans la vérification de la signature (date, pid, ...).
Dans la vraie vie quand on parle de sécurité, il faut se demander de quoi on veut se prémunir.
Signer les logs a pour but d'éviter qu'on puisse modifier les logs a posteriori, puisqu'on n'empêche personne de transformer les logs avant qu'ils ne soient envoyés à syslog. Mais toute personne qui a accès en écriture aux logs a posteriori, a les mêmes droits que le processus qui écrit les logs. Il a donc accès au système de signature.
Mais alors qu'a-t-on gagné ?
Tout d'abord, un difficulté légèrement accrue pour un attaquant, c'est pas grand chose, mais ça peut toujours servir. Ensuite, il nous suffit maintenant de séparer les droits du système de chiffrement de ceux du système d'écriture pour enfin détecter la modification par une personne possédant les droits d'écriture.
Pour cela vous avez plusieurs moyens à votre disposition :
Ou toute combinaison de ceux-ci.
Vous remarquerez que ces techniques ont déjà pour but d'empêcher la modification des logs a posteriori. La signature n'apporte qu'une preuve supplémentaire.
Mais prenez l'exemple du serveur syslog centralisé. On ne peut plus modifier les logs depuis le client, mais on le peut toujours depuis le serveur. La signature, si elle est effectuée côté client permet d'apporter une garantie supplémentaire puisqu'il faut cette fois un accès coté client ET côté serveur pour effecture la modification.
Si on y ajoute l'append only, il faut être root, si on y ajoute le HSM, il faut disposer d'une carte à puce ou d'un mot de passe, si on y ajoute un media read only, il faut disposer d'un accès physique pour le modifier. Et chacun de ces éléments peut être géré par une personne différente pour rendre impossible toute modification par une unique personne malintentionnée.
A vous de choisir votre niveau de sécurité !
Je vous colle ici l'usage complet des commandes (c'est du perl pour ceux qui veulent savoir)
$ signlogger --help Usage: signlogger [options] Options --key|-k keyfile Use private key for signing (PEM encoded) --file|-f file Log to file instead of stdout --lastsig|-l line Use line as last signature (used for chaining) --initfile|-i file Use last line of file as last signature (used for chaining) --blocksize|-b lines Insert signature each "lines" count (default 50) --timestamp|-t seconds Insert signature each "seconds" seconds (default 30mn) --help|-h This help $ signvalidator --help Usage: signvalidator [options] Options --key|-k keyfile Use public key for validation (PEM encoded) --file|-f file Read file instead of stdin --lastsig|-l line Use line as last signature (used for chaining) --initfile|-i file Use last line of file as last signature (used for chaining) --help|-h This help
Et pour les télécharger :
Si vous avez aimé, il y a aussi :
Niveau :
Résumé : trap DEBUG ; PROMPT_COMMAND
Voici comment loguer l'activité d'un utilisateur.
Mais tout d'abord, commençons par apprendre comment envoyer une ligne dans syslog. C'est simple, il suffit d'appeler logger avec les options qui vous intéressent (toutes optionnelles) et un message :
$ logger -i -p local5.info -t bash "$(tty): Bonjour syslog"
On enregistre le pid (option -i) pour permettre la corrélation avec d'autres lignes de logs.
On utilise la facility local5 qui est une sorte de tag utilisé par syslog pour savoir dans quelle catégorie mettre les logs. Les facilities servent essentiellement à faire des règles de tri des logs (par exemple il y a une facility authpriv pour tout ce qui est authentification). Il y a 8 facilities disponible pour les administrateur qui voudraient utiliser des valeurs qui ne sont pas standard. J'ai choisi local5.
On utilise le niveau de log info qui est quelque chose de standard parmi les systèmes de logs en général et permet de filtrer facilement.
On en profite pour loguer le tty en cours pour permettre une corrélation avec la commande last (on ne sait jamais).
Nous avons aussi besoin de la commande capable de nous donner la dernière commande tapée :
# lister la dernière commande sans son numéro $ fc -ln -1
Il n'y a plus qu'à mettre l'une de ces lignes dans le fichier /etc/profile qui est lu par bash au lancement de sessions interactives :
# envoyer la commande dans syslog pour chaque commande AVANT exécution $ trap 'logger -i -p local5.info -t bash "$USER $(tty): $(fc -ln -1)"' DEBUG # envoyer la commande dans syslog pour chaque commande APRES exécution $ PROMPT_COMMAND='logger -i -p local5.info -t bash "$USER $(tty): $(history 1)"' # fc ne marche pas correctement dans PROMPT_COMMAND
Enregistrer cette info peut être utile puisque les logs ne sont pas modifiables par un utilisateur simple. Et si vous avez un serveur syslog centralisé, ils ne le sont même pas par root depuis la machine d'origine.
Mais ceci ne doit pas vous faire oublier eux choses.
Tout d'abord le shell est un processus lancé par l'utilisateur, ce qui veut dire que l'enregistrement de cette information est nécessairement soumis à la bonne volonté de l'utilisateur. Un utilisateur peut supprimer le trap ou remplacer le PROMPT_COMMAND. Et supposons que vous trouviez un moyen pour l'en empêcher, l'utilisateur peut toujours tuer son propre shell, lui faire faire un exec vers un autre shell n'ayant pas de logs, tracer son shell pour modifier son activité etc.
Ensuite il faut être bien conscient de ce qu'on enregistre. On enregistre l'activité interactive d'un shell. Ceci exclue les transferts de fichiers (scp,...), les exécutions automatiques (cron, ...), les exécutions via un code (vi script; ./script). Et si on regarde bien ce dernier cas, on comprend qu'à moins de loguer tous les appels systèmes avec tous leurs paramètres, il est impossible de garantir qu'un utilisateur malveillant n'a pas exécuté une commande.
En conclusion ce système n'est pas là pour garantir l'enregistrement de toute activité d'un utilisateur plus ou moins malveillant, mais ça peut être une piste de recherche parmi d'autres lorsqu'un problème survient (qui a supprimé ma libc ?).
Tags:CommandeSi vous avez aimé, il y a aussi :