# CQFD ## Énoncé Pas d'énoncé ¯_(ツ)_/¯ ## État de l'art Le fichier du challenge est une capture de traffic réseau. ```shell $ file capture.pcap capture.pcap: pcap capture file, microsecond ts (little-endian) - version 2.4 (Ethernet, capture length 262144) $ trid capture.pcap TrID/32 - File Identifier v2.24 - (C) 2003-16 By M.Pontello Definitions found: 10792 Analyzing... Collecting data from file: capture.pcap 100.0% (.PCAP/ACP) TCPDUMP's style capture (little-endian) (4000/1) ``` ![](https://i.imgur.com/xGDRKmX.png) ### Statistiques Wireshark nous indique les éléments suivants. - 84 packets **(Statistics > Conversations > Ethernet : Packets)** - 2 adresse ethernet différentes **(Statistics > Endpoints > Ethernet)** - 4 adresses IPv4 différentes **(Statistics > Endpoints > IPv4)** - Aucune adresse IPv6 **(Statistics > Endpoints > IPv6)** - 8 connections TCP différentes **(Statistics > Conversations > TCP)** - Aucune connection UDP **(Statistics > Conversations > TCP)** ### Contextualisation On peut facilement traiter manuellement cette quantité de données. Les communications sont toutes en HTTP ou TLSv1.2. Le challenge étant dans la catégorie `crypto`, il s'agit probablement de déchiffrer les flux TLS. 4 certificats sont dans la capture. Nous pouvons extraire chaque certificat en sélectionnant le paquet `Server Hello, Certificate, Server Hello Done`. Clic droit sur `SSL > TLS Certificate > Handshake > Certificates > Certificate` puis `Export packet bytes...`. ![](https://i.imgur.com/1TF6FIL.png) Nous pouvons également obtenir des informations sur ces certificats avec l'outil `ssldump`. ```shell $ ssldump -r capture.pcap New TCP connection #1: 172.30.24.1(56706) <-> 84-139-15-51.rev.cloud.scaleway.com(443) [...] server_name host_name: www.iluvprimes.com [...] New TCP connection #3: 172.30.24.1(39238) <-> 213.56.166.109(443) [...] server_name host_name: www.ssi.gouv.fr [...] New TCP connection #4: 172.30.24.1(58356) <-> 95-198-15-51.rev.cloud.scaleway.com(443) [...] server_name host_name: www.cryptoftw.fr [...] ``` On peut supposer que le second certificat est suffisamment solide et que ça n'est pas le sujet ici. Les `server_name` des deux autres sont déjà plus folkloriques. ### Certificats Soit `pub1.der` et `pub2.der` respectivement les certificats pour les server_name `www.iluvprimes.com` et `www.cryptoftw.fr`. ```shell $ openssl x509 -inform DER -in pub1.der -pubkey -noout > pub1.key $ openssl x509 -inform DER -in pub2.der -pubkey -noout > pub2.key $ openssl rsa -pubin -in pub1.key -text -noout RSA Public-Key: (2047 bit) Modulus: 65:e3:8a:08:e4:ed:c7:40:c8:cc:92:db:b0:9d:59: db:4a:c5:ba:2a:ca:75:c9:5f:17:e4:0b:df:48:44: 9f:b7:e0:d7:fb:35:36:51:96:f0:43:14:d9:ce:9f: a9:f9:d4:6b:a1:c7:f4:61:df:f9:e4:08:a4:95:f7: c9:70:ca:77:92:c7:26:4d:6c:ec:89:e3:b6:a2:ab: 86:a3:32:6f:fe:44:04:0e:b4:d8:70:f2:5c:d0:58: f4:29:c8:6b:da:1a:12:ed:fd:3c:dc:83:89:01:a2: 43:74:b1:46:8d:69:bd:6c:60:86:ff:13:89:4a:ab: dc:77:40:43:b9:90:b4:cd:16:6f:10:c0:e8:2e:a5: bd:d6:82:00:ab:91:e8:38:3c:53:e8:9f:e3:27:89: e7:00:85:14:af:82:18:d2:fc:46:1e:8e:4f:16:9c: 67:fd:1b:7f:d6:df:6a:00:a1:59:14:b4:8f:b3:e5: 79:29:7d:07:0a:f8:48:71:1c:de:95:5c:34:e6:f3: 4a:fa:60:97:98:95:90:8c:21:ac:b3:a1:2e:bf:68: ae:b1:68:2a:d1:23:d0:14:35:50:fc:60:59:bb:0d: 98:02:88:69:f8:64:bf:98:5a:be:c3:b9:fe:4d:8b: 2e:02:da:73:fc:63:12:2b:17:d5:f9:80:dd:c5:7d: f1 Exponent: 65537 (0x10001) $ openssl rsa -pubin -in pub2.key -text -noout RSA Public-Key: (2048 bit) Modulus: 00:8f:02:91:66:fd:f2:a6:b4:54:99:9a:f0:85:54: 80:01:8c:bd:3a:de:ea:ab:93:fe:af:6d:3c:07:fa: 1c:1c:d9:cb:ce:ef:31:28:b7:55:96:0d:34:80:48: fc:87:98:85:2a:5c:5b:e4:89:35:b6:ce:1a:63:9f: 19:f9:ab:31:5a:ef:4d:c8:1b:62:33:2a:6e:9a:d4: 5a:c8:20:e0:c0:50:8e:44:67:76:16:12:0a:5f:67: f2:b2:e5:5c:cf:6e:16:2a:5a:a4:37:4e:99:64:24: 58:2d:f7:74:27:4c:5e:5d:7f:e2:55:b1:65:84:bb: 81:00:84:fe:ae:14:a0:d3:9f:ed:7a:de:42:bd:9e: 55:ca:80:a2:b4:91:78:d8:b2:3a:f6:15:e4:3c:75: 86:b4:38:7f:8d:c6:17:51:7a:57:cb:be:67:42:29: f3:4b:35:45:c0:e5:4b:30:63:64:d6:a1:b5:82:55: de:92:c3:d8:47:fe:cd:ac:27:40:e8:5d:1c:db:fa: 3a:ac:3c:8b:73:4d:4a:40:53:f8:98:a9:11:40:bf: 9a:b6:01:ab:6f:de:2d:a0:93:9f:89:e3:79:8b:0b: 54:72:d0:9b:a6:8b:b6:7d:b7:74:5a:f2:20:c4:de: 4e:17:9c:df:85:80:9d:54:a1:51:6a:74:b4:5b:c2: f1:b3 Exponent: 65537 (0x10001) ``` On a ici deux clés publiques RSA-2048. À ce jour, personne n’a pu publiquement factoriser RSA-2048. Nous allons donc probablement devoir trouver un autre moyen d'attaquer le module de ces certificats. ## Attaque des clés publiques ### RsaCtfTool Sans rentrer dans détails techniques de chaque attaque, il en existe une multitude. Voyons si quelque chose marche. L'outil [RsaCtfTool](https://github.com/Ganapati/RsaCtfTool) est un très bon outil (de CTF surtout) pour attaquer des clés publiques. Le script va notamment : - Chercher les facteurs premiers du module dans des bases telles que factordb; - Tenter d'attaquer le module et voir si la factorisation est "faible"; - Tenter l'attaque Hastad (exposant public petit); - Et bien d'autres attaques (mersenne_primes, noveltyprimes, smallq, wiener, comfact_cn, primefac, fermat, siqs, Pollard_p_1,all). Malheureusement, `RsaCtfTool` ne donne rien. ```shell $ rsactftool --verbose --private --publickey pub1.key [*] Performing hastads attack. [*] Performing factordb attack. [*] Performing pastctfprimes attack. [*] Loaded 71 primes [*] Performing mersenne_primes attack. [*] Performing noveltyprimes attack. [*] Performing smallq attack. [*] Performing wiener attack. [*] Performing comfact_cn attack. [*] Performing primefac attack. [*] Performing fermat attack. [*] Performing siqs attack. [!] Warning: Modulus too large for SIQS attack module [*] Performing Pollard_p_1 attack. [-] Sorry, cracking failed $ rsactftool --verbose --private --publickey pub2.key [idem] ``` ### Attaque ROCA Quelques recherches sur les attaques possibeles sur une clé publique RSA-2048 m'amènent [ici](https://ctftime.org/writeup/8805). Il est question ici d'attaque ROCA. > Une implémentation de l’algorithme RSA au sein des puces Infineon est vulnérable à l’attaque dénommée ROCA (Return of Coppersmith’s Attack) qui touche la génération des clés par la librairie cryptographique. Toute clé privée RSA inférieure ou égale à 2048 bits et générée par les puces d’Infineon Technologies AG peut être retrouvée à partir de la clé publique correspondante. (cf. [cyberveille-sante.gouv.fr](https://www.cyberveille-sante.gouv.fr/cyberveille/264-vulnerabilite-critique-impactant-lalgorithme-de-generation-des-cles-rsa-roca-2017)) ```shell $ git clone https://gitlab.com/jix/neca $ sudo apt-get install cmake $ cd neca $ cmake . $ make $ python -c "print(int(\"$(openssl rsa -pubin -in ../pub1.key -modulus -noout | cut -d "=" -f2)\", 16))" 12862272562103424721436654564272304657609534482185665387600821410880521595524480937003540764964868094076026072506938788276319781278760050706594940055306345783111506068623090529020904720840323597550392798019777140032752947813309214536936857545104051608274551357465157572571547853159799500153864387715109447611346236295086674020094149039310293386230081483725119888010418464290176729751485892981968533726813150894269074250237445299088035980653939821337253721972102525176865299992319914895220563812837475572503917276817276445943174224296660112124422839613356296081387438965212164340903794474969142246462653812069150064113 $ ./neca $(python -c "print(int(\"$(openssl rsa -pubin -in ../pub1.key -modulus -noout | cut -d "=" -f2)\", 16))" | tr -d "\n") [...] Given key does not seem to be weak. $ ./neca $(python -c "print(int(\"$(openssl rsa -pubin -in ../pub2.key -modulus -noout | cut -d "=" -f2)\", 16))" | tr -d "\n") [...] Given key does not seem to be weak. ``` Raté... ### Attaque par facteur commun Quelques ~~(une quantité astronomique de)~~ recherches plus tard, je tombe sur [ce writeup](https://zonesec.org/fr-quals-grehack-2k18-network/). Une autre façon d'attaquer un couple de module est de chercher un facteur commun en tirant partie de la difficulté pour certains systèmes de générer des grands nombres aléatoires. ```shell $ git clone https://github.com/sagi/fastgcd $ cd fastgcd $ ./install.sh $ openssl rsa -pubin -in pub1.key -modulus -noout | cut -d "=" -f 2 > modules.moduli $ openssl rsa -pubin -in pub2.key -modulus -noout | cut -d "=" -f 2 >> modules.moduli $ ./fastgcd modules.moduli $ cat vulnerable_moduli [module1] [module2] $ cat gcds 91b19518125d563294f1aba371ebd06cb4a851dbdbe62e25767f0b7f80ef69627baab904c999af0c02df0ac36c254a6c7b82ebcce3d650862065f1022d7dedc1480399e16c98c56983b48c363d38c5d4a4dbf0719474f22eb356da2a1acca0810791da56b2bee7ce3a4f5f0f869e386a9a177aa4985479d7316c59c1c82fe35f 91b19518125d563294f1aba371ebd06cb4a851dbdbe62e25767f0b7f80ef69627baab904c999af0c02df0ac36c254a6c7b82ebcce3d650862065f1022d7dedc1480399e16c98c56983b48c363d38c5d4a4dbf0719474f22eb356da2a1acca0810791da56b2bee7ce3a4f5f0f869e386a9a177aa4985479d7316c59c1c82fe35f ``` Bingo! On trouve un facteur premier commun pour les deux modules. On peut donc maintenant trouver le seul paramètre manquant pour générer des clés privées : le second facteur premier. ```shell $ python -c 'print(int("91b19518125d563294f1aba371ebd06cb4a851dbdbe62e25767f0b7f80ef69627baab904c999af0c02df0ac36c254a6c7b82ebcce3d650862065f1022d7dedc1480399e16c98c56983b48c363d38c5d4a4dbf0719474f22eb356da2a1acca0810791da56b2bee7ce3a4f5f0f869e386a9a177aa4985479d7316c59c1c82fe35f",16))' $ python >>> mod1 = 12862272562103424721436654564272304657609534482185665387600821410880521595524480937003540764964868094076026072506938788276319781278760050706594940055306345783111506068623090529020904720840323597550392798019777140032752947813309214536936857545104051608274551357465157572571547853159799500153864387715109447611346236295086674020094149039310293386230081483725119888010418464290176729751485892981968533726813150894269074250237445299088035980653939821337253721972102525176865299992319914895220563812837475572503917276817276445943174224296660112124422839613356296081387438965212164340903794474969142246462653812069150064113 >>> mod2 = 18053343927187441108441676210352812208841821342176375072626907832579120529616542004286898021310125324177396453091146242892059023480248994812385743745829080533443709021801626752988504702779717383968935903480999751947593336274820105521875042566841237938309494595847368546040134225853055300125071970318904115478019359346905077910568516541409230598529104099513308295900154736804341485288504384483587566258326282352342852431455293545691814140471361311559581606313563521176326293297059267560469065513610526391626949122116277529307127764052525170569813954351374019777288115175379547188764678814330441682477499584967168160179 >>> p = 102309582252265727725340345451462353412917609251698470327358369038596447497782878994409403649899367357603426088862355403689989422161491768264328621320078645274330159165477896764608597302037237479418618729362585728029980211269117774589439387986392752717360615171973810177719407580656540183624752965381895742303 >>> q1 = mod1 / p >>> q2 = mod2 / p >>> print q1 125719138705784123981847760107353155221882767209282696996965365992026982759758663118724123157393002768533176626973097645949189824701082982581701050294390522480835951921853654312282010346776587123903192192907425920069889168729347508276355649273626333244122472994469367988621590243736589293453607998476471300271 >>> print q2 176457996697446541797078410681787975133044515403509374804191105369011520443365030282337656325217135953227384636548119123621186869405770201501319516665267152735988889608562764690464368640847985329674996378162898832997914646190946704515696039119406636883505009715464637237568076162984205812746062622257115842093 ``` ## Résolution ### Génération des clés privées Nous avons maintenant tous les paramètres nécessaires pour générer des clés privées. ```shell $ rsactftool -n 12862272562103424721436654564272304657609534482185665387600821410880521595524480937003540764964868094076026072506938788276319781278760050706594940055306345783111506068623090529020904720840323597550392798019777140032752947813309214536936857545104051608274551357465157572571547853159799500153864387715109447611346236295086674020094149039310293386230081483725119888010418464290176729751485892981968533726813150894269074250237445299088035980653939821337253721972102525176865299992319914895220563812837475572503917276817276445943174224296660112124422839613356296081387438965212164340903794474969142246462653812069150064113 -p 102309582252265727725340345451462353412917609251698470327358369038596447497782878994409403649899367357603426088862355403689989422161491768264328621320078645274330159165477896764608597302037237479418618729362585728029980211269117774589439387986392752717360615171973810177719407580656540183624752965381895742303 -q 125719138705784123981847760107353155221882767209282696996965365992026982759758663118724123157393002768533176626973097645949189824701082982581701050294390522480835951921853654312282010346776587123903192192907425920069889168729347508276355649273626333244122472994469367988621590243736589293453607998476471300271 -e 65537 --private > priv1.key $ rsactftool -n 18053343927187441108441676210352812208841821342176375072626907832579120529616542004286898021310125324177396453091146242892059023480248994812385743745829080533443709021801626752988504702779717383968935903480999751947593336274820105521875042566841237938309494595847368546040134225853055300125071970318904115478019359346905077910568516541409230598529104099513308295900154736804341485288504384483587566258326282352342852431455293545691814140471361311559581606313563521176326293297059267560469065513610526391626949122116277529307127764052525170569813954351374019777288115175379547188764678814330441682477499584967168160179 -p 102309582252265727725340345451462353412917609251698470327358369038596447497782878994409403649899367357603426088862355403689989422161491768264328621320078645274330159165477896764608597302037237479418618729362585728029980211269117774589439387986392752717360615171973810177719407580656540183624752965381895742303 -q 176457996697446541797078410681787975133044515403509374804191105369011520443365030282337656325217135953227384636548119123621186869405770201501319516665267152735988889608562764690464368640847985329674996378162898832997914646190946704515696039119406636883505009715464637237568076162984205812746062622257115842093 -e 65537 --private > priv2.key ``` ### Déchiffrement des flux TLS Pour déchiffrer les flux TLS, il faut importer les clés privées dans les préférences de Wireshark **(Edit > Preferences > Protocols > SSL > RSA keys list)**. ![](https://i.imgur.com/f3lF4t9.png) Dans les versions les plus récentes de Wireshark il n'est normalement pas nécessaires de renseigner d'autres informations que le chemin des clés. ![](https://i.imgur.com/XbWNA8f.png) Certaines communications sont déchiffrées. On peut renseigner le filtre `http.response.code == 200` pour retrouver les 2 parties du flag (paquets 11 et 79). Le flag est **ECSC{77ee6f654aaec8d8a01f0a3e053315120252d484}**.