==Phrack Inc.== Volume 0x0b, Édition 0x3e, Article n°0x03 sur 0x10 |=-----------------------------------------------------------------------=| |=---------------------=[ L I N E N O I S E ]=---------------------------=| |=-----------------------------------------------------------------------=| 1 - Erreurs dans la RFC à propos d'attaque de spoofing DNS 2 - L'injection de signaux par Shaun 3 - Pirater une station radio |=--------=[ L'impact de la RFC sur les attaque de spoofing DNS ]=--------=| par have2Banonymous --[ Sommaire 1 - Introduction 2 - Survol de la base du spoofing DNS 3 - Proposition de critère d'acceptation de réponses DNS 4 - Impact de la RFC sur les critère d'acceptation de réponses DNS 5 - Exemple d'attaque de spoofing DNS 6 - Impacts pratiques de la RFC sur les attaque de spoofing DNS 7 - Comparaisons d'implémentations 8 - Conclusion --[ 1 - Introduction Cet article fournit un bref survol des bases d'attaque de spoofing DNS[1] (Domain Name System - système de nom de domaines en français) contre les clients DNS. Des challenge techniques sont proposés pour nous aider à la fois à identifier les tentatives d'attaques et éviter qu'elles réussissent. Les RFC correspondantes, utilisées par les programmeurs pour leur permettre de vérifier que leur code respecte les spécifications sont analysées. Cela résultera dans le constat que les RFC ne sont ni assez spécifiques ni bien armées pour aider à identifier et éviter les attaques de spoofing DNS contre les clients DNS. En outre, les RFC simplifient en fait ces attaques à un niveau qui n'a encore jamais été discuté en publique. Pour souligner les conséquences de suivre à la lettre les RFC, sans considérer toutes ses ramifications de sécurité, un example d'attaque de spoofing DNS contre un client DNS de Microsoft Windows XP est fourni. Ceci illustrera les manques de sérieux dans l'implémentation du résolveur DNS de Windows XP. Par exemple, Windows XP acceptera une réponse DNS comme valide sans faire de vérification compléte que la réponse DNS correspond bien à la requête DNS. Ceci permet à un attaquant de créer des réponses DNS malicieuses génériques qui ne doivent répondre qu'à quelques critères à valeur prévisibles pour être acceptée comme valides par l'utilisateur ciblé. Cet article discute des impacts pratiques des questions soulevées, comme la possibilité d'effectuer une attaque de spoofing DNS réussie et raisonablement indétectable contre une large base d'utilisateurs de Windows XP, sans que l'attaquant ait connaissance des requêtes DNS effectuées par ces utilisateurs. Enfin, une comparaison avec le résolveur DNS de la distribution Linux Debian est effectuée. --[ 2 - Survol de la base du spoofing DNS Quand un utilisateur tape le nom d'un site web www.unsiteweb.fr dans son navigateur, il effectue une requête DNS vers le serveur DNS de son fournisseur d'accès à Internet (FAI) pour résoudre le nom du site en adresse IP. Un attaquant pourrait essayer d'exploiter cette action en envoyant à l'utilisateur une réponse DNS contenant une adresse IP incorrecte, obligeant l'ordinateur de l'utilisateur à se connecter à un ordinateur du choix de l'attaquant au lieu du site web désiré. --[ 3 - Proposition de critère d'acceptation de réponses DNS La RFC 2535 (Domain Name System Security Extensions), autrement connue comme DNSSEC, discute de l'utilisation de signatures numériques cryptographiques pour authentifier les transactions DNS et aider à atténuer les attaques de spoofing. Cependant, l'adoption de cette technologie a été extrêmement lente. Par contre, même sans ce niveau de sécurité, une attaque de spoofing DNS pourrait être difficile à réaliser. Cette difficulté résulte des critères proposés suivants, que les réponses DNS doivent respecter pour être acceptées par l'ordinateur client. Critère de validité proposé pour les réponses DNS : 1) L'adresse IP source doit correspondre à l'adresse IP à laquelle la requête DNS a été envoyée. 2) L'adresse IP de destination doit correspondre à l'adresse IP à partir de laquelle la requête à été émise. 3) Le numéro de port source doit correspondre au numéro de port auquel la requête a été adressée. 4) Le numéro de port destination doit correspondre au numéro de port à partir duquel la requête à été émise. 5) Le checksum UDP doit être correctement calculé. Ceci demandera à l'attaquant de dépenser plus de temps et d'efforts par attaque, bien que certains outils de générations de paquets aient la possibilité de calculer cette valeur. 6) L'identifiant de transaction doit correspondre à celui utilisé dans la requête. 7) Le nom de domaine de la section "question" doit correspondre au nom de domaine de la section question de la requête. 8) Le nom de domaine de la section "réponse" doit correspondre au nom de domaine de la section "question" de la requête. 9) L'ordinateur demandant la résolution de nom doit recevoir la réponse DNS de l'attaquant avant la réponse DNS légitime. [NDT : La première réponse à arriver est considérée comme bonne par le client.] --[ 4 - Impact de la RFC sur les critère d'acceptation de réponses DNS D'après les RFC, il n'est pas nécessaire que tous ces critères soient respectés pour qu'une réponse DNS soit acceptée. Spécifiquement, les critères 1, 2, 3, 5, 7 et 8 ne sont pas obligatoires, alors que les critères 4, 6 et 9 le sont. Ce qui va suivre est une interpretation de l'avocat du diable des RFC et une discussion détaillée de leurs effets sur chaque critère. Critère n°1 (adresse IP source) n'est pas obligatoire d'après la RFC 791 (Internet Protocol) qui dit que "On adopte comme principe général qu'implémen- tation doit être stricte quant à ce qu'elle émet, et libérale par rapport à ce qu'elle reçoit. C'est à dire qu'elle doit faire attention à émettre des datagrammes conformes et correctement constitués, mais doit accepter tout datagramme qu'elle est en mesure d'interpréter (ex., exempt d'erreurs d'ordre technique et tant que sa signification reste déchiffrable)."[2] La RFC 1035 (Domain names - implementation and specification) dit que "Certains serveurs de noms envoient leur réponses à partir d'adresses différentes que celles utilisées pour recevoir les requêtes. Ce qui veut dire qu'un résolveur ne peut pas s'attendre à ce qu'une réponse lui parvienne à partir de l'adresse à laquelle il a envoyé sa requête". L'adresse IP source peut donc être fixée arbitrairement. On peut aussi ignorer, si on veut, le fait que l'attaquant puisse aussi mettre comme adresse IP source, celle du serveur DNS de l'utilisateur. C'est justement plus facile si l'utilisateur est un client d'un FAI via la téléphonie, puisque ces FAI ont toujours une gentille page : "Comment configurer votre connection internet" qui spécifie entre autre les adresses IP de leurs serveurs DNS. Critère n°2 (Adresse IP destination) n'est pas obligatoire d'après la RFC 1122 (Requirements for Internet Hosts -- Communication Layers) qui stipule que "Dans la pluspart des cas, un datagramme adressé en broadcast[3] ou à plusieurs destinations est traité comme s'il était adressé à l'adresse IP d'un des hôtes". Utiliser une adresse de broadcast en destination serait plus qu'utile pour attaquer des ordinateurs dans un LAN. En outre, une réponse DNS sera acceptée si elle est adressée à une adresse IP associée à n'importe quelle interface réseau. Critère n°3 (numéro de port source) n'est pas obligatoire d'après la RFC 768 (User Datagram Protocol) qui stipule que "le port source est un champ optionnel". Le port source peut donc avoir n'importe quelle valeur arbitraire comme 0 ou 12345. Puisque le port source d'une réponse DNS affecte l'analyse de paquets par des utilitaires comme Ethereal, une valeur de 137 est un choix original puisqu'il sera analysé d'après le protocol de service de nom de NetBIOS (NetBIOS Name Service - NBNS) qui est basé sur le DNS. Comme résultat, la réponse malicieuse pourra apparaître comme traffique NetBIOS, qui sera surement ignoré par l'administrateur systme ou un enquêteur puisque considéré comme bruit de fond typique NetBIOS. Critère n°4 (numéro de port destination) doit être respecté d'après la RFC 768 (User Datagram Protocol). Cependant, cette valeur pourra être prévisible en fonction du système d'exploitation de l'ordinateur client. Pendant les tests, Windows XP a toujours utilisé le port 1026 pour faire ses requêtes DNS, bien que cette valeur dépende du moment, lors du démarrage du PC, où le service DNS client a démarré. Critère n°5 (Checksum UDP) n'est pas obligatoire d'après la RFC 1122 (Requirements for Internet Hosts -- Communication Layers) qui dit que "le checksum UDP est optionnel ; une valeur de 0 est transmise dans le champ de checksum d'une en-tête UDP pour indiquer son absence". Critère n°6 (Identifiant de transaction) doit être respecté d'après la RFC 1035 (Domain names - implementation and specification) qui stipule que les identifiants de transactions sont utilisés "pour apparier les réponses aux requêtes". Cependant, cette valeur peut être prévisible en fonction du système d'exploitation de l'ordinateur ciblé. Pendant les tests, Windows XP n'a jamais choisi aléatoirement les 16 bits du numéro d'identification. Au lieu de cela, Windows XP a toujours utiliser un identifiant de 1 pour la première requête DNS après le boot du PC, et en incrémentant simplement pour les requêtes suivantes. Les numéros de transactions 1 et 2 sont utilisés par le système pour faire des requêtes DNS vers time.windows.com. Critère n°7 et n°8 ((domain name in question and answer section) ne sont pas obligatoires d'après la RFC 1035 (Domain names - implementation and specification) qui stipule que les identifiants de transactions sont utilisés "pour apparier les réponses aux requêtes" et recommande, comme deuxième étape "de vérifier que la section de question correspond à l'information actuellement demandée". Les recommandations des RFC ne sont pas obligatoires, et dans le cas d'une section réponse absente, en principe, l'implémentation doit accepter tout datagram qui apparait pouvoir être interpreté. Donc, une réponse DNS ne contenant qu'une réponse sous la forme d'une adresse IP peut être appariée à la requête DNS correpondante, basée sur l'identifiant de transaction, sans requérir une section de question ni en recourant à calculer les informations de nom de la section réponse. En outre, une section réponse n'est pas non plus nécessaire si une section d'autorité est fournie pour référer au client, un serveur DNS faisant autorité (ou un serveur DNS sous contrôle de l'attaquant). Critère n°9 (la réponse de l'attaquant doit arriver en premier) doit être respecté et reste le plus gros problème pour l'attaquant. Cette restriction est difficile à casser, à moins que le serveur DNS légitime soit mis hors d'état de fonctionner pour se prévenir de compétitions avec les réponses spoofées, ou alors qu'un grand nombre de réponses DNS spoofées soient émises vers l'utilisateur ciblé. En même temps, comme discuté précédement, les critères 1 à 8 ne sont pas obligatoires ou ont des valeur prévisibles. Il s'ensuit qu'un attaquant n'a besoin d'aucune information sur la requête DNS de la victime pour avoir une chance raisonnable de réussir son attaque en lui envoyant un petit nombre de réponses DNS génériques. En outre, il y a un voisinage viable à la nature restrictive de ce critère. Si l'attaquant n'a pas en vue une machine prévise, une approche par "spray and pray"[4] peut être utilisée. Cette approche nécessite d'envoyer un faible nombre (une vingtaine) de réponses DNS spoofées à un maximum d'ordinateur cible potentiels, au lieu d'essayer de compromettre une machine et ensuite, de passer à la suivante. Cette approche "spray and pray" ne compromettra pas toutes les victimes potentielles, et chaque paquet envoyé ne réussira pas sa mission, mais un nombre suffisant de réponses DNS malicieuses seront acceptée pour que l'exercice soit rentable. --[ 5 - Exemple d'attaque de spoofing DNS Une attaque de spoofing DNS utilisant les concepts discutés dans ce article a été effectuée contre un ordinateur sous Windows XP. L'ordinateur de test avait une installation par défaut de Windows XP suivie de l'application du SP1 [NDT : Servcice Pack 1]. Le firewall de windows (le Microsoft Internet Connection Firewall) fourni avec windows XP a été activé et configuré pour logger tous les paquets supprimés et les connections réussies. L'utilisateur du Windows XP a tapé le site web www.somewebsite.org dans Internet Explorer, générant une requête DNS envoyée de son ordinateur ( adresse IP : 192.168.1.1) vers son serveur DNS (adresse IP : 192.168.1.254). Une réponse DNS spoofée, déguisée en trafic NetBIOS a été envoyée à l'utilisateur à partir de la fausse et non-existante adresse IP 10.10.10.1, spécifiant que le nom qu'elle tentait de résoudre avait l'adresse IP 192.168.1.77. À l'adresse IP 192.168.1.77, se trouvait un serveur web sous le controle de l'attaquant. Internet Explorer s'est connecté à 192.168.1.77 et a demandé la page web. Ceci révèle que les concepteurs du résolveur DNS de Microsoft Windows XP ont interpreté aussi les RFC comme nous l'avons décrit plus haut, simplifiant énormément les attaques de spoofing DNS. Le paquet suivant, décodé par Ethereal version 0.10.3 illustre la réponse DNS malicieuse et montre comment Ethereal peut être perdu en décodant le paquet en tant que trafic NetBIOS : Frame 1 (102 bytes on wire, 102 bytes captured) Ethernet II, Src: 00:50:56:c0:00:01, Dst: 00:0c:29:04:7d:25 Internet Protocol, Src Addr: 10.10.10.1 (10.10.10.1), Dst Addr: 192.168.1.1 (192.168.1.1) User Datagram Protocol, Src Port: 137 (137), Dst Port: 1026 (1026) Source port: 137 (137) Destination port: 1026 (1026) Length: 68 Checksum: 0x0000 (none) NetBIOS Name Service Transaction ID: 0x0003 Flags: 0x8580 (Name query response, No error) Questions: 0 Answer RRs: 1 Authority RRs: 0 Additional RRs: 0 Answers WORKGROUP<1b>: type unknown, class inet Name: WORKGROUP<1b> Type: unknown Class: inet Time to live: 1 day Data length: 4 Data 0000 00 0c 29 04 7d 25 00 50 56 c0 00 01 08 00 45 00 ..).}%.PV.....E. 0010 00 58 bf 58 00 00 00 11 25 89 0a 0a 0a 01 c0 a8 .X.X....%....... 0020 01 01 00 89 04 02 00 44 00 00 00 03 85 80 00 00 .......D........ 0030 00 01 00 00 00 00 20 46 48 45 50 46 43 45 4c 45 ...... FHEPFCELE 0040 48 46 43 45 50 46 46 46 41 43 41 43 41 43 41 43 HFCEPFFFACACACAC 0050 41 43 41 43 41 42 4c 00 00 01 00 01 00 01 51 80 ACACABL.......Q. 0060 00 04 c0 a8 01 4d .....M Ce paquet à été crée en utilisant les paramètres suivants passé à l'utilitaire libre de création de paquets réseau : netwox 38 --ip4-src 10.10.10.1 --ip4-dst 192.168.1.1 --ip4-protocol 17 --ip4-data 008904020044000000038580000000010000000020464845504643454c45484 643455046464641434143414341434143414341424c0000010001000151800004c0a8014d Alternativement, les paramètres suivants peuvent être utilisés puisque netwox calcule lui-même le checksum UDP : netwox 39 --ip4-src 10.10.10.1 --ip4-dst 192.168.1.1 --udp-src 137 --udp-dst 1026 --udp-data 00038580000000010000000020464845504643454c45484 643455046464641434143414341434143414341424c0000010001000151800004c0a8014d La suite montre que la réponse DNS spoofée a été ajoutée au cache du résolveur DNS de l'utilisateur pour une période d'un jour, les prochaines résolutions du nom www.somewebsite.org aboutiront donc automatiquement vers le serveur sous notre controle. La durée de mise en cache peut être diminuée par l'attaquant pour que l'entrée ne soit pas mise en cache ou immédiatement retirée du cache pour supprimer les traces de l'attaque. C:\>ipconfig /displaydns Windows IP Configuration 1.0.0.127.in-addr.arpa ---------------------------------------- Record Name . . . . . : 1.0.0.127.in-addr.arpa. Record Type . . . . . : 12 Time To Live . . . . : 604393 Data Length . . . . . : 4 Section . . . . . . . : Answer PTR Record . . . . . : localhost www.somewebsite.org ---------------------------------------- Record Name . . . . . : FHEPFCELEHFCEPFFFACACACACACACABL Record Type . . . . . : 1 Time To Live . . . . : 86364 Data Length . . . . . : 4 Section . . . . . . . : Answer A (Host) Record . . . : 192.168.1.77 localhost ---------------------------------------- Record Name . . . . . : localhost Record Type . . . . . : 1 Time To Live . . . . : 604393 Data Length . . . . . : 4 Section . . . . . . . : Answer A (Host) Record . . . : 127.0.0.1 Le fichier de log suivant généré par Microsoft's Internet Connection Firewall revèle qu'il n'a fourni aucune protection contre cette attaque, bien qu'il ne soit pas conçu pour inspecter et correler le trafic DNS. Si le firewall n'avait pas été configuré pour garder trace des connections réussies, il ne serait resté aucune trace dans les logs. #Verson: 1.0 #Software: Microsoft Internet Connection Firewall #Time Format: Local #Fields: date time action protocol src-ip dst-ip src-port dst-port size tcpflags tcpsyn tcpack tcpwin icmptype icmpcode info 2004-05-10 20:34:56 OPEN UDP 192.168.1.1 192.168.1.254 1026 53 - - - - - - - - 2004-05-10 20:34:57 OPEN-INBOUND UDP 10.10.10.1 192.168.1.1 137 1026 - - - - - - - - 2004-05-10 20:34:57 OPEN TCP 192.168.1.1 192.168.1.77 3010 80 - - - - - - - - 2004-05-10 20:35:30 CLOSE TCP 192.168.1.1 192.168.1.77 3010 80 - - - - - - - - 2004-05-10 20:36:30 CLOSE UDP 192.168.1.1 192.168.1.254 1026 53 - - - - - - - - 2004-05-10 20:36:30 CLOSE UDP 10.10.10.1 192.168.1.1 137 1026 - - - - - - - - On peut y voir que quand le PC sous windows envoie un paquet UDP du port 1026 vers le port 53 du serveur DNS, le firewall autorise tout le traffic UDP vers le port 1026, sans se soucier de l'adresse IP source ni du port source du trafic entrant. Un tel trafic sera autorisé jusqu'à ce que le firewall décide de bloquer l'accès au port 1026, ce qui arrivera quand il n'y aura aucun trafic vers le port 1026 pendant un certain laps de temps. Ce laps de temps variait entre 61 et 120 secondes, car il est apparu que le firewall vérifie une fois par minute pour déterminer si l'accès au port doit être retiré ou pas du à plus de 60 secondes d'inactivité. En considérant qu'un utilisateur connecté à Internet fera typiquement une requête DNS par minute, et l'accès au port 1026 sera donc toujours autorisé. Un attaquant sur internet pourra donc envoyer au PC sous Windows XP, des réponses DNS spoofées sans se soucier qu'elles soient bloquées par le firewall. Un tel trafic ne génerera aucun log si le firewall est uniquement configuré pour logger les suppressions de paquets. Si le firewall loggait aussi les connexions réussies, comme dans l'exemple, ces entrées dans le fichier seront noyées sous des miliers d'autres lignes. Puisque le firewall de windows XP ne log que les connexions et pas le trafic, si l'adresse IP source était celle du serveur DNS du poste Windows, aucun log inhabituel ne sera créé lors d'une attaque de spoofing DNS. La commande netstat révéla aussi que le PC sous windows écoutait toujours sur le port UDP 1026, et comme résultat, les réponses DNS supplémentaires sont passées silencieusement et n'ont généré aucun message d'erreur dans les logs ni de paquet d'erreur ICMP (erreur de port non accessible). Ce comportement, et la réutilisation du même port source pour les requêtes DNS, a été attribué au service DNS client. --[ 6 - Impacts pratiques de la RFC sur les attaque de spoofing DNS L'attaquant n'a besoin d'aucune information à propos de la requête DNS de sa cible, comme l'adresse IP du serveur DNS, le port source de la requête initiale, ni même le nom qu'elle demande de résoudre en adresse IP. Il s'ensuit que l'attaquant n'a pas besoin d'avoir accès au lien de communication entre l'utilisateur et son serveur DNS. Windows XP SP1 apparie les réponses DNS à leur requête DNS en utilisant seulement l'identifiant de transaction et le port UDP, et ces deux valeurs sont très prévisibles. Puisque le nom qu'on tente de résoudre n'est pas comparé entre la requête et la réponse, l'attaquant n'a pas besoin de se tracasser du nom que l'utilisateur a vraiment demandé puisque ce nom de domaine n'est pas obligé d'apparaitre dans la réponse DNS. Comme résultat, un attaquant peut créer des réponses DNS malicieuses génériques qui vont réussir à corrompre le processus de résolution DNS de la cible, sans se soucier du nom de domaine que la cible voulait vraiment résoudre, ni même de la configuration réseau de la cible (comme l'adresse IP du serveur DNS). Un attaquant désirant compromettre le plus de machine possible en un minimum d'efforts et de temps pourrait envoyer une vingtaines de réponses DNS similaires à la réponse générique donnée dans l'exemple d'attaque contre windows XP de cet article, bien qu'il faille utiliser un identifiant de transaction entre 3 et 22. Pour être plus efficace, un attaquant pourrait envoyer plutôt une centaine de réponses DNS avec des numéros de ports destinations entre 1025 et 1029. L'attaquant utiliserait une approche "spray and pray" en envoyant ces réponses DNS à chaque adresse IP dans la plage d'adresses appartenant à un gros fournisseur d'accès à internet par téléphonie, et une fois fait, de recommencer. Un bon niveau de succès est garanti par ce genre de scénario d'attaque, considérant la masse de cibles potentielles attendant une réponse DNS, et considérant que Windows XP acceptera n'importe quoi ressemblant vaguement à une réponse DNS comme étant une réponse DNS valide. Les utilisateurs recevant les vingt réponses DNS de l'attaquant accepteront l'une d'entre elle comme valide, et rendant l'attaque victorieuse, si cet utilisateur : - utilise Windows XP avec son résolveur DNS implémenté avec les pieds (la plupart des clients des FAI par téléphonie sont dans ce cas). - s'est connecté récement à internet dans les 10-20 dernières minutes ou alors n'a pas fait plus de 20 requêtes DNS (une part raisonnable des clients de ces FAI est dans cette catégorie). - a fait récement une requête DNS et attend une réponse (une part raisonnable du grand nombre de cibles choisies parmis des clients des FAI par téléphonie est dans cette catégorie). L'utilisateur sous Windows XP ciblé par l'attaque ne pourra déceler l'attaque, surtout s'il se base sur le Microsoft Internet Connection Firewall pour le protéger. L'analyse des logs d'un firewall plus sophistiqué et l'inspection du trafic réseau ne rendra pas lisiblement la présence d'une attaque de spoofing DNS puisque l'adresse IP source ne sera pas celle du serveur DNS légitime. En outre, le numéro de port source et le contenu de la réponse DNS spoofée peut être forgé pour ressembler à un traffic réseau NetBIOS typique qui circule sur Internet. Enfin, la plage d'adresse IP d'un FAI en téléphonie concernera principalement des utilisateurs d'Internet "à la maison", qui ne sont pas familiarisés aux concepts de sécurité avancée du réseau. L'adresse IP dans la réponse DNS spoofée peut être celle d'un ordinateur sur Internet sous le contrôle de l'attaquant, sur lequel fonctionne des serveurs mandataires [NDT : c'est la traduction française pour "proxy"] pour les emails (SMTP et POP3) et le traffic HTTP. L'attaquant sera alors capable de récolter des informations sensibles comme les envois et réception d'emails mais encore des mots de passe de boites emails pour récupérer les mails plus tard. Les boites emails utilisant le web et les identifications à des sites webs non chiffrés seront aussi récoltées. L'attaquant peut aussi ajouter du contenu aux pages HTML avant de les retourner aux utilisateurs. Ces contenus pourraient contenir des bannières publicitaires pour générer de l'argent, ou un cadre caché avec un lien vers un fichier sur un site web tiers, causant une attaque de déni de service distribuée sur ce site web tiers. Plus sérieusement, l'attaquant pourrait améliorer le status de corruption des machines en ajoutant du contenu HTML qui exploite une des vulnérabilités publiquement connues d'Internet Explorer permettant d'exécuter du code arbitraire, mais pour laquelle, il n'y a pas de mise à jour disponible par le vendeur. Par exemple, la vulnérabilité détaillée sur le site web http://www.computerworld.com.au/index.php?id=117316298&eid=-255. L'approche par "spray and pray" est très utile pour créer un réseau de machines compromises semi-aléatoire sous le controle de l'attaquant, aussi connu sous le nom de botnet. Le relai du trafic HTTP/1.1 peut être fait en inspectant l'en-tête HOST pour déterminer quel site web l'utilisateur veut réellement visiter. Cependant, pour relayer plus facilement et sans aucune anicroche ce trafic, un attaquant pourrait décider de ne pas placer de section réponse dans la réponse DNS spoofée. À la place, l'attaquant pourrait envoyer des réponses DNS spoofées non-autoritaires en utilisant les sections autorité [Authority] et divers [Additionnal] pour référer le client vers un serveur DNS sous le contrôle de l'attaquant. Ceci permettrait à l'attaquant de savoir exactement quel domaine la victime est en train de demander, et en plus, ce genre de réponse DNS spoofée aura un effet plus long et plus large sur l'ordinateur de la victime. Un discussion des références DNS et des tests pour savoir si Windows XP peut le gérer est en dehors du champ de cet article. --[ 7 - Comparaisons d'implémentations Les développeurs du système d'exploitation Linux on révélé avoir eu une approche plus consciente des problèmes de sécurité des RFC. Le navigateur Mozilla, fonctionnant sur l'ordinateur sous debian des auteurs était très restrictif et demandait aux réponses DNS de respecter tous les neuf critères ci-dessus sauf pour le critère 5 ; où des valeurs de checksum UDP de zéro étaient acceptées. En fait, une valeur incorrecte de checksum était acceptée si le paquet provenait du réseau local, mais jamais s'il venait d'Internet. Une lecture du code source du noyau indiqua que pour les réseaux locaux, le checksum UDP était délibérément ignoré et une vérification hardware était faite à la place, pour des raisons de performance. Ceci est apparu être une fonctionnalité plutôt qu'un bogue, même si ça ne respecte pas la RFC 1122 (Requirements for Internet Hosts -- Communication Layers) qui stipule que "si un datagramme UDP est reçu avec un checksum différent de zéro et invalide, UDP DOIT jeter silencieusement ce datagramme". Durant les tests, l'ordinateur sous Linux a utilisé les numéro de ports 32768 et 32769 pour effectuer les requêtes DNS. L'identifiant de transaction était choisi aléatoirement, compliquant les attaque de spoofing DNS, bien que l'identifiant utilisé lors des retransmissions de requêtes non résolues ne soit pas aussi aléatoire. Le choix des identifiants de transaction apparu assez robuste pour aider à se défendre contre les attaques de spoofing DNS sur Internet, puisque l'identifiant initial était imprévisible, et que la première requête serait typiquement résolue, sans besoin de retransmission. Le firewall iptables sur les ordinateurs sous Linux était configuré pour n'accepter le traffic UDP qu'en provenance et à partir du port 53 du serveur DNS légitime. Quand une requête DNS était effectuée et qu'une réponse était reçue, iptables était incapable de bloquer les réponses surnuméraires (spoofées) puisqu'il n'est pas conçu pour inspecter le traffic DNS et autorise une réponse DNS entrante par requête DNS sortante. Cependant, puisque le port utilisé pour envoyer les requêtes était fermé une fois une réponse DNS valide reçue, des messages ICMP de port indisponibles (ICMP port unreachable) étaient générés pour chaque réponse DNS surnuméraires (spoofées). iptables était configuré pour bloquer et logguer le trafic ICMP sortant. Une lecture des logs révela des messages ICMP de port indisponibles destinés au serveur DNS légitime, ce sont une très bonne indication d'attaque de spoofing DNS. En plus de cet indice d'une attaque de spoofing DNS, puisque les réponses DNS doivent parvenir du port 53, l'analyse du traffic réseau à l'aide d'un dissecteur comme Ethereal révela du traffic ressemblant à du DNS, arrivant apparement du serveur DNS légitime. --[ 8 - Conclusion Les RFC simplifient les attaques de spoofing DNS contre les résolveurs DNS puisque l'attaquant n'a besoin d'aucune information comme l'adresse IP du serveur DNS de la victime ou du contenu de la requête DNS qu'elle a envoyé. Microsoft Windows XP est plus vulnérable aux attaques de spoofing DNS que Linux, ceci est du à une implémentation trop simpliste des RFCs. D'autres simplifications des attaques de spoofing DNS viennent de la façon d'apparier les requêtes et les réponses DNS de windows XP et ses valeurs prévisibles d'identification de transaction - comportement qui peut être changé sans violer les RFCs. Les traces d'attaque de spoofing DNS sont diminuées par la capacité de déguiser les réponses DNS comme du traffic NetBIOS, le manque de granularité dans la configuration et de l'inspection du traffic de certains firewalls, et l'erreur de Windows XP à ne pas générer d'erreur ICMP pour les réponses DNS surnuméraires. La RFC 791 (Internet Protocol) disant qu'un programme doit être stricte quant à ce qu'il émet, et libéral par rapport à ce qu'il reçoit" et "doit accepter tout datagram qu'il peut interpreter" a pu être acceptable en 1981, quand la RFC a été crée et que l'interropérabilité était plus importante que la sécurité. Cependant, Internet a changé des utilisateurs de confiance d'universités et du département américain à la défense, pour maintenant inclure des hackers et scammers, faisant de la sécurité une priorité. Peut-être est-il temps que les logiciels basé sur cette vielle perception d'internet changent aussi. La communauté d'Internet continue d'attendre pour une plus grande adoption de signatures digitales cryptographiques pour authentifier les transactions DNS, comme discuté dans la RFC 2535 (Domain Name System Security Extensions). À plus court terme, le sujet des attaques de spoofing DNS pourrait être minimisé par Microsoft en améliorant leur implémentation des DNS dans tous leurs systèmes d'exploitations affectés. Ces améliorations incluent l'utilisation d'un identifiant de transaction aléatoire, la vérification que le nom dans la réponse correspond à la requête DNS, et l'utilisation d'un numéro de port aléatoire pour les requêtes DNS. Ces améliorations rendraient les attaques de spoofing DNS plus difficile à effectuer contre les résolveurs DNS, et ne violeraient pas les RFC. NDT : [1] le spoofing, terme anglais traduisible en "tromperie" est utilisé pour regrouper les attaques où on tente de faire passer une chose pour une autre (qu'elle n'est pas). [2] extrait d'une version française de cette RFC disponible à http://abcdrfc.free.fr/rfc-vf/rfc791.html [10-01-2007]. [3] une adresse de broadcast est une adresse signifiant "tout le monde sur ce réseau". [4] Littéralement "asperger et prier". |=----------------------------------------------------------------------=| |=----------------------------------------------------------------------=| ################################################# # Injecter des signaux pour le fun ou le profit # ################################################# Par shaun2k2 --[ 1 - Introduction La programmation plus sécurisée est à la mode, éliminant plus de vecteurs d'exploitations générique des programme, comme les dépassement de pile [stack-based overflow], les dépassement du tas [heap-overflow] et les bugs de symlink. Malgré cela, quelques subtiles vulnérabilités sont souvent négligées pendant les audits de code, laissant ces applications "sécurisées" vulnérables aux attaques, mais d'une manière moins évidente. La conception sure des gestionnaires de signaux est souvent inconsidérée mais je pense que cette classe de trous de sécurité mérite autant d'attention que des classes plus génériques de bugs, comme les dépassement de buffer [buffer overflow]. Cet article tente de discuter des problèmes rencontrés lors de l'écriture des fonctions de gestion de signaux, de comment exploiter ces problèmes, et présente des idées pour éviter ces problèmes. Une connaissance pratique de la programmation en C et des systèmes d'exploitations similaire à Unix serait grandement bénéfique au lecteur, mais ce n'est certainement pas nécessaire. --[ 2 - Gestion des signaux : vue d'ensemble Pour comprendre ce que sont les gestionnaires de signaux, on doit d'abord apprendre ce que sont exactement ce qu'est un signal. En bref, les signaux sont délivrés aux processus pour alerter ces processus à propos d'"évenements" important le concernant. Par exemple, l'utilisateur d'une application peut envoyer un signal en utilisant les combinaisons de la touche "CTRL", comme CTRL+C - qui envoit un signal SIGINT au processus concerné. Il existe plein de signaux, mais les plus commun (ou plus utiles) sont les suivants : SIGINT, SIGHUP, SIGKILL, SIGABRT, SIGTERM et SIGPIPE. Bien qu'il en existe plein d'autres. Une liste des signaux disponibles, d'après le standart POSIX.1, peut être trouvée dans la page de manuel Unix : signal(7). Il vaut la peine de noter que les signaux SIGKILL et SIGSTOP ne peuvent pas être gérés, ignorés ou bloqués. Leur "action" ne peut pas être changée. "Que sont les gestionnaires de signaux ?" pourrait-on se demander. Une réponse simple est que ce sont de petites fonctions qui sont typiquement appellées quand un signal prédéfini, ou un ensemble de signaux, sont délivrés au processus auquel elles appartiennent, avant la fin de l'exécution du programme - après que le flux d'exécution aie été redirigé à la fonction de gestion du signal, toutes les instructions dans ce gestionnaire sont exécutées à leur tour. Dans de plus grosses applications, des fonctions de gestion de signaux sont souvent écrites pour effectuer un ensemble de taches plus complexes pour garantir une terminaison propre du programme, comme la libération de fichiers temporaires, la libération de buffer en mémoire, l'ajout de messages de logs, et la libération de descripteurs de fichiers ou de sockets. Les gestionnaires de signaux sont souvent déclarées comme des fonctions ordinaires du programme, et ensuite déclarées comme gestionnaire par défaut pour un certain signal, généralement proche du début du programme. Considérons le programme d'exemple suivant : --- sigint.c --- #include #include void sighndlr() { printf("Ctrl-C caught!\n"); exit(0); } int main() { signal(SIGINT, sighndlr); while(1) sleep(1); /* should never reach here */ return(0); } --- EOF --- "sigint.c" spécifie que la fonction "sighndlr" devrait recevoir le flot d'exécution quand un signal SIGINT est reçu par le programme. Le programme s'endors "pour toujours", ou jusqu'à ce qu'un signal SIGINT soit reçu - dans ce cas, un message "Ctrl-C caught!" est écrit dans le terminal - comme montré ci-après : --- output --- [root@localhost shaun]# gcc test.c -o test [root@localhost shaun]# ./test [... program sleeps ...] Ctrl-C caught! [root@localhost shaun]# --- EOF --- En général, un signal SIGINT est délivré quand l'utilisateur tappe la combinaison CTRL-C au clavier, mais un signal SIGINT peut être généré par la commande kill(1). Que le gestionnaire de signaux soit simple ou complexe, il y a quelques pièges potentiels qui doivent être éviter pendant la conception des gestionnaires de signaux. Bien qu'un gestionnaire de signaux aie l'air sûr, des problèmes peuveut quand même arriver, mais seront moins évidents pour des yeux crédules. Il y a deux classes de problèmes quand on travaille sur le développement du gestionnaire designaux - les modifications non-atomiques des processus, et le code non-réentrant, dont les deux sont potentiellements critiques pour la sécurité du système. --[ 3 - Modifications non-atomiques Puisque les signaux peuvent être délivré presqu'à n'importe quel moment, et que les provilèges ont souvent besoin d'être maintenus (i.e. les privilèges root dans une applications SUID root) pour des raisons évidentes (i.e pour acceder à une socket matérielle, aux ressources graphiques, etc), les fonctions de gestion des signaux doivent être écrites avec des précautions supplémentaires. Si ce n'est pas le cas, et que des privilèges spéciaux sont détenus par le processus au moment où le signal est délivré, les choses peuvent aller mal assez vite. Ce qu'on veut dire par "non-atomique" est que le changement dans le programme n'est pas permanent - il sera en place temporairement. Pour illustrer cela, nous allons discuter d'un exemple de programme vulnérable. Considérons le programme d'exemple suivant : --- atomicvuln.c --- #include #include void sighndlr() { printf("Ctrl-C caught!\n"); printf("UID: %d\n", getuid()); /* other cleanup code... */ } int showuid() { printf("UID: %d\n", getuid()); return(0); } int main() { int origuid = getuid(); signal(SIGINT, sighndlr); setuid(0); sleep(5); setuid(origuid); showuid(); return(0); } --- EOF --- Le programme ci-dessus devrait immédiatement éveiller la paranoïa de tout programmeur fada de sécurité, mais l'insécurité n'apparait pas immédiatement évidente à tout le monde. Comme nous pouvons le voir d'après ce qui précède, un gestionnaire de signal est déclaré pour "SIGINT", et le programme se donne lui-même les droits root (pour ainsi dire). Après une pause de plus ou moins 5 secondes, les privilèges sont révoqués et le programme termine avec succès. Cependant, si un signal SIGINT est reçu, l'exécution est dirigée vers le gestionnaire de signal "sighdlr()". Regardons maintenant un exemple de trace : --- output --- [root@localhost shaun]# gcc test.c -o test [root@localhost shaun]# chmod +s test [root@localhost shaun]# exit exit [shaun@localhost shaun]$ ./test [... program sleeps 5 seconds ...] UID: 502 [shaun@localhost shaun]$ ./test [... CTRL-C is typed ...] Ctrl-C caught! UID: 0 UID: 502 [shaun@localhost shaun]$ --- EOF --- Si vous n'avez pas encore trouvé l'insécurité dans "atomicvuln.c", la trace ci-dessus devrait rendre les choses plus évidentes ; puisque la fonction de gestion de signal, "sighdlr()", a été pendant que le programme possédait encore les droits root l'amicale fonction printf() nous a gentillement dit que nos privilèges étaient ceux de root (en admettant que le programme soit en SUID root). Et pour prouver notre théorie, si nous laissons simplement le programme dormir 5 secondes sans lui envoyer d'interruption, la fonction printf() nous dit gentillement que notre UID est 502 - mon UID réel - comme vu précédement. Avec ceci, il est facile de comprendre où le bas blesse ; si un programme peut être interrompu entre le moment où les droits super-utilisateur sont acquis et celui où ils sont rendus, le code de gestion du signal "sera" exécuté avec les privilèges root. Imaginez seulement - si le gestionnaire de signal contenait du code potentiellement sensible, une corruption des droits root aurait pu avoir lieu. Bien que le programme d'exemple ci-dessus ne montre pas un exemple d'escalade de privilèges, il démontre au moins comment une modification non-atomique peut présenter un problème de sécurité si le gestionnaire de signal est invoqué. Et n'allez pas croire que des codes similaires à celui en exemple ne se trouve pas dans des applications critique de sécurité populaires et à large utilisation, ça l'est. Pour un exemple de code vulnérable similaire à celui ci-dessus qui est une application à large utilisation, voyez [1] dans la bibliographie. --[ 4 - Code non-réentrant Bien qu'il ne soit pas évident (et ça ne l'est pas), quelques fonctions de la glibc n'ont pas été écrite pour être réentrées à cause d'un signal, causant donc des problèmes potentiels aux gestionnaires de signaux les utilisant. Un exemple d'une telle fonction est la fonction "free()". D'après la page de manuel de free() : "free() libère l'espace mémoire pointé par ptr, qui a été obtenu lors d'un appel antérieur à malloc(), calloc() ou realloc(). Si le pointeur ptr n'a pas été obtenu par l'un de ces appels, ou si il a déjà été libéré avec free(), le comportement est indéterminé. Si ptr est NULL, aucune tentative de libération n'a lieu."[1] Comme l'extrait de page de manuel le clame, free() ne peut être utilisé que pour libérer de la mémoire qui a été allouée en utilisant malloc(), sinon, "le comportement est indéterminé". Plus spécifiquement, et dans un cas général, la pile est corrompue, si free() est appellée sur une zone mémoire qui a déjà été free()ée. À cause de ce problème de conception d'implémentation, les procédure de signal réentrant qui utilisent free() peuvent être attaquées. Considérons l'exemple suivant de programme vulnérable : --- reentry.c --- #include #include #include #include #include void *data1, *data2; char *logdata; void sighdlr() { printf("Entered sighdlr()...\n"); syslog(LOG_NOTICE,"%s\n", logdata); free(data2); free(data1); sleep(10); exit(0); } int main(int argc, char *argv[]) { logdata = argv[1]; data1 = strdup(argv[2]); data2 = malloc(340); signal(SIGHUP, sighdlr); signal(SIGTERM, sighdlr); sleep(10); /* should never reach here */ return(0); } --- EOF --- Le progamme ci-dessus défini un gestionnaire de signal qui libère la mémoire allouée dans le tas et s'endors pours 10 secondes. Cependant, une fois qu'on est entré dans le gestionnaire de signal, les signaux ne sont pas bloqués, et donc, peuvent être librement délivrés. Comme nous avons vu précédement, un deuxième appel à free() sur une zone mémoire déjà free()ée résultera dans un "comportement indéterminé" - une possible corruption du tas. Comme nous pouvons le voir, des données de l'utilisateurs sont prises et syslog() est aussi appellée dans le gestionnaire de signal - mais comment syslog() foncionne ? "syslog() crée un buffer mémoire pour faire un flux, en utilisant deux invoquations à malloc() - la première pour créer une structure de description de flux [NDT : "stream description structure"], pendant que l'autre crée un buffer pour y placer une copie des données du message de log. Cette base est utilisée pour maintenir une copie temporaire du message de syslog. Mais en quoi est-ce un problème dans le contexte de co-utilisation de procédure non-réentrantes ? Pour trouver la réponse, essayons d'expérimenter un petit peu, en essayant d'exploiter le progamme ci-dessus, qui apparaîtra être vulnérable. --- output --- [shaun@localhost shaun]$ ./test `perl -e 'print "a"x100'` `perl -e 'print "b"x410'` & sleep 1 ; killall -HUP test ; sleep 1 ; killall -TERM test [1] 2877 Entered sighdlr()... Entered sighdlr()... [1]+ Segmentation fault (core dumped) ./test `perl -e 'print "a"x100'` `perl -e 'print "b"x410'` [shaun@localhost shaun]$ gdb -c core.2877 GNU gdb 5.2.1-2mdk (Mandrake Linux) Copyright 2002 Free Software Foundation, Inc. GDB is free software, covered by the GNU General Public License, and you are welcome to change it and/or distribute copies of it under certain conditions. Type "show copying" to see the conditions. There is absolutely no warranty for GDB. Type "show warranty" for details. This GDB was configured as "i586-mandrake-linux-gnu". Core was generated by `./test aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'. Program terminated with signal 11, Segmentation fault. #0 0x4008e9bb in ?? () (gdb) info reg eax 0x61616161 1633771873 ecx 0x40138680 1075021440 edx 0x6965fa38 1768290872 ebx 0x4013c340 1075036992 esp 0xbfffeccc 0xbfffeccc ebp 0xbfffed0c 0xbfffed0c esi 0x80498d8 134519000 edi 0x61616160 1633771872 eip 0x4008e9bb 0x4008e9bb eflags 0x10206 66054 cs 0x23 35 ss 0x2b 43 ds 0x2b 43 es 0x2b 43 fs 0x2b 43 gs 0x2b 43 fctrl 0x0 0 fstat 0x0 0 ftag 0x0 0 fiseg 0x0 0 fioff 0x0 0 foseg 0x0 0 fooff 0x0 0 ---Type to continue, or q to quit--- fop 0x0 0 xmm0 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm1 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm2 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm3 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm4 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm5 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm6 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} xmm7 {f = {0x0, 0x0, 0x0, 0x0}} {f = {0, 0, 0, 0}} mxcsr 0x0 0 orig_eax 0xffffffff -1 (gdb) quit [shaun@localhost shaun]$ --- EOF --- Intéressant. Comme nous pouvons le voir, notre longue chaine de 'a' a trouvé sa voie dans certains registres sur la pile - EAX et EDI. À partir de ceci, nosu pouvons supposer être témoins du "comportement indéterminé" dont nous avons discuté plus tôt, quand le gestionnaire de signal est réentré. Quand l'exemple de programme vulnérable a reçu le deuxième signal (SIGTERM), puisque les signaux ne sont pas bloqués, le gestionnaire de signal est réentré pour pouvoir géré ce deuxième signal, impliquant que les choses aillent mal. Mais pouquoi c'est arrivé ? Puisque la deuxième zone mémoire a été libérée pendant la première exécution du gestionnaire de signaux, syslog a ré-utilisé cette zone de mémoire libre pour ses propres opérations - stocker son message de syslog, parce que comme la petite explication de syslog() l'a dit, deux appels à malloc sont présent dans la pluspart des implémentations de syslog, et donc, il a réutilisé la nouvelle zone mémoire libérée - *data2. Après l'utilisation de la zone mémoire anciennement *data2 par syslog, un deuxième free() est fait sur cette zone, parce qu'on réentre dans le gestionnaire de signal. Comme la page de manuel de free(3) nous l'a dit, un comportement indéterminé aura lieu si la zone mémoire a déjà été libérée, et nons avons vu que ça a été le cas. Donc, quand free() a été appellé une deuxième fois sur *data2, free() à atteri quelque part dans la zone contenant les 'a' (ici, 0x61 en hexa), parce que syslog a réutilisé cette zone libre pour stocker le message de syslog, temporairement. Comme la sortie de GDB ci-dessus l'illustre, puisque les données de l'utilisateur sont utilisées par "syslog()" (ça l'est dans notre cas), nous avons un certain controle sur les registres du programme, quand le "comportement indéterminé" à lieu (corruption du tas dans la pluspart des cas. Grace à cette possibilité, une exploitation est plus que possible - il est laissé en exercice au lecteur, le fait de jouer un peu plus avec cet exemple de programme vulnérable, et de déterminer si la vulnérabilité est exploitable. Pour les lecteurs intéressés, "free()" n'est pas la seule fonction de la glibc non-réentrante. En général, on peut assumer que toutes les fonctions de la Glibc qui NE SONT PAS inclues dans la liste suivante sont non-réentrantes, et donc, ne sont pas sûres si utilisées dans un gestionnaire de signaux. -- _exit(2), access(2), alarm(3), cfgetispeed(3), cfgetospeed(3), cfsetispeed(3), cfsetospeed(3), chdir(2), chmod(2), chown(2), close(2), creat(3), dup(2), dup2(2), execle(3), execve(2), fcntl(2), fork(2), fpathconf(2), fstat(2), fsync(2), getegid(2), geteuid(2), getgid(2), getgroups(2), getpgrp(2), getpid(2), getppid(2), getuid(2), kill(2), link(2), lseek(2), mkdir(2), mkfifo(2), open(2), pathconf(2), pause(3), pipe(2), raise(3), read(2), rename(2), rmdir(2), setgid(2), setpgid(2), setsid(2), setuid(2), sigaction(2), sigaddset(3), sigdelset(3), sigemptyset(3), sigfillset(3), sigismember(3), signal(3), sigpause(3), sigpending(2), sigprocmask(2), sigsuspend(2), sleep(3), stat(2), sysconf(3), tcdrain(3), tcflow(3), tcflush(3), tcgetattr(3), tcgetpgrp(3), tcsendbreak(3), tcsetattr(3), tcsetpgrp(3), time(3), times(3), umask(2), uname(3), unlink(2), utime(3), wait(2), waitpid(2), write(2)." -- --[ 5 - Gestion sûre des signaux En général, les vulnérabilités des gestionnaires de signaux peuvent être évitées par -- 1) N'utilisant que des fonctions de la glibc réentrantes dans les gestionaires de signaux - Ceci nous garde contre la possibilité de "comportement indéterminé" ou autre comme présenté dans l'exemple précédent. Cependant, ce n'est pas "toujours" faisable, spécialement quand le programmeur doit faire des choses comme libérer de la mémoire. D'autres contres mesures peuvent, dans ce cas, nous défendre contre ceci. Voyez plus bas. 2) Ignorer les signaux dans les procédures de gestion de signaux - Il est évident que cette pratique de progammation évitera la gestion des signaux pendant l'exécution de fonction de gestion de signaux, e tdonc, nous prémunira de réentrer dans le gestionnaire de signaux. Considérons l'exemple de code de gestionnaire de signal : --- sighdlr.c --- void sighdlr() { signal(SIGINT, SIG_IGN); signal(SIGABRT, SIG_IGN); signal(SIGHUP, SIG_IGN); /* ...ignore other signals ... */ /* cleanup code here */ exit(0); } --- EOF --- Comme nous pouvons le voir, les signaux sont bloqués avant de faire quoi que ce soit d'autre dans la fonction de gestion du signal. Ceci garantis d'éviter de réentrer dans le gestionnaire de signaux (ou presque). 3) Ignorer les signaux quand des modification non-atomiques du processus ont lieu - Ceci implique de bloquer les signaux, d'une manière similaire à l'exemple précédent, pendant l'exécution de code qui ont des modifications non-atomiques en place, comme l'exécution de code en mode super-utilisateur. Considérons l'extrait d'exemple de code suivant : --- nonatomicblock.c --- /* code exec with non-atomic process modifications starts here... */ signal(SIGINT, SIG_IGN); signal(SIGABRT, SIG_IGN); signal(SIGHUP, SIG_IGN); /* block other signals if desired... */ setuid(0); /* sensitive code here */ setuid(getuid()); /* sensitive code ends here */ signal(SIGINT, SIG_DFL); signal(SIGABRT, SIG_DFL); signal(SIGHUP, SIG_DFL); /* ...code here... */ --- EOF --- Avant d'exécuter du code privilégié, les signaux sont bloqués. Après l'exécution du code privilégié, les privilèges sont abandonnés et les actions par défaut de gestions de signaux retrouvent leur valeur par défaut. Il y a surement plus de façon de se prémunir de vulnérabilité des signaux, mais les trois ci-dessus devraient être assez pour implémenter des gestionnaires de signaux semi-sécurisés. --[ 6 - Conclusion J'espère que cet article a au moins touché du doigt les problèmes possibles rencontrés quand on travaille avec les signaux dans les applications en C. Si rien d'autre ne peut être retenu de cet article, mon but est d'avoir souligné que les pratiques de programmation sûres devrait toujours être appliquées lors d'implémentation de gestionnaires de signaux. Point final. Souvenez-vous en. Si j'ai oublié quelque chose, donné des informations imprécises, ou autre, s'il vous plait, permettez-vous de m'envoyer une ligne à l'email au début de l'article, à condition que vos commentaires soient gentillement écrits. Les écrits recommandés sont présentés dans la bibliographie suivante. --[ 7 - Bibliographie Les écrits recommandés sont les suivants : -- "Delivering Signals for Fun and Profit" - http://razor.bindview.com/publish/papers/signals.txt, Michal Zalewski. Michal's Cet article a été une ressource très utile pendant la rédaction de cet article, et quelques idées ont été récoltées à partir de lui. Merci Michal. "Introduction To Unix Signals Programming" - http://users.actcom.co.il/~choo/lupg/tutorials/signals/signals-programming.html,LUGPs. "Procmail insecure signal handling vulnerability" - http://xforce.iss.net/xforce/xfdb/6872 "Traceroute signal handling vulnerability" - http://lwn.net/2000/1012/a/traceroute.php3 "signal(2) man page" - http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=/usr/share/catman/man2/signal.2.html&srch=signal "signal(7) man page" - http://techpubs.sgi.com/library/tpl/cgi-bin/getdoc.cgi?coll=linux&db=man&fname=/usr/share/catman/man7/signal.7.html&srch=signal -- --[ 8 - Remerciements Remerciements à : -- Mes amis de HDC (ou les anciens membres de HDC), excluded.org, #hackcanada, tous @ GSO, rider (joyeux anniversaire en retard!). Tous les autres chouettes personnes que j'ai rencontré en ligne. -- Merci les gens. Merci pour votre temps. Shaun. NDT : [1] D'après la traduction de la page de man de free faite par Christophe Blaess (1997). |=----------------------------------------------------------------------=| |=----------------------------------------------------------------------=| |=--------------------=[ Pirater une station radio ]=-------------------=| Par j kuinga" Comme plein de stations radios font pour réduire les coûts, ils font ce qu'on appelle de l'"émission centralisée" [NDT : "central casting"]. C'est de cette manière que tout est produit à partir d'un batiment et géré par un groupe d'ingénieurs. Pourquoi est-ce important ? Vous pourriez interrompre l'émission du site central vers la tours, et créer votre propre programmation, sans le boulot d'acheter un transmetteur, récupérer une licence FCC, et ce genre de choses. Nous allons vous montrer deux façons différentes de vous amuser -- en interrompant l'émission et en doublant la station radio. Les stations radios ont typiquement des "Marti"'s, ce sont des mini-transmetteurs, et "Marti Repeater", typiquement dans la plage des 425-455MHz. Certains "Ham Transmitters" fonctinneront dans cette plage, sinon, allez voir votre vendeur d'électronique local. Les Marti's sont utilisés typiquement pour relayer les rencontres de Foot et de basket des lycées, ou encore les événements commerciaux "vivants" et c'est aussi facile que suplanter le signal, pour avoir votre message envoyé. Soyez prévenus, il y a typiquement une personne vivante à l'autre bout du transmetteur. Il ne fera probablement pas attention à vous, parce qu'il est payé 5,50$ de l'heure, mais il a la capacité de vous emmerder. Comment trouver la fréquence ? Bien, vous pourriez toujours faire du SE avec les ingénieurs de la station et leur demander, cependant, la pluspart d'entre eux sont de vieux grognons, alors, vous n'obtiendrez pas grand chose. Je vous suggère une bonne copie de "Police Call", qui a BEAUCOUP de fréquences, pour des usages comme les stations radios. J'ai utilisé une installation fait-main pour découvrir des fréquences particulières. Avoir quelques outils essentiels comme un bonne antenne bidirectionnelle, un conteur de fréquences, et un transmetteur très précis, en même temps qu'une planche à pain et des composants essentiels sera un bon départ pour trouver ce que vous devez savoir. Je conduis aussi une grosse camionnette blanche, completé d'un "Mast and Bucket"[1], je peux donc placer mon antenne optimalement, à la bonne hauteur et à la bonne position, que j'ai récupéré à une vente au anchère de l'école pour à moitié rien (e.g., moins de 500 $, même avec une étagère de 18" dedans et un chouette générateur). La pluspart des stations radios qui font comme ça ont ce qu'ils appellent un "STL" (ou Studio to Transmitter Link). C'est typiquement dans la plage des 800-900MHz, et les mêmes idées générales sont applicables. Vous trouvez la direction générale vers laquelle l'antenne est pointée, ensuite, vous suplantez leur signal. Puisque (idéalement), vous vous trouverez à quelques kilomètres du transmetteur, pas 30 ou 50 kilomètres comme le point d'émission principal [NDT : the Central-Casting spot], vous suplanterez leur transmetteur et commencerez votre propre station pirate. Cependant, la pluspart des stations on une surveillance aérienne [NDT : "Air" monitor], qui leur permet d'éteindre le transmetteur distant en appuyant un boutton sur leur STL. Cependant, si vous êtes assez proche de lui, vous devrier garder le controle jusqu'à ce qu'un des ingénieurs de la station vienne pour arreter manuellement votre transmetteur. Si vous repérez une camionette noire avec des antennes et qu'ils ont l'air de faire du repérage, il y a des chances qu'ils soient l'un ou l'autre a) avec l'équipe d'audit de la compagnie locale du cable, ou b) en train d'en vouloir à votre cul. kuinga@hotmail.com NDT : [1] Il doit s'agir d'un chariot élévateur... [Traduit de l'anglais par TboWan pour arsouyes.org] |=[ EOF ]=---------------------------------------------------------------=|