Analyse du concours IDS Bypass aux Positive Hack Days 9

Le forum international Positive Hack Days 2019 a accueilli le premier concours IDS Bypass. Les participants devaient examiner un segment de réseau de cinq nœuds, puis soit exploiter la vulnérabilité du service, soit remplir la condition spécifiée (par exemple, envoyer une réponse HTTP spécifique) et ainsi obtenir l'indicateur. Trouver un exploit était facile, mais IDS compliquait la tâche: le système se tenait entre les participants et les nœuds et vérifiait chaque paquet réseau. Les attaquants ont vu sur le tableau de bord si la signature bloquait leur connexion. Ci-dessous, je vais vous parler en détail des tâches elles-mêmes et analyser leur solution.



100.64.0.11 - Struts


Le premier nœud du nombre de ceux qui ont résolu la tâche était Struts. Après avoir analysé les ports Nmap, nous trouvons le service Apache Struts sur le port 8080.

# nmap -Pn -sV -p1-10000 100.64.0.11 631/tcp open ipp CUPS 2.1 8005/tcp open mxi? 8009/tcp open ajp13 Apache Jserv (Protocol v1.3) 8080/tcp open http Apache Tomcat/Coyote JSP engine 1.1 



La vulnérabilité d'Apache Struts a disparu en 2017: en utilisant l'injection OGNL, un attaquant pourrait exécuter n'importe quel code sur Struts sans autorisation. Il y a un exploit, par exemple, sur GitHub , mais IDS est intercepté:

[Drop] [**] [1:1001:1] Apache Struts2 OGNL inj in header (CVE-2017-5638) [**]

Le code de signature lui-même n'est pas disponible pour les participants, mais à partir du message dans les journaux, vous pouvez comprendre le mécanisme de son fonctionnement. Dans ce cas, la signature a détecté une injection OGNL dans HTTP:

 GET /showcase.action HTTP/1.1 Accept-Encoding: identity Host: 100.64.0.11:8080 Content-Type: %{(#_='multipart/form-data')... 

Si nous examinons le comportement d'IDS, il deviendra évident qu'il intercepte la combinaison% {au début de l'en-tête Content-Type. Il existe plusieurs solutions:

  1. Le participant @empty_jack a tenté de casser la combinaison de caractères% {avec son propre dictionnaire pour le fuzzing et est ainsi parvenu à une solution avec la ligne Content-Type:% $ {.
  2. Fuzz la requête HTTP elle-même. Le membre @ c00lhax0r a découvert que le caractère nul au début de l'en-tête contournerait également IDS: Content-Type: \ 0 $ {.
  3. La plupart des exploits pour CVE-2017-5638 font une injection avec un symbole de pourcentage. Mais certains chercheurs de cette vulnérabilité et des vulnérabilités précédentes d'Apache Struts écrivent que l'injection peut commencer à la fois par% et $. Ainsi, la combinaison de $ {contournera la signature IDS et exécutera le code sur le système. Une telle décision a été initialement conçue.

Cette tâche a été la plus simple, elle a été décidée par huit participants.

100.64.0.10 - Solr


Sur le port 8983 se trouvait le serveur Apache Solr, écrit en Java.

 $ nmap -Pn -sV -p1-10000 100.64.0.10 22/tcp open ssh (protocol 2.0) 8983/tcp open http Jetty 



Un exploit pour Apache Solr 5.3.0 est facile à trouver - CVE-2019-0192 . Un attaquant pourrait usurper l'adresse d'un serveur RMI dans une collection. Le fonctionnement nécessite le framework ysoserial, qui génère des chaînes d'objets Java (gadgets) et les délivre de différentes manières. Par exemple, à partir d'un serveur JRMP.

Bien sûr, en utilisant l'exploit de front dans le front, les participants verront les signatures IDS se déclencher:

[Drop] [**] [1:10002700:3001] ATTACK [PTsecurity] Java Object Deserialization RCE POP Chain (ysoserial Jdk7u21) [**]

Jdk7u21 n'est que l'une des trente charges, et leur choix dépend des bibliothèques utilisées dans le service vulnérable. La chaîne de gadgets Jdk7u21 utilise uniquement les classes standard de la version 7u21 du kit de développement Java, et la chaîne CommonsCollections1 contient des classes de la très répandue Apache Common Collections 3.1.

L'attaquant remplace l'adresse du serveur RMI dans la collection Solr par la sienne, puis démarre le serveur JRMP. Solr demande un objet à une adresse et reçoit un objet Java malveillant. Après sa désérialisation, le code est exécuté sur le serveur.

La signature se déclenche sur une séquence de classes dans un objet Java sérialisé. Il est transmis depuis la machine de l'attaquant et dans le trafic commence comme ceci:



La solution à ce problème était simple. La signature fait explicitement référence à Jdk7u21. Pour le contourner, vous avez dû essayer d'autres chaînes de gadgets. Par exemple, une des CommonsCollections. Il n'y avait aucune signature pour d'autres chaînes dans IDS. Le participant recevra un shell sur le système et lira le drapeau. Cinq participants ont terminé la tâche.

100.64.0.12 - SAMR


L'une des tâches les plus difficiles et intéressantes de la compétition. Il s'agit d'une machine Windows avec un 445ème port ouvert. L'indicateur est divisé en noms de deux utilisateurs du système, et pour terminer la tâche, il était nécessaire d'obtenir une liste de tous les utilisateurs sur le nœud Windows.

Bien sûr, MS17-010 et d'autres exploits n'ont pas fonctionné sur cette machine. Énumérer les utilisateurs pourrait, par exemple, les scripts de Nmap ou du framework impacket :

 $ python samrdump.py 100.64.0.12 Impacket v0.9.15 - Copyright 2002-2016 Core Security Technologies [*] Retrieving endpoint list from 100.64.0.12 [*] Trying protocol 445/SMB… Found domain(s): . SAMR . Builtin [*] Looking up users in domain SAMR [-] The NETBIOS connection with the remote host timed out. [*] No entries received. 

Les deux scénarios font des requêtes DCERPC à la machine sur le port 445. Mais tout n'est pas si simple: certains paquets sont bloqués par IDS, et cette fois deux signatures sont déclenchées:

[**] [1:2001:2] SAMR DCERPC Bind [**]
[Drop] [**] [1:2002:2] SAMR EnumDomainUsers Request [**]

Le premier détecte une connexion au service SAMR et marque uniquement la connexion TCP avec un indicateur. Et le second est déclenché par la demande EnumDomainUsers pour le service SAMR. Ce service a d'autres moyens d'obtenir des utilisateurs: QueryDisplayInfo, QueryDisplayInfo2, QueryDisplayInfo3. Tous ont également été bloqués par des signatures.

Le protocole DCERPC et les services Windows offrent d'énormes possibilités de gestion de site à distance. Ce protocole est utilisé par la plupart des outils bien connus, tels que PsExec ou BloodHound. Le service SAMR, c'est-à-dire SAM Remote Protocol, vous permet de travailler avec des comptes sur l'hôte, y compris la liste des utilisateurs.

Pour demander EnumDomainUsers Impacket, procédez comme suit:



Une connexion DCERPC au service SAMR est établie sur SMB, et toutes les autres demandes vont dans le contexte de ce service. Les signatures fonctionnent sur le premier et le dernier paquet de la capture d'écran.

J'ai donné deux indices sur la mission:

  • Vos tentatives font que IDS gĂ©nère 2 alertes. Regardez attentivement le premier.
  • Quelles commandes de connexion pour ce protocole connaissez-vous?

Il s'agit du protocole DCERPC et de la façon d'établir des connexions. Dans la liste des PDU disponibles, les commandes Bind et Alter Context sont responsables de la connexion et de la modification du contexte, et la seconde permet de modifier le contexte actuel sans interrompre la connexion.

Pour le résoudre, il a fallu réécrire la logique du script samrdump:

  1. Créez une liaison avec un autre service, par exemple avec l'UUID 3919286a-b10c-11d0-9ba8-00c04fd92ef5.
  2. Utilisez Alter Context pour basculer vers SAMR.
  3. Envoyez la demande Ă  EnumDomainUsers.

Les changements s'articulent sur trois lignes:

 < dce.bind(samr.MSRPC_UUID_SAMR) --- > dce.bind(uuid.uuidtup_to_bin(("3919286a-b10c-11d0-9ba8-00c04fd92ef5", "0.0"))) > dce.alter_ctx(samr.MSRPC_UUID_SAMR) > dce._ctx = 1 

Une solution alternative a été proposée par le lauréat du concours @ psih1337. La requête EnumDomainUsers a renvoyé une liste d'utilisateurs non pas par nom, mais par SID (ID de sécurité). SID n'est pas un nombre aléatoire. Par exemple, le compte LocalSystem a le SID S-1-5-18, et pour les utilisateurs créés manuellement, il commence à 1000.

Ainsi, en triant manuellement les graines de 1000 à 2000, il est très probable de trouver les comptes souhaités dans le système. Ils ont été trouvés sous les sids 1008 et 1009.

La solution à cette tâche nécessitait une compréhension du protocole DCERPC et une expérience dans la recherche d'infrastructures Windows. @ psih1337 était le seul à l'avoir décidé.

100.64.0.13 - DNSCAT


Sur le port 80, il y a une page Web avec un formulaire pour une adresse IP.



Si vous spécifiez votre IP, UDP arrive au port 53:

 17:40:45.501553 IP 100.64.0.13.38730 > 100.64.0.187: 61936+ CNAME? dnscat.d2bc039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173) 17:40:45.501639 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209 17:40:46.520457 IP 100.64.0.13.38730 > 100.64.0.187: 21842+ TXT? dnscat.7f4e039ce800000000d6eae8eae3bf81fd84d1695f5888aba8dcec06d071.a73b3f0561ca4906d268214f4b70da1bdb50f75739ae0577139096732bf8.0d0a987ce23408bac15426a22e. (173) 17:40:46.520546 IP 100.64.0.187 > 100.64.0.13: ICMP 100.64.0.187 udp port domain unreachable, length 209 


Il s'agit clairement de DNSCAT, un outil pour les tunnels DNS. Après avoir spécifié l'adresse IP dans le formulaire, un client DNSCAT essaie d'établir une connexion avec celle-ci. Si cela réussit, le serveur (c'est-à-dire le participant) recevra un shell sur la machine concurrente et retirera le drapeau.

Bien sûr, si nous élevons simplement le serveur DNSCAT et essayons d'accepter la connexion, nous échouerons:

[Drop] [**] [1:4001:1] 'dnscat' string found in DNS response [**]

La signature IDS est déclenchée sur la ligne dnscat dans le trafic de notre serveur - cela est clairement indiqué dans le message. Le trafic obscurci ou chiffré ne fonctionnera pas non plus.

En regardant le code client, nous constatons que les contrôles qu'il contient ne sont pas assez stricts. Autrement dit, la ligne dnscat peut ne pas apparaître du tout dans la réponse! Il ne reste plus qu'à le supprimer du code ou à le remplacer à la volée avec l'utilitaire NetSED. Le remplacement immédiat est beaucoup plus facile, mais je vais quand même donner un patch pour le code du serveur:

 diff -r dnscat2/server/libs/dnser.rb dnscat2_bypass/server/libs/dnser.rb < segments << unpack("a#{len}") > segments << [unpack("a#{len}")[0].upcase] < name.split(/\./).each do |segment| > name.upcase.split(/\./).each do |segment| diff -r dnscat2/server/tunnel_drivers/driver_dns.rb dnscat2_bypass/server/tunnel_drivers/driver_dns.rb < response = (response == "" ? "dnscat" : ("dnscat." + response)) > response = (response == "" ? "dnsCat" : ("dnsCat." + response)) 

Il y avait cinq solutions pour cette mission lors du concours.

100.64.0.14 - POST


Le drapeau de ce véhicule de concours n'a été reçu par personne.



Nous voyons un formulaire familier avec une adresse IP. Quelqu'un nous propose de participer au test d'un nouveau malware. Parmi ses innovations, le contournement d'IDS d'une manière inconnue. Pour l'indicateur, il vous suffit de lui envoyer l'en-tête HTTP «Server: ng1nx» en réponse. Ce sera chaud.

Comme prévu: nous recevons une demande GET sur notre IP et envoyons une réponse bloquée par IDS.

[Drop] [**] [1:5002:1] 'ng1nx' Server header found. Malware shall not pass [**]

Il y a un indice:

Parfois, les tâches qui semblent difficiles sont les plus simples. Si rien ne semble vulnérable, vous manquez peut-être quelque chose sous votre nez?

IDS est quelque chose de vulnérable juste devant notre nez. À partir de la page de réponse, vous pouvez constater que nous avons un ID Suricata ouvert.



Le premier lien sur la requête «Contournement IDS Suricata» mène à CVE-2018-6794 . Cette vulnérabilité permet de contourner l'inspection des paquets si le cours normal de la communication TCP (prise de contact TCP) est violé et les données sont envoyées avant la fin du processus. Cela ressemble à ceci:

 Client -> [SYN] [Seq=0 Ack=0] -> Evil Server # 1/2 Client <- [SYN, ACK] [Seq=0 Ack=1] <- Evil Server # 2/2 Client <- [PSH, ACK] [Seq=1 Ack=1] <- Evil Server # Data here Client <- [FIN, ACK] [Seq=83 Ack=1] <- Evil Server Client -> [ACK] [Seq=1 Ack=84] -> Evil Server # 3/2 Client -> [PSH, ACK] [Seq=1 Ack= 4] -> Evil Server 

Téléchargez l'exploit, changez la ligne en "ng1nx", désactivez les packages RST du noyau et exécutez.

Comme déjà mentionné, personne n'a reçu les drapeaux de cette machine, même si quelques participants étaient proches d'une solution.

Conclusion


49 participants se sont inscrits à la compétition, 12 ont passé au moins un drapeau. Il est intéressant de noter que les tâches compétitives peuvent avoir plusieurs solutions à la fois, en particulier les tâches avec le protocole SMB et DCERPC. Peut-être avez-vous vos propres idées pour accomplir certaines tâches?

Prix:

  • 1ère place: @ psih1337
  • 2ème place: @ webr0ck
  • 3e place: @empty_jack

Statistiques de réponse de signature:



Merci à tous les participants! L'année prochaine, il y aura encore plus de tâches de différents niveaux de difficulté.

Publié par Kirill Shipulin, Positive Technologies

Source: https://habr.com/ru/post/fr457932/


All Articles