Het SSH Protocol
Oriëntatie Richard Peters, augustus 2002
Index Het SSH Protocol............................................................................................. 1 Index................................................................................................................ 2 Inleiding ........................................................................................................... 4 Protocol versie ............................................................................................. 4 Localization .................................................................................................. 5 Algemene definities/concepten ........................................................................ 5 Pakket .......................................................................................................... 5 Datatypes ..................................................................................................... 5 Algoritme en protocol benamingen............................................................... 6 Genereren van random data ........................................................................ 6 De Transport layer ........................................................................................... 7 Concepten.................................................................................................... 7 EncryptionAlgorithm ................................................................................. 7 PublicKeyAlgorithm .................................................................................. 7 MACAlgorithm .......................................................................................... 7 CompressionAlgorithm ............................................................................. 7 KeyExchangeAlgorithm ............................................................................ 7 Host key.................................................................................................... 8 Algemeen ..................................................................................................... 8 Initialisatie................................................................................................. 8 Algoritme onderhandeling......................................................................... 8 Sleutel onderhandeling ............................................................................. 9 In gebruik nemen van sleutels .................................................................. 9 Details ........................................................................................................ 10 Initialisatie............................................................................................... 10 Binair protocol......................................................................................... 10 Algoritme onderhandeling....................................................................... 11 Sleutel onderhandeling ........................................................................... 13 In gebruik nemen van sleutels ................................................................ 14 De connectie is gereed ........................................................................... 14 Services aanvragen ................................................................................ 14 De verbinding verbreken......................................................................... 14 Negeer data............................................................................................ 15 Debug berichten ..................................................................................... 15 Onbekende pakketten ............................................................................ 15 Bericht nummers .................................................................................... 16 Algoritmes .................................................................................................. 16 Encryptie................................................................................................. 16 Integriteit................................................................................................. 17 Compressie ............................................................................................ 17 Key Exchange ........................................................................................ 17 Public Key Algoritmes............................................................................. 19 Het User Authentication protocol ................................................................... 21 Authenticatie methodes.............................................................................. 21 Methode: none ........................................................................................... 21 Methode: publickey .................................................................................... 21 Methode: password.................................................................................... 21 Methode: hostbased................................................................................... 21 2
De Connection layer ...................................................................................... 22 Kanalen ...................................................................................................... 22 Sessie..................................................................................................... 22 TCP/IP Forwarding ................................................................................. 22 X11 kanalen............................................................................................ 22 Problemen ..................................................................................................... 23 Een KeyExchangeAlgorithm dat een PublicKeyAlgorithm nodig heeft dat kan signen én encrypten ............................................................................ 23 Het gebruik van disconnection reason codes is niet gespecificeerd .......... 23 Algoritme onderhandeling is niet transparant ............................................. 24 Het coderen van een hash als mpint.......................................................... 24 C-stijl definities ........................................................................................... 24 Niet gebruiken van namelist ....................................................................... 25 Sommige algoritmes zijn ‘verplicht’ ............................................................ 25 Referenties................................................................................................. 26 Appendix A: Een voorbeeld ........................................................................... 28 Appendix B: RSSH ........................................................................................ 37
3
Inleiding Het SSH protocol is een protocol dat gebruikt wordt voor het maken van veilige connecties tussen twee computers (server/client). De veel gebruikte TCP/IP connecties vormen geen bescherming tegen afluisteren en het veranderen van data door de verkeerde personen. Ook is er bij een gewone TCP/IP connectie geen zekerheid over of degene aan de andere kant van de connectie wel echt degene is wie je denkt dat hij is. Het SSH protocol lost al deze problemen op. SSH is bedoeld om bovenop een betrouwbare (pakketten gaan niet verloren en komen in de juiste volgorde aan) verbinding te draaien, deze verbinding is in de praktijk TCP/IP. Op dit moment wordt SSH het meest voor remote shell access gebruikt, als Secure Shell, waar de naam SSH vandaan komt. Het is een vervanger voor de unix programmas rsh, rlogin, telnet, etc. Verder wordt het ook voor secure file transfer gebruikt, en als tunnel voor normale TCP/IP connecties, zodat programma’s die alleen over TCP/IP werken van SSH gebruik kunnen maken, waardoor die connecties dezelfde beveiliging krijgen als het SSH protocol. Het SSH protocol bestaat uit verschillende lagen: • De Transport layer: deze verzorgt 1) vertrouwelijkheid, zodat niemand anders data kan afluisteren van de connectie. 2) integriteit, je bent er zeker van dat de data die je ontvangt ook echt door de server verstuurd is, en niet door een derde gegenereerd is (door bijvoorbeeld bogus tcp pakketten te versturen). 3) server authenticatie, zodat de client zeker weet dat hij een connectie met de server heeft. Dit verhindert zogenaamde Man-in-the-middle attacks. • Het User Authetication protocol: Dit protocol biedt verschillende manieren voor de client om zichzelf te authenticeren aan de server. Dit protocol draait bovenop de Transport layer. • De Connection layer: De Transport layer maakt een beveiligde tunnel aan voor data. De Connection layer maakt meerdere kanalen aan, allemaal met hun eigen eigenschappen, en zorgt dat data bestemd voor één van deze kanalen aan de andere kant van de connectie in het goede kanaal er weer uit komt. Dit heet multiplexing. De Connection layer draait bovenop de Transport layer en wordt gestart door het User Authentication protocol. • Kanaal protocollen, zoals een shell, een file transfer protocol, of een getunnelde TCP/IP connectie. Deze opdeling in verschillende lagen maken het protocol makkelijk te implementeren en uit te breiden. Voor bedrijf-specifieke uitbreidingen zijn steeds methoden aangegeven waarop de bedrijven hun eigen algoritmes/protocollen toe kunnen voegen. Zodoende kan een bedrijf zijn eigen encryptie protocol gebruiken, zonder dat iemand met een client zonder deze extensies opeens niet meer werkt.
Protocol versie Op dit moment zijn er twee versies van SSH, versie 1 en 2. Versie 1 schijnt onveilig te zijn en wordt daarom vaak niet meer ondersteund. Versie twee wordt door het ietf (internet engineering taskforce) beschreven in internet-
4
drafts, later zullen hier RFC (Request For Comments) pagina’s van gemaakt worden. Het protocol dat ik beschrijf is beschreven in deze internet-drafts.
Localization Voor het grootste gedeelte wordt over het SSH protocol binaire data gestuurd die door server en client geinterpreteerd worden. In sommige gevallen echter, wordt tekst gestuurd die direct voor de gebruiker is bestemd. Op die plaatsen is de taal meestal instelbaar, de server hoeft echter niet jouw taal te ondersteunen. De internet-draft zegt op al deze plaatsen dat beide kanten de talen en teksten mogen negeren, op een enkele plaats wordt het gebruik ervan zelfs sterk afgeraden. Omdat het eigenlijk nooit voorkomt dat het nuttig is om tekst van de server direct aan de user te tonen, zal ik in dit document verder geen aandacht besteden aan localization.
Algemene definities/concepten Pakket Een pakket bestaat uit informatie dat verstuurd wordt over het SSH protocol. De informatie bestaat uit één of meer velden, elk veld is data van een bepaald type.
Datatypes Hier wordt beschreven hoe data van een bepaald type wordt opgeslagen en vervolgens verstuurd. • boolean: representeert de waardes true en false. True wordt als de waarde 1 opgeslagen, false als 0, beide van het type uint8. • uint8: representeert een 8-bits niet-negatief getal. Dit wordt in de tekst een byte genoemd. Als er uint8[n] wordt gebruikt, betekent dit n keer een uint8. • uint32: representeert een 32-bits niet-negatief getal. Een waarde wordt opgeslagen als vier uint8’s volgens de big-endian methode: Het meest significante uint8 krijgt de minst significante plaats, etc. • string: representeert een rij van variabele lengte van uint8 waardes. De lengte van de string is minimaal 0, maximaal 232 – 1. De lengte wordt als een uint32 opgeslagen, daarachter wordt de data geplakt. • mpint: deze multiple-precision integer representeert een integer van virtueel ongelimiteerde lengte. Hij wordt opgeslagen in two’s complement formaat, voorafgegaan door zijn lengte, de lengte is een uint32 veld. Voorbeelden: o De waarde nul heeft als lengte 0, dit betekent dat er één uint32 wordt opgeslagen met de waarde 0, of de vier uint8’s 0 0 0 0 o De waarde 8 is in één uint8 op te slaan, dus de lengte is 1. De opgeslagen waarde wordt dus 0 0 0 1 8 o De waarde 255 is niet zo op te slaan: 0 0 0 1 255, want dit is gelijk aan het getal –1. Er moet dus een nul voor worden gezet, zodat de lengte 2 wordt. De data wordt 0 0 0 2 0 255. • namelist: representeert een lijst van namen, gescheiden door komma’s. Een naam moet een lengte groter dan nul hebben, en mag geen komma bevatten. In het protocol wordt de namelist alleen voor 5
•
benamingen van algoritmes en subprotocollen gebruikt, en niet voor binaire data, zodat de restrictie dat een naam geen komma mag bevatten geen problemen oplevert. block: representeert 1 of meerdere velden. Het formaat van het block wordt door de omstandigheden gespecificeerd. Een block dat bestaat uit bv. een string en een uint32 wordt verkregen door de string te pakken en daar de uint32 gewoon achter te plakken.
Algoritme en protocol benamingen De gebruikte algoritmes en protocollen hebben ieder hun eigen naam. Een naam zal minstens 1 karakter hebben en niet langer zijn dan 64 karakters. Al deze karakters zullen printbare USASCII zijn, en de naam is case-sensitive, zodat zlib een andere naam is als ZLIB. Ook mogen ze geen komma bevatten. Alle mogelijke namen die geen @ bevat, zijn gereserveerd door de IETF. Alle mogelijke namen die één @ bevatten, zijn te gebruiken door andere personen. Het formaat van deze namen is naam@dnsnaam, waabij dnsnaam eigendom is van de persoon die de naam gebruikt. Op deze manier kunnen er geen botsingen ontstaan doordat verschillende personen dezelfde naam hebben gekozen voor een algoritme dat anders werkt.
Genereren van random data In de Transport layer worden er tijdelijke sleutels gegenereerd voor de verschillende algoritmes. De informatie die nodig is om die sleutels te maken, is voor een deel random data, die door elke partij zelf gegenereerd moet worden. Het is zeer belangrijk dat hiervoor goed random number generators (rng’s) worden gebruikt. Het beste is om non-deterministische rng’s te gebruiken, maar die zullen vaak niet aanwezig zijn. Met een voldoende grote entropie is het best mogelijk om deterministische rng’s te gebruiken. Het is verleidelijk om de C library functie rand() te gebruiken, deze heeft een toestand van 232, dit is echter veel te weinig voor een fatsoenlijke initialisatie van je sleutels. Een afluisteraar kan gewoon elke toestand van de rng proberen en zien of de sleutels kloppen. Een Mersenne twister met een toestand van 219937 – 1 is al een veel betere keus. Zo’n rng moet dan ook nog geinitialiseerd worden. De standaard truuk om de huidige tijd te pakken, werkt niet. Als de klok in secondes nauwkeurig werkt, dan hoeft een afluisteraar slechts 1800 mogelijke sleutels af te gaan, gegeven dat hij op een kwartier nauwkeurig de tijd van een van de beide partijen weet. Het initialiseren van een rng kan het beste met nondeterministische data, zoals bv. uit /dev/random onder linux. Het is misschien mogelijk dat een andere user op hetzelfde systeem ook 512 bits uit /dev/random haalt en daaruit jouw 512 bits berekent. Een andere mogelijkheid om random data te genereren is de eindgebruiker een aantal keer toetsen in te laten drukken. Je meet steeds de tijd tussen twee opeenvolgende aanslagen, als deze groter is dan de voorgaande, genereer je een bit 1, als deze kleiner is, dan genereer je een 0. Op deze manier heb je nondeterministische data gegenereerd. Het is echt belangrijk dat er goede random data wordt gegenereerd, want dit is de basis van het hele protocol. Als dit niet goed in elkaar zit, dan is de rest niet veilig, en kun je beter onbeveiligde TCP/IP connecties gebruiken, want dan ben je je er tenminste van bewust dat wat je doet niet beveiligd is. 6
De Transport layer De Transport layer is een beveiligd transport protocol. Op dit niveau wordt de vertrouwelijkheid geregeld door de data door encryptie algoritmes te versleutelen, de integriteit wordt gewaarborgd door een message authentication code (MAC) toe te voegen aan de data, en de server authenticiteit wordt gecontroleerd doordat de server in het begin zijn cryptografische handtekening over bepaalde data moet zetten.
Concepten EncryptionAlgorithm Een EncryptionAlgorithm is een cryptografische symmetrische cipher; dit is een algoritme dat met een geheime sleutel data kan encrypten, en met dezelfde sleutel kan de versleutelde data decrypten, zodat de originele data weer bekend wordt. Een voorbeeld van een EncryptionAlgorithm is DES.
PublicKeyAlgorithm Een PublicKeyAlgorithm is een cryptografisch algoritme dat gebruikt wordt voor het signen/verifyen (handtekening zetten/verifiëren) en/of encrypten/decrypten van data. Het heeft als eigenschap dat slechts één partij data kan signen en encrypten, en ieder ander kan het sign van de data verifiëren en decrypten. Dit wordt gebruikt door de server om zijn authenticiteit aan te tonen. Een PublicKeyAlgorithm kan data signen, encrypten, of beide. Een voorbeeld van een PublicKeyAlgorithm is DSA. Dit algoritme kan alleen signen.
MACAlgorithm Een MACAlgorithm is een Message Authentication Code en wordt gebruikt om m.b.v. een sleutel die aan beide kanten van de connectie bekend is van data een soort checksum te maken. Deze ‘checksum’ die MAC wordt genoemd, wordt achter de data geplakt voor het versturen zodat de andere kant van de connectie kan zien dat er niets aan de data is veranderd. Een voorbeeld van een MACAlgorithm is HMAC-SHA1.
CompressionAlgorithm Een CompressionAlgorithm is een algoritme dat compressie toe past op data. Dit kan het dataverkeer over het netwerk verminderen, maar het gebruik kost wel rekenkracht van zowel de server als de client.
KeyExchangeAlgorithm Een KeyExchangeAlgorithm is een algoritme dat gebruikt wordt om sleutels af te spreken. Dit algoritme heeft de eigenschap dat beide kanten van de connectie data oversturen, beide partijen kunnen uit die data de benodigde sleutels berekenen, maar een afluisteraar kan uit de overgestuurde data de sleutels niet bereken. Een KeyExchangeAlgorithm gebruikt eerder overgestuurde informatie, dit zijn de versies van de client en de server en de pakketten van de initialisatie van de Algoritme onderhandeling. Een KeyExchangeAlgorithm levert een Shared 7
Secret op, een Exchange Hash en een Hashfunctie. Met deze informatie worden later de sleutels berekend. Als de sleutels berekend zijn, worden deze voor de EncryptionAlgorithms en MACAlgorithms gebruikt. Een voorbeeld van een (onderdeel van een) KeyExchangeAlgorithm is Diffie-Hellman.
Host key Een PublicKeyAlgorithm heeft een sleutel nodig. Als de server een bepaald PublicKeyAlgorithm wil gebruiken, dan moet hij daar al een sleutel bij gegenereerd hebben. Deze sleutel wordt de Host key genoemd. Tijdens het gebruik van het KeyExchangeAlgorithm wordt deze Host key gebruikt om de authenticiteit van de server aan te tonen. Als de client nog geen Host key van de server kent, of als er wel een Host key bekend is maar deze afwijkt van de gestuurde Host key, dan bestaat het gevaar dat je geen connectie hebt met de gewenste server, maar met iemand die zelf wel een connectie heeft met de server. Door zijn eigen key op te sturen, kan hij de connectie afluisteren en data veranderen. Dit is de man-in-the-middle attack. Het kan zijn dat je voor de eerste keer een connectie met de server opent, en nog geen Host key kent. Daarom wordt vaak de optie aangeboden om alleen de eerste keer de Host key te accepteren. Het is verstandig om via andere methodes (bv. de server eigenaar opbellen) te verifiëren dat de host key klopt, anders loop je alsnog het risico dat iemand een man-in-the-middle attack uit voert.
Algemeen Ik zal eerst uitleggen hoe de Transport layer ongeveer in elkaar zit om daar een globaal idee van te krijgen. Daarna leg ik hetzelfde nog eens uit, maar dan komen alle details aan bod.
Initialisatie Een client wil een SSH connectie maken met een server. De client opent eerst een TCP/IP connectie met de SSH server. De client en server sturen hun versies naar elkaar op. Vervolgens begint de client met de Algoritme onderhandeling: dit is het bepalen van de te gebruiken algoritmes en sleutels. Daarna zal de client een service aanvragen. De services worden in een ander hoofdstuk behandeld.
Algoritme onderhandeling Zowel de client als de server sturen lijsten van algoritmes op die ze ondersteunen. De volgende lijsten worden opgestuurd: • KexExchangeAlgorithms • ServerHostKeyAlgorithms, dit is een lijst met PublicKeyAlgorithms die door de client ondersteund worden of waarvoor de server een Host key heeft. • EncryptionAlgorithms, dit is een lijst met EncryptionAlgorithms die de client wil gebruiken of die door de server ondersteund worden. Hieruit wordt een EncryptionAlgorithm afgeleid die wordt gebruikt om de data te versleutelen die van de client naar de server wordt gestuurd. • MACAlgorithms • CompressionAlgorithms 8
Encryption, MAC en CompressionAlgorithms worden toegepast op het verkeer van server naar client en client naar server. Er kan voor de client naar server richting een ander algoritme worden gekozen dan voor de server naar client richting. Voor Encryption, MAC en CompressionAlgorithms geldt, dat het eerste protocol dat op de lijst van de Client staat, en die ook op de lijst van de Server staat, gebruikt wordt als protocol voor die desbetreffende functie. Als de Client bv. als EncryptionAlgorithms de lijst “aes128-cbc,aes192-cbc,blowfish-cbc” stuurt en de server stuurt “aes192-cbc,twofish192-cbc”, dan zal aes192-cbc als EncryptionAlgorithm gebruikt worden. Als KexExchangeAlgorithm en PublicKeyAlgorithm wordt een iets moeilijker algoritme toegepast, dat verderop behandeld wordt. In het geval dat er geen algoritme afgesproken kan worden, doordat de corresponderende lijst op de server en de client disjunct zijn, dan mislukt de Algoritme onderhandeling, en moeten de server en client de connectie verbreken. Na het succesvol bepalen van de te gebruiken algoritmes, wordt door middel van een KeyExchangeAlgorithm de sleutels voor de algoritmes bepaald, en wordt de authenticiteit van de server vastgesteld.
Sleutel onderhandeling Het bepalen van de sleutels voor de algoritmes gebeurt tijdens de Sleutel onderhandelingsfase met een KeyExchangeAlgorithm. Een KeyExchangeAlgorithm levert het volgende op: een shared secret K, een exchange hash H en een hash algoritme Hash. Als session identifier voor de connectie wordt de H gebruikt van de eerste sleutel onderhandeling. Deze session identifier is een uniek gegeven voor de connectie en wordt later nog gebruikt. Uit de K, H en Session identifier wordt m.b.v. Hash de verschillende sleutels berekend. Er kunnen zes verschillende sleutels gemaakt worden: Initializatie Vector (IV) voor het EncryptionAlgorithm van client naar server, IV voor server naar client, key voor het EncryptionAlgorithm van client naar server, key voor server naar client, key voor het MACAlgorithm van client naar server en key voor het MACAlgorithm van server naar client. Het berekenen van de sleutels gebeurd door de session identifier, de K en de H op een bepaalde manier aan elkaar te plakken en daar de Hash functie op los te laten.
In gebruik nemen van sleutels Na het bepalen van de sleutels stuurt elke kant een bericht “De sleutels zijn in gebruik genomen” en is de connectie helemaal gereed om data over te sturen. De client zal een service aanvragen, dit zal meestal de User Authentication service zijn, die op zijn beurt het Connection protocol start. Het is ook mogelijk om nieuwe sleutels af te spreken, zodat hackers het moeilijker krijgen om de connectie te kraken. Dit gebeurt door opnieuw met de Algoritme onderhandeling te beginnen. Het advies is om dit elk uur of na elke gigabyte aan verstuurde data, wat er ook eerder komt.
9
Details Initialisatie In het algemeen opent de client een TCP/IP connectie met de server, die op poort 22 staat te luisteren. Andere poorten kunnen natuurlijk ook worden gebruikt, er kan zelfs een ander soort connectie worden gebruikt. Dit moet wel een betrouwbare, connectie-georiënteerde verbinding zijn. Als de connectie eenmaal open staat, dan sturen client en server hun versie op in het volgende formaat: “SSH-protoversion-softwareversion comments” gevolgd door een CRLF, waarbij protoversion “2.0” is voor het in dit document besproken protocol, en softwareversion een implementatie-afhankelijke string is, die uit printbare ASCII karakters bestaat, behalve de spatie en het minteken. De totale lengte mag niet meer zijn dan 255 tekens. Het deel zonder de CRLF wordt later voor het KexExchangeAlgorithm gebruikt. De server mag nog extra informatie sturen voor de versie. Die regels mogen niet met “SSH-“ beginnen, en worden afgesloten met een CRLF. Na het ontvangen van de versies, beginnen de server en client met de Algoritme onderhandeling.
Binair protocol Vanaf het einde van het oversturen van de versies wordt er niet meer gebruik gemaakt van een ASCII protocol, maar van een binair protocol. Informatie wordt overgestuurd in pakketten, die er als volgt uit zien: uint32 packet_length De lengte van het pakket, zonder de mac of de packet_length zelf uint8 padding_length Lengte van de padding, zo dat 5 + n1 + n2 deelbaar is door het maximum van 8 en de blok grootte van het huide EncryptionAlgorithm. De padding_length is minimaal 4. uint8[n1] payload De informatie van het pakket uint8[n2] random Random data padding uint8[m] mac De message authentication code n1 = packet_length – padding_length – 1 n2 = padding_length m = lengte van de MAC. Als er geen MACAlgorithm is, dan m = 0. Een pakket is minimaal 16 bytes groot, en minimaal de blok grootte van het EncryptionAlgorithm plus de lengte van de MAC. De maximale grootte van een pakket is 35000 bytes, de maximale ongecomprimeerde grootte van de payload is 32768 bytes. Op plaatsen waar het nodig is, mag hiervan worden afgeweken, bv. als de server een groot aantal certificaten wil oversturen. Payload De payload is de (mogelijk gecomprimeerde) informatie van het pakket. Als je informatie wil versturen over de Transport layer, dan gebeurt dat als payload in een pakket. De eerste byte van de payload is het type van het pakket. De namen van de types beginnen in dit document met SSH_MSG_. Types
10
bestemd voor verschillende delen van het protocol zitten in verschillende waardebereiken: Transport layer: • 1 – 19: Transport layer algemeen • 20 – 29: Algoritme onderhandeling • 30 – 49: Sleutel onderhandeling User Authentication protocol: • 50 – 59: User Authentication algemeen • 60 – 79: Methode specifieke codes Connection layer: • 80 – 89: Connection layer algemeen • 90 – 127: Channel berichten Overig: • 128 – 191: Gereserveerd • 192 – 255: Lokale extensies Compressie Als er een compressie algoritme actief is wordt de te versturen data gecomprimeerd. De uitvoer hiervan wordt als payload gebruikt. De compressiemethode wordt opnieuw geinitialiseerd na elke Algoritme onderhandeling. De context wordt van pakket tot pakket doorgegeven en voor het verkeer van client naar server en van server naar client worden aparte contexten bewaard. Na elk pakket wordt een partieële flush toegepast, dit betekent dat het huidige blok wordt beeindigd zodat alle data kan worden overgestuurd. Encryptie Als er een encryptie algoritme actief is, dan wordt het hele pakket zonder mac geencrypt. De lengte van het pakket is dus ook geencrypt, zodat bij het ontvangen van de eerste vier bytes van het pakket of de blokgrootte van het encryptie algoritme al begonnen moet worden met decrypten. De sleutels en initialisatie vectors worden bepaald na de KeyExchange. Alle pakketten (zonder mac) achter elkaar worden als één stroom data gezien, de algoritmes worden dus niet steeds opnieuw geinitialiseerd. De encryptie algoritmes voor client naar server en server naar client werken onafhankelijk van elkaar. MAC Als er een MAC algoritme actief is, dan wordt aan het pakket een MAC toegevoegd. Het MAC algoritme wordt geinitialiseerd na de KeyExchange. De MAC wordt berekend over (sequence_number ++ unencrypted_packet) waarbij sequence_number het nummer van het pakket is, gerepresenteerd als een uint32. Het sequence_number is nul voor het eerste pakket, wordt na elk pakket verhoogd, en wordt weer op nul gezet na 232 – 1. Het unencrypted_packet is het pakket voordat het geencrypt wordt.
Algoritme onderhandeling Na het uitwisselen van de versies, begint de Algoritme onderhandeling. Elke kant stuurt het volgende pakket:
11
uint8 SSH_MSG_KEXINIT uint8[16] random data namelist KeyExchangeAlgorithms namelist ServerHostKeyAlgorithms namelist EncryptionAlgorithmsClientToServer namelist EncryptionAlgorithmsServerToClient namelist MacAlgorithmsClientToServer namelist MacAlgorithmsServerToClient namelist CompressionAlgorithmsClientToServer namelist CompressionAlgorithmsServerToClient namelist LanguagesClientToServer namelist LanguagesServerToClient boolean FirstKexPacketFollows uint32 0 (reserved) Op de hieronder beschreven manieren worden de te gebruiken algoritmes bepaald. Als een algoritme niet gekozen kan worden, dan verbreken de client en server de connectie. KeyExchangeAlgorithms Beide kanten sturen een lijst met namen van KeyExchangeAlgorithms die ze ondersteunen. De client geeft met de volgorde de voorkeur weer. Op de volgende manier wordt het te gebruiken KeyExchangeAlgorithm bepaald: itereer over de algoritmes ondersteund door de client. Neem het eerste algoritme dat aan de volgende voorwaardes voldoet: • De server ondersteund het algoritme • Als het algoritme een PublicKeyAlgorithm nodig heeft dat kan encrypten, dan staat zo’n algoritme op de lijst van ServerHostKeyAlgorithms van zowel de client als de server • Als het algoritme een PublicKeyAlgorithm nodig heeft dat kan signen, dan staat zo’n algoritme op de lijst van ServerHostKeyAlgorithms van zowel de client als de server ServerHostKeyAlgorithms De server stuurt een lijst met de namen van PublicKeyAlgorithms op waarvoor hij Host keys heeft. De client stuurt een lijst met PublicKeyAlgorithms op waarvoor hij Host keys wil accepteren. Als PublicKeyAlgorithm wordt het eerste algoritme op de lijst van de client gebruikt die ook door de server wordt ondersteund en die ook aan de voorwaarden voor de al gekozen KeyExchangeAlgorithm voldoet. EncryptionAlgorithmsClientToServer EncryptionAlgorithmsServerToClient Beide kanten sturen een lijst met de namen van EncryptionAlgoritms op. Het gekozen algoritme is het eerste algoritme op de lijst van de client die ook op de lijst van de server staat. Voor het verkeer van client naar server en voor het verkeer van server naar client kunnen dus verschillende algoritmes worden gebruikt.
12
MacAlgorithmsClientToServer MacAlgorithmsServerToClient Beide kanten sturen een lijst met de namen van MacAlgorithms op. Het gekozen algoritme is het eerste algoritme op de lijst van de client die ook op de lijst van de server staat. CompressionAlgorithmsClientToServer CompressionAlgorithmsServerToClient Beide kanten sturen een lijst met de namen van CompressionAlgorithms op. Het gekozen algoritme is het eerste algoritme op de lijst van de client die ook op de lijst van de server staat. LanguagesClientToServer LanguagesServerToClient Wordt hier niet behandeld. FirstKexPacketFollows Zowel de server als de client mogen gokken dat het eerste algoritme dat ze op sturen in KeyExchangeAlgorithms het te gebruiken algoritme wordt. Om de snelheid van het opbouwen van de Transport layer te verhogen, mogen ze alvast een pakket voor dat specifieke KeyExchangeAlgorithm sturen. Als ze dat doen, dan is het veld FirstKexPacketFollows gelijk aan true, anders false. Als bij het ontvangen van het Algoritme onderhandelingspakket van de andere kant blijkt dat de gok van de andere partij verkeerd was, dan moet het volgende pakket bestemd voor Key Exchange genegeerd worden. Als blijkt dat de eigen gok verkeerd was, dan kan er gewoon door worden gegaan met het echte KeyExchangeAlgorithm.
Sleutel onderhandeling De KeyExchangeAlgorithms van beide kanten sturen een aantal voor dat algoritme specifieke pakketten over. Ze krijgen daar de volgende informatie voor: De versies die in het begin zijn overgestuurd, zonder CRLF, en de payload van de Algoritme onderhandelings pakketten. Een KeyExchangeAlgorithm levert het volgende op: Een Shared Secret K, een Exchange Hash H en een Hash functie Hash. De K en H worden als getallen gezien; als ze in een pakket worden gebruikt worden ze dus als mpint gecodeerd. Voor de Transport layer wordt een Session Identifier bijgehouden, die uniek is voor de connectie. Hogere protocollen kunnen van deze session identifier gebruik maken. Tijdens de eerste Sleutel onderhandeling wordt de Session Identifier gelijk gemaakt aan H. Deze verandert daarna niet meer. De sleutels worden als volgt gemaakt: • IV client to server: Key = Hash(K ++ H ++ “A” ++ Session ID) • IV server to client: Key = Hash(K ++ H ++ “B” ++ Session ID) • Encryption client to server: Key = Hash(K ++ H ++ “C” ++ Session ID) • Encryption server to client: Key = Hash(K ++ H ++ “D” ++ Session ID) • Mac client to server: Key = Hash(K ++ H ++ “E” ++ Session ID) • Mac server to client: Key = Hash(K ++ H ++ “F” ++ Sessied ID) De “A”, “B”, etc worden als byte gecodeerd, de K, H, en Session ID als mpint. Samen worden ze in een block gestopt, waarna Hash over dat block de hashwaarde berekent. 13
De algoritmes geven zelf aan hoe groot de sleutel moet zijn. Als de benodigde lengte kleiner is dan de verkregen sleutel, dan wordt de rest van de sleutel niet gebruikt. Als de benodigde lengte groter is, dan wordt de sleutel op de volgende manier langer gemaakt, dit proces wordt herhaald totdat de lengte groot genoeg. Key = Hash(K ++ H ++ Key)
In gebruik nemen van sleutels Nadat de sleutels bekend zijn, kunnen ze worden gebruikt. Met de oude sleutels wordt het volgende pakket verstuurd: uint8 SSH_MSG_NEWKEYS Nadat dit pakket verstuurd is, worden de algoritmes en de bijbehorende sleutels voor het versturen van data in gebruik genomen. Nadat dit pakket ontvangen is, worden de algoritmes en de bijbehorende sleutels voor het ontvangen van data in gebruik genomen.
De connectie is gereed Na de eerste Algoritme onderhandeling vraagt de client een service aan.
Services aanvragen De client kan services aanvragen. Dat gebeurt door het volgende pakket te sturen: uint8 SSH_MSG_SERVICE_REQUEST string service name Als de server de service wil aanbieden, stuurt hij het volgende pakket en start hij de service: uint8 SSH_MSG_SERVICE_ACCEPT string service name Als de server de service de service niet wil aanbieden, dan verbreekt hij de verbinding.
De verbinding verbreken Er zijn verschillende redenen waarom de server of client de verbinding wil verbreken. Een mac van een pakket is niet in orde, een service kan niet verleent worden, etc. Voordat de verbinding echt verbroken wordt, wordt het volgende pakket verstuurd: uint8 SSH_MSG_DISCONNECT uint32 reason code string description string language tag
14
Als reden worden de volgende waardes gebruikt: 1 De host mag niet connecten 2 Protocol fout 3 Key Exchange is mislukt 4 gereserveerd 5 Mac fout 6 Compressie fout 7 Service is niet beschikbaar 8 Protocol versie wordt niet ondersteund 9 Host key is niet te controleren 10 Connectie is kwijtgeraakt 11 Connectie is verbroken door de applicatie 12 Te veel connecties 13 Authenticatie is door de gebruiker afgebroken 14 Er zijn geen authenticatiemethodes meer 15 Illegale gebruikersnaam
Negeer data Om eventuele hackers af te leiden, kan het volgende pakket gestuurd worden: uint8 SSH_MSG_IGNORE string data Beide partijen mogen dit pakket op elk moment sturen, beide partijen zullen de inhoud van data negeren.
Debug berichten Voor het debuggen van programma’s is het volgende pakket bestemd: uint8 SSH_MSG_DEBUG boolean always_display string message string language_tag Beide partijen mogen dit pakket op elk moment sturen, beide partijen mogen dit pakket negeren. Als always_display true is, dan is dat een sterke hint dat de implementatie het aan de eindgebruiker moet laten zien of in de logs moet opslaan.
Onbekende pakketten Als een implementatie een pakket binnen krijgt waarvan het niet weet waar het voor bestemd is, dan moet hij het volgende pakket terug sturen: uint8 SSH_MSG_UNIMPLEMENTED uint32 sequence number van onbekende pakket Deze pakketten zullen gestuurd worden in de volgorde van de onbekende pakketten waarin ze binnen kwamen. Het nut van deze pakketten is dat toekomstige protocollen nieuwe pakketten kan definiëren. Als ze dan niet ondersteund worden, kan zo’n implementatie dan verder af zien van verder gebruik van de nieuwe opties.
15
Bericht nummers De volgende bericht nummers zijn gebruikt in het protocol: SSH_MSG_DISCONNECT 1 SSH_MSG_IGNORE 2 SSH_MSG_UNIMPLEMENTED 3 SSH_MSG_DEBUG 4 SSH_MSG_SERVICE_REQUEST 5 SSH_MSG_SERVICE_ACCEPT 6 SSH_MSG_KEXINIT 20 SSH_MSG_NEWKEYS 21
Algoritmes Van elk algoritme is de titel gelijk aan de naam.
Encryptie 3des-cbc Dit is DES in EDE3 modus (encrypt-decrypt-encrypt met 3 verschillende sleutels). Het wordt gebruikt in CBC (Cipher Block Chaining) modus. De sleutel, IV en blok grootte is 24 bytes. Een beschrijving van dit algoritme staat in [SCHNEIER] blowfish-cbc Dit is Blowfish in CBC modus, zoals beschreven in [SCHNEIER]. De sleutel en IV grootte is 16 bytes, de blok grootte is 8 bytes. twofish128-cbc Dit is Twofish in CBC modus, zoals beschreven in [TWOFISH]. De sleutel, IV en blok grootte is 16 bytes. twofish192-cbc Dit is Twofish in CBC modus, zoals beschreven in [TWOFISH]. De sleutel en IV grootte is 24 bytes, de blok grootte is 16 bytes. twofish256-cbc Dit is Twofish in CBC modus, zoals beschreven in [TWOFISH]. De sleutel en IV grootte is 32 bytes, de blok grootte is 16 bytes. aes128-cbc Dit is AES (Rijndael, sinds 2 october 200 de Advanced Encryption Standard) in CBC modus. De sleutel, IV en blok grootte is 16 bytes. aes192-cbc Dit is AES in CBC modus. De sleutel, IV en blok grootte is 24 bytes. aes256-cbc Dit is AES in CBC modus. De sleutel, IV en blok grootte is 32 bytes. serpent128-cbc Dit is Serpent (gemaakt door Ross Anderson, Eli Biham, Lars Knudsen) in CBC modus. De sleutel, IV en blok grootte is 16 bytes. serpent192-cbc Dit is Serpent in CBC modus. De sleutel, IV en blok grootte is 24 bytes serpent256-cbc Dit is Serpent in CBC modus. De sleutel, IV en blok grootte is 32 bytes. arcfour Dit is de Arcfour stream cipher, zoals beschreven in [SCHNEIER]. De sleutel grootte is 16 bytes, de IV grootte 0 bytes en de blok grootte is 1 byte. Er wordt 16
geloofd dat dit algoritme hetzelfde is als RC4, dat geregistreerd is al strademark van RSA Data Security, Inc. idea-cbc Dit is IDEA (International Data Encryption Algorithm) in CBC modus, zoals beschreven in [SCHNEIER]. De sleutel en IV grootte is 16 bytes, de blok grootte is 8 bytes. The IDEA(tm) block cipher is covered by a patent held by ETH and a Swiss company called Ascom-Tech AG. The Swiss patent number is PCT/CH91/00117. International patents are pending. IDEA(tm) is a trademark of Ascom-Tech AG. There is no license fee required for noncommercial use. Commercial users may obtain licensing details from Dieter Profos, Ascom Tech AG, Solothurn Lab, Postfach 151, 4502 Solothurn, Switzerland, Tel +41 65 242885, Fax +41 65 235761. cast128-cbc Dit is CAST-128 in CBC modus, zoals beschreven in [RFC2144]. De sleutel, IV en blok grootte is 16 bytes. none Dit is het algoritme dat niets doet met de data. De sleutel en IV grootte is 0 bytes. De blok grootte is 1 byte. Dit algoritme wordt initieel gebruikt. Aangeraden wordt om dit algoritme niet te gebruiken.
Integriteit hmac-sha1 Dit is HMAC, beschreven in [RFC2104] met als hash SHA-1, beschreven in [SCHNEIER]. De sleutel en digest grootte is 20 bytes hmac-sha1-96 Dit is HMAC met als hash SHA-1 waarvan alleen de eerste 96 bits worden gebruikt. De sleutel grootte is 20 bytes, de digest grootte is 12 bytes. hmac-md5 Dit is HMAC met als hash MD5, beschreven in [RFC1321]. De sleutel en digest grootte is 16 bytes. hmac-md5-96 Dit is HMAC met als hash MD5 waarvan alleen de eerste 96 bits worden gebruikt. De sleutel grootte is 16 bytes, de digest grootte is 12 bytes. none Dit is het algoritme dat geen mac oplevert. De sleutel en digest grootte is 0 bytes. Aangeraden wordt om dit algoritme niet te gebruiken.
Compressie none Dit is het algoritme dat niets aan de data veranderd. zlib Dit is Zlib (Lempel-Ziv, [LZ77]) zoals beschreven in [RFC1950] en [RFC1951].
Key Exchange diffie-hellman-group1-sha1 Dit algoritme gebruikt Diffie-hellman met als priemgetal p = 17976931348623159077083915679378745319786029604875601170644442 36841971802161585193689478337958649255415021805654859805036464 40548199239100050792877003355816639229553136239076508735759914 17
82257486257500742530207744771258955095793777842444242661733472 7629299387668709205606050270810842907692932019128194467627007 en als generator voor een subgroep van GF(p), g = 2. De orde q is (p – 1) / 2. De hashfunctie Hash is SHA-1. Het heeft een PublicKeyAlgorithm nodig dat kan signen. VC = versie van de client, VS = versie van de server, IC = Algoritme onderhandelings pakket van de client, IS = Algoritme onderhandelingspakket van de server, KS is de public Host key van de server voor het gebruikte PublicKeyAlgoritm. De client genereert een random getal x, 1 < x < q, en berekent e = gx mod p. De client stuurt het volgende pakket naar de server: uint8 SSH_MSG_KEXDH_INIT mpint e De server genereert een random getal y, 0 < y < q) en berekent f = gy mod p. De server ontvangt e van de client. Hij berekent K = ey mod p, H = Hash(VC ++ VS ++ IC ++ IS ++ KS ++ e ++ f ++ K), en hij berekent de signature s van H met het PublicKeyAlgorithm en zijn private Host key. H. VC, VS, IC, IS en KS worden als string gecodeerd, e, f en K worden als mpint gecodeerd. De server stuurt het volgende pakket naar de client: uint8 SSH_MSG_KEXDH_REPLY string KS mpint f string s De client verifieert dat KS de echte Host key van de server is. De client mag KS accepteren zonder te hebben gecontroleerd dat het echt de Host key is van de server. Dit brengt echter het gevaar van de man-in-the-middle-attack met zich mee. De client berekent K = fx mod p, H = Hash(VC ++ VS ++ IC ++ IS ++ KS ++ e ++ f ++ K) en verifieert met het PublicKeyAlgoritm en KS de signature s van De waardes K, H en de functie Hash worden geretourneert aan de Algoritme onderhandeling. De volgende bericht nummers zijn gebruikt in dit algoritme: SSH_MSG_KEXDH_INIT 30 SSH_MSG_KEXDH_REPLY 31 diffie-hellman-group-exchange-sha1 De veiligheid van Diffie-Hellman is gebaseerd op de moeilijkheid van het oplossen van het Discrete Logaritme Probleem (DLP). Waarschijnlijk wordt SSH nog vele jaren gebruikt, en het is mogelijk dat door efficiente algoritmes en veel voorbereidend rekenwerk diffie-hellman-group1-sha1 niet meer veilig is. Daarom is er een tweede KeyExchange gemaakt. De server genereert nu een veilig priemgetal en een generator van een grote subgroep. De hashfunctie is SHA-1. Het heeft een PublicKeyAlgorithm nodig dat kan signen. VC = versie van de client, VS = versie van de server, IC = Algoritme onderhandelings pakket van de client, IS = Algoritme onderhandelingspakket van de server, KS is de public Host key van de server voor het gebruikte PublicKeyAlgoritm. 18
De client stuurt het volgende pakket om de key exchange te beginnen: uint8 SSH_MSG_KEY_DH_GEX_REQUEST uint32 min uint32 n uint32 max min is de minimum grootte van een accepteerbare groep, n is de gewenste grootte en max is de maximum grootte. De aanbevolen grootte van min is 1024, voor max 8192. De server neemt een groep die het beste past bij de wensen van de client. P is een veilig priemgetal, dat wil zeggen dat (p – 1) / 2 is priem. g is een generator van een grote subgroep van GF(p). en stuurt het volgende pakket: uint8 SSH_MSG_KEY_DH_GEX_GROUP mpint p mpint g De client genereert een random getal x, 1 < x < (p – 1) / 2, berekent e = gx mod p, en stuurt het volgende pakket: uint8 SSH_MSG_KEY_DH_GEX_INIT mpint e De server genereert een random getal y, 0 < y < (p – 1) / 2, berekent f = gy mod p, en ontvangt e. De server berekent K = ey mod p, H = Hash(VC ++ VS ++ IC ++ IS ++ KS ++ min ++ n ++ max ++ p ++ g ++ e ++ f ++ K), en signature s over H met de PublicKeyAlgorithm met als key KS. VC, VS, IC, IS en KS worden als string gecodeerd, min, n en max als uint32 en p, g, e, f en K worden als mpint gecodeerd. De server stuurt het volgende pakket op: uint8 SSH_MSG_KEY_DH_GEX_REPLY string KS mpint f string s De client verifieert dat KS de echte Host key van de server is. Ook hier mag de client een onbekende Host key accepteren. De client berekent vervolgens K = fx mod p, H = Hash(VC ++ VS ++ IC ++ IS ++ KS ++ min ++ n ++ max ++ p ++ g ++ e ++ f ++ K), en verifieert het signature s over H met het PublicKeyAlgorithm en de Host key HS. De waardes K, H en de functie Hash worden geretourneert aan de Algoritme onderhandeling. De volgende bericht nummers zijn gebruikt in dit algoritme: SSH_MSG_KEX_DH_GEX_REQUEST 34 SSH_MSG_KEX_DH_GEX_GROUP 31 SSH_MSG_KEX_DH_GEX_INIT 32 SSH_MSG_KEX_DH_GEX_REPLY 33
Public Key Algoritmes In het voorafgaande deel werd gesproken over Host key en Signature. Er werd niet verteld hoe deze in elkaar zitten. Wat de bovengaande tekst betreft, zijn dit allebei blocks, die verpakt in een string (uint32 lengte + inhoud van het block) behandeld worden.
19
ssh-dss Dit is de DSS (Digital Signature Standard, [FIPS-186]) DSA (Digital Signature Algorithm), zoals beschreven in [SCHNEIER]. Dit PublicKeyAlgorithm kan alleen signen. De Host key wordt als volgt gecodeerd in een block: string “ssh-dss” mpint p mpint q mpint g mpint y De Signature wordt als volgt gecodeerd in een block: string “ssh-dss” string dss_signature_blob dss_signature_blob is gecodeerd als een string die r en s bevat. r es s zijn beide 160 bits unsigned integers, zonder lengte, zonder padding en in bigendian gecodeerd. ssh-rsa Dit is het RSA (Rivest, Shamir, Adleman) algoritme, zoals beschreven in [SCHNEIER]. Dit algoritme kan alleen signen (wat het SSH protocol betreft). Het signen en verifien wordt gedaan zoals beschreven in [PKCS1] met de SHA-1 hash. De Host key wordt als volgt gecodeerd in een block: string “ssh-rsa” mpint e mpint n De Signature wordt als volgt gecodeerd in een block: string “ssh-rsa” string rsa_signature_blob rsa_signature_blob is gecodeerd als een string die s bevat. s is een unsigned integer, zonder lengte, zonder padding en in big-endian gecodeerd.
20
Het User Authentication protocol Het User Authentication protocol is een service dat bovenop de Transport layer draait. Ik zal van dit protocol alleen globaal uitleggen hoe het werkt, details kunnen in de internet drafts worden opgezocht.
Authenticatie methodes Er worden verschillende authenticatie methodes ondersteund. De client verteld tegen de server wat zijn usernaam is, welke service er na het User Authentication protocol moet worden gestart en welke authenticatie methode hij wil gebruiken. Afhankelijk van de methode wordt er extra data gestuurd, zoals een public key of een paswoord. De server kan op verschillende manieren reageren: • De authenticatie is gelukt, de gevraagde service wordt gestart. • De authenticatie is gelukt, maar nog niet genoeg. Hier heb je een lijstje met wat je nog meer mag proberen. • De authenticatie is niet gelukt, maar je mag het nog een keer proberen. Hier heb je een lijstje met methodes die je nog mag uitproberen. • De authenticatie is niet gelukt.
Methode: none Met de methode “none” probeer je toegang te krijgen zonder jezelf te authenticeren. De server zal dit normaal gesproken weigeren, maar reageert dan wel met een lijst van methodes die je mag uitproberen. Daarna zoek je dus een leuke methode uit en gaat die uitproberen.
Methode: publickey Met deze methode zet de client zijn handtekening met een van de PublicKeyAlgorithms over een UserAuthRequest pakket en de Session Identifier. De server kan op deze manier controleren of de client eigenaar is van een bepaalde private key, en kan hem vervolgens toegang geven. De client mag ook eerst vragen of hij een bepaalde public key mag gebruiken, waarop de server antwoord of het zin heeft of niet. Op deze manier wordt er processorcapaciteit uitgespaard in de gevallen dat een kostbare sign-operatie geen zin heeft.
Methode: password De client stuurt zijn paswoord op. Dit paswoord wordt niet geencrypt, maar de Transport layer zorgt wel voor encryptie (als het goed is; als de encryptie methode ‘none’ wordt gebruikt, dan hoort deze methode uit gezet te worden). De server kan nu drie dingen doen: zeggen dat het paswoord goed is, zeggan dat hij fout is, of vragen om het paswoord te veranderen. Dit laatste betekent dat het paswoord goed is, maar dat er eerst een nieuw paswoord aangemaakt moet worden.
Methode: hostbased Met deze methode wordt de Host key van de site waar de client vandaan komt gebruikt om de authenticatie te signen.
21
De Connection layer De Connection layer is een service dat bovenop de Transport layer draait. Ook van dit protocol zal ik alleen globaal uitleggen hoe het werkt.
Kanalen Het versturen van data over de Connection layer gebeurt over kanalen. Zo’n kanaal wordt door de server of client aangevraagd, de andere kant bevestigt of wijst dit af, en afhankelijk van het type kanaal wordt het kanaal geinitialiseert. Daarna kan door beide kanten data worden overgestuurd. Er zijn verschillende types, zoals een sessie of een TCP/IP forwarded connectie. Elke type kanaal heeft zijn eigen doel.
Sessie Het is niet duidelijk wat er allemaal onder sessie valt. Als de sessie geopend is, dan kan de client een PTY (pseudo terminal) aanvragen, waarna hij een shell zal openen, de client kan een specifiek commando uitvoeren, of de client kan een subsysteem aanvragen. Op dit moment is er één subsysteem gedefinieerd: een File Transfer / File System Access verbinding.
TCP/IP Forwarding De client kan aan de server vragen om een TCP/IP connectie te maken met een bepaald adres. Als de server dit toestaat, en de verbinding is gemaakt, dan kan de client over het kanaal data sturen die aan de kant van de server in de TCP/IP connectie wordt gestopt. Over het algemeen zal de client eerst zelf hebben staan luisteren voor een inkomende connectie, de data die dan wordt overgestuurd is beveiligd op het deel tussen de client en de server. De client kan ook aan de server vragen om op een bepaalde port te gaan luisteren voor inkomende TCP/IP connecties. Op het moment dat de server een connectie ontvangt, dan zal hij dit de client laten weten door een kanaal te openen. De client kan dan zelf zijn eigen deel van de TCP/IP connectie maken.
X11 kanalen De client kan aan de server vragen om een X11 (Een soort grafische shell) kanaal aan te maken. Het lijkt erop dat er eerst een sessie moet worden geopend waar toestemming wordt gevraagd om X11 connecties aan te maken, maar de draft is voor mij heel erg onduidelijk. Ik ben onbekend met het X11 protocol, misschien zit dit deel in de draft toch logisch in elkaar.
22
Problemen Tijdens het bestuderen van het SSH protocol en het implementeren van een SSH client ben ik op een aantal vreemde zaken gestuit. Sommige daarvan zijn heel erg klein, andere zijn wat lastiger en zouden in de toekomst problemen op kunnen leveren.
Een KeyExchangeAlgorithm dat een PublicKeyAlgorithm nodig heeft dat kan signen én encrypten Op dit moment hebben de KeyExchangeAlgorithms alleen PublicKeyAlgorithms nodig die kunnen signen. Er zijn ook alleen maar PublicKeyAlgorithms die kunnen signen. Maar wat gebeurt er als in de toekomst of door een lokale extensie PublicKeyAlgorithms worden toegevoegd die alleen maar kunnen encrypten (bv El-Gamal), PublicKeyAlgorithms die beide kunnen (bv RSA), en KeyExchangeAlgorithms die beide nodig hebben. Het is in de draft niet duidelijk of zo’n KeyExchangeAlgorithm dan één PublicKeyAlgorithm krijgt, of twee, mogelijk verschillende, namelijk één voor signen en de ander voor encrypten. Het probleem zit in de Algoritme onderhandeling. In de ietf draft [SSHTRANSPORT] staat het volgende over het kiezen van een KeyExchangeAlgorithm: iterate over client's kex algorithms, one at a time. Choose the first algorithm that satisfies the following conditions: • the server also supports the algorithm • if the algorithm requires an encryption-capable host key, there is an encryption-capable algorithm on the server's server_host_key_algorithms that is also supported by the client • if the algorithm requires a signature-capable host key, there is a signature-capable algorithm on the server's server_host_key_algorithms that is also supported by the client. Stel we kiezen een KeyExchangeAlgorithm dat een PublicKeyAlgorithm nodig heeft dat kan signen en encrypten. Uit dit stukje tekst kun je concluderen dat zo’n KeyExchangeAlgorithm twee verschillende PublicKeyAlgorithms krijgt. Nu kijken we naar het stukje in [SSH-TRANSPORT] dat gaat over het kiezen van een PublicKeyAlgorithm: The first algorithm on the client's list that satisfies the requirements and is also supported by the server MUST be chosen. Een algoritme dat alleen kan signen of alleen kan encrypten wordt dus niet gekozen, er wordt hier dus alleen een algoritme gekozen dat beide kan. Uit dit stukje tekst kun je dus concluderen dat een KeyExchangeAlgorithm precies één PublicKeyAlgorithm krijgt, wat in tegenspraak is met het stukje over het kiezen van een KeyExchangeAlgorithm.
Het gebruik van disconnection reason codes is niet gespecificeerd De client of server stuurt net voordat de connectie wordt beeindigd meestal een disconnect bericht. Met dat bericht wordt een code meegegeven als reden. De ietf draft geeft de redenen in het volgende formaat: #define SSH_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT 1 23
#define SSH_DISCONNECT_PROTOCOL_ERROR 2 #define SSH_DISCONNECT_KEY_EXCHANGE_FAILED 3 #define SSH_DISCONNECT_RESERVED 4 etc. Van een aantal redenen is heel goed te bedenken wanneer welke gebruikt moet worden. Van een aantal andere redenen is dat niet bekend. Wat gebeurt er als de server opeens een bericht met code 30 verstuurt? Dat bericht behoort tot de berichten die door de KeyExchange gebruikt worden. Als je niet met de key exchange bezig bent, wat doe je dan? Stuur je dan een bericht UnImplemented waarna je gewoon doorgaat, of breek je de verbinding af met een code ProtocolError? Of een code 39? Deze valt ook nog in de KeyExchange reeks, maar ik ken geen KeyExchangeAlgorithm dat deze code gebruikt, een UnImplemented klinkt dan dus eigenlijk logischer. Als ik mijn client meteen nadat de eerste Algoritme onderhandeling klaar is een nieuwe onderhandeling laat starten, dan krijg ik van de OpenBSD SSHD UnImplemented messages terug, terwijl de server de Algoritme onderhandeling wel degelijk ondersteund. Dit is ook meteen het volgende probleem:
Algoritme onderhandeling is niet transparant Tijdens de Algoritme onderhandeling kunnen nog steeds berichten zoals Debug, Ignore, Disconnect en data bestemd voor hogere protocollen worden gestuurd. Het lijkt erop dat de Algoritme onderhandeling volledig transparant is. Dit is echter niet het geval. [SSH-TRANSPORT]: After the key exchange, the client requests a service. We mogen dus niet meteen een re-exchange beginnen. Als we dit wel doen, dan zou de server ons eigenlijk moeten disconnecten vanwege een protocol error. OpenBSD SSHD doet dit niet, die stuurt een UnImplemented. Op dit moment zijn er slechts twee services gedefinieerd, UserAuth en Connection, die meteen in het begin worden aangevraagd. Als er nieuwe services bij komen, dan mogen die niet op elk moment worden aangevraagd. Als er net op dat moment dat je ze wil aanvragen een Algoritme onderhandeling aan de gang is, dan zal de service moeten wachten.
Het coderen van een hash als mpint Een hash functie levert een blok data op. Die data is gewoon een rijtje bits, met een lengte afhankelijk van de gebruikte hash functie. Je zou dus verwachten dat die data als string wordt opgeslagen. In het SSH protocol wordt die data echter als mpint gerepresenteerd. Dat heeft als gevolg dat als de meest significante bit een 1 is, er een extra nul voor moet worden gezet, anders is het een negatief getal. Je 160 bits hash, die in 20 bytes kan worden gezet, wordt dan opeens als 21 bytes behandeld. Als je hier geen rekening mee houdt, en je gebruikt dit als data voor een andere hash, krijg je een totaal andere uitkomst. Dit levert de nodige uurtjes debuggen op.
C-stijl definities De bericht codes, disconnect codes, etc worden in de volgende stijl gegeven: #define SSH_MSG_DISCONNECT 1 #define SSH_MSG_IGNORE 2
24
#define SSH_MSG_UNIMPLEMENTED 3 #define SSH_MSG_DEBUG 4 Dit is in de programmeertaal C gewoon te kopieëren. Ik vraag me af waarom in de drafts niet gewoon tabellen met iets als het volgende staat: MsgDisconnect 1 MsgIgnore 2 Een #define hoort volgens mij niet in de drafts thuis. In C++ bijvoorbeeld zouden deze messages niet als #define worden gebruikt, dit bevuilt namelijk alle namespaces, maar als enum of als constanten in een speciale namespace of class. Het voorvoegsel SSH_ is dan ook meteen overbodig.
Niet gebruiken van namelist In [SSH-ARCH] wordt het veld namelist uitgelegd, maar verder kom je het niet tegen. Overal waar het zou kunnen worden gebruikt, wordt string gebruikt, samen met de tekst dat elke naam in de string geen komma mag bevatten, dat namen door komma’s van elkaar gescheiden worden, etc. Na de tiende keer wordt dit vrij vermoeiend.
Sommige algoritmes zijn ‘verplicht’ De internet-drafts geven bij lijsten van algoritmes aan welke algoritmes verplicht zijn, welke aanbevolen, en welke optioneel. In veel gevallen kunnen die algoritmes door local policy uitgeschakeld worden. In de draft staat dat dit ook mag. Wat heeft het dan voor nut om ze verplicht te stellen?
25
Referenties [BOOST] http://www.boost.org, “Boost C++ Libraries”, May 15, 2002 – Version 1.28.0 [CRYPTO++] http://www.cryptopp.com, “Crypto++: a C++ Class Library of Cryptographic Primitives”, November 5, 2001 – Version 4.2 [FIPS-186] Federal Information Processing Standards Publication, "FIPS PUB 186, Digital Signature Standard", May 1994. [LZ77] Ziv, J and A. Lempel, A universal algorithm for sequential data compression, IEEE Transactions on Information Theory, IT-23, pp. 337-343, 1977. [RFC1950] Deutsch, P. and J-L. Gailly, "ZLIB Compressed Data Format Specification version 3.3", RFC 1950, May 1996. [RFC1951] Deutsch, P., "DEFLATE Compressed Data Format Specification version 1.3", RFC 1951, May 1996. [RFC2104] Krawczyk, H., Bellare, M. and R. Canetti, "HMAC: Keyed-Hashing for Message Authentication", RFC 2104, February 1997. [RFC2144] Adams, C., "The CAST-128 Encryption Algorithm", RFC 2144, May 1997. [SCHNEIER] Schneier, B., “Applied Cryptography Second Edition: protocols algorithms and source in code in C”, 1996. [SSH-ARCH] Ylonen, T., "SSH Protocol Architecture", I-D draft-ietf-architecture-12.txt, January 2002. [SSH-CONNECT] Ylonen, T., "SSH Connection Protocol", I-D draft-ietf-connect-15.txt, January 2002. [SSH-DHGEX] Friedl, M., “Diffie-Hellman Group Exchange for the SSH Transport Layer Protocol”, I-D draft-ietf-dh-group-exchange-02.txt, January 2002. [SSH-FILEXFER]
26
Ylonen, T., “SSH File Transfer Protocol”, I-D draft-ietf-filexfer-02.txt, October 2001. [SSH-FINGER] Friedl, M., “SSH Fingerprint Format”, I-D draft-ietf-fingerprint-00.txt, March 2002. [SSH-KBDINTER] Cusack, F., “Generic Message Exchange Authentication for SSH”, I-D draftietf-auth-kbdinteract-03.txt, April 2002. [SSH-TRANS] Ylonen, T., "SSH Transport Layer Protocol", I-D draft-ietf-transport-14.txt, March 2002. [SSH-USERAUTH] Ylonen, T., "SSH Authentication Protocol", I-D draft-ietf-userauth-15.txt, January 2002. [Tbo] van Tilborg, H., “An Interactive Introduction To Cryptology”, Eindhoven University of Technology. [TWOFISH] Schneier, B., "The Twofish Encryptions Algorithm: A 128-Bit Block Cipher, 1st Edition", March 1999.
27
Appendix A: Een voorbeeld Ik zal een voorbeeld geven hoe je via SSH het commando “ls /” kunt geven. De output is gegenereerd door mijn programma RSSH (Zie volgende appendix). Elk pakket wordt twee keer gegeven: Voor pakketten die verstuurt worden eerst de plain-tekst payload, daarna het volledige pakket encrypted, voor pakketten die ontvangen worden eerst encrypted, daarna de payload in plain-text. Alle pakketten worden in twee versies gegeven: in hexadecimaal en in tekst. In de tekst vorm zijn alle niet-printbare karakters vervangen door een punt. Commentaar staat schuingedrukt onder de pakketten. Client version: SSH-2.0-sshclient1.0 We sturen onze versie op. We gaan over op het binaire protocol. Oh ja, ik moet de versie nog eens veranderen in rssh1.0 of zo. Outgoing unencrypted data: 14e85e63069a6d0588145858a4da668f610000003d6469666669652d68656c6c6d616 e2d67726f75702d65786368616e67652d736861312c6469666669652d68656c6c6d61 6e2d67726f7570312d736861310000000f7373682d6473732c7373682d72736100000 0636165733132382d6362632c6165733139322d6362632c6165733235362d6362632c 626c6f77666973682d6362632c74776f666973683132382d6362632c74776f6669736 83139322d6362632c74776f666973683235362d6362632c336465732d636263000000 636165733132382d6362632c6165733139322d6362632c6165733235362d6362632c6 26c6f77666973682d6362632c74776f666973683132382d6362632c74776f66697368 3139322d6362632c74776f666973683235362d6362632c336465732d6362630000002 b686d61632d736861312d39362c686d61632d6d64352d39362c686d61632d73686131 2c686d61632d6d64350000002b686d61632d736861312d39362c686d61632d6d64352 d39362c686d61632d736861312c686d61632d6d6435000000046e6f6e65000000097a 6c69622c6e6f6e6500000000000000000100000000 20 ..^c..m...XX..f.a...=diffie-hellman-group-exchange-sha1,diffiehellman-group1-sha1....ssh-dss,ssh-rsa...caes128-cbc,aes192cbc,aes256-cbc,blowfish-cbc,twofish128-cbc,twofish192-cbc,twofish256cbc,3des-cbc...caes128-cbc,aes192-cbc,aes256-cbc,blowfishcbc,twofish128-cbc,twofish192-cbc,twofish256-cbc,3des-cbc...+hmacsha1-96,hmac-md5-96,hmac-sha1,hmac-md5...+hmac-sha1-96,hmac-md596,hmac-sha1,hmac-md5....none....zlib,none............. Pakket 20, SSH_MSG_KEXINIT. We sturen onze lijsten met algoritmes op. Alhoewel hier maar een paar algoritmes aangeboden worden, ondersteund mijn client alle algoritmes die in de IETF draft genoemd zijn. Outgoing encrypted data: 000001bc0814e85e63069a6d0588145858a4da668f610000003d6469666669652d686 56c6c6d616e2d67726f75702d65786368616e67652d736861312c6469666669652d68 656c6c6d616e2d67726f7570312d736861310000000f7373682d6473732c7373682d7 27361000000636165733132382d6362632c6165733139322d6362632c616573323536 2d6362632c626c6f77666973682d6362632c74776f666973683132382d6362632c747 76f666973683139322d6362632c74776f666973683235362d6362632c336465732d63 6263000000636165733132382d6362632c6165733139322d6362632c6165733235362 d6362632c626c6f77666973682d6362632c74776f666973683132382d6362632c7477 6f666973683139322d6362632c74776f666973683235362d6362632c336465732d636 2630000002b686d61632d736861312d39362c686d61632d6d64352d39362c686d6163 2d736861312c686d61632d6d64350000002b686d61632d736861312d39362c686d616 32d6d64352d39362c686d61632d736861312c686d61632d6d6435000000046e6f6e65 000000097a6c69622c6e6f6e65000000000000000001000000000000000000000000 .......^c..m...XX..f.a...=diffie-hellman-group-exchange-sha1,diffiehellman-group1-sha1....ssh-dss,ssh-rsa...caes128-cbc,aes192cbc,aes256-cbc,blowfish-cbc,twofish128-cbc,twofish192-cbc,twofish256-
28
cbc,3des-cbc...caes128-cbc,aes192-cbc,aes256-cbc,blowfishcbc,twofish128-cbc,twofish192-cbc,twofish256-cbc,3des-cbc...+hmacsha1-96,hmac-md5-96,hmac-sha1,hmac-md5...+hmac-sha1-96,hmac-md596,hmac-sha1,hmac-md5....none....zlib,none..................... Deze tekst is nog te lezen... Encryptie is nog niet actief Outgoing unencrypted data: 22000004000000040000000400 34 "............ We gokken erop dat we Diffie-Hellman-Group-Exchange-SHA1 gaan gebruiken en sturen een SSH_MSG_KEX_DH_GEX_REQUEST. Als grootte voor het priemgetal vragen we een grootte van minimaal 1024, maximaal 1024 en een voorkeur van 1024. Outgoing encrypted data: 000000140622000004000000040000000400000000000000 .....".................. Server version: SSH-2.0-OpenSSH_3.1p1 De server versie Incoming encrypted data: 000001e40914ac7079393e4ce5e78ae3b9c54c948a6f0000003d6469666669652d686 56c6c6d616e2d67726f75702d65786368616e67652d736861312c6469666669652d68 656c6c6d616e2d67726f7570312d736861310000000f7373682d7273612c7373682d6 473730000004a6165733132382d6362632c336465732d6362632c626c6f7766697368 2d6362632c636173743132382d6362632c617263666f75722c6165733139322d63626 32c6165733235362d6362630000004a6165733132382d6362632c336465732d636263 2c626c6f77666973682d6362632c636173743132382d6362632c617263666f75722c6 165733139322d6362632c6165733235362d63626300000055686d61632d6d64352c68 6d61632d736861312c686d61632d726970656d643136302c686d61632d726970656d6 4313630406f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d 6d64352d393600000055686d61632d6d64352c686d61632d736861312c686d61632d7 26970656d643136302c686d61632d726970656d64313630406f70656e7373682e636f 6d2c686d61632d736861312d39362c686d61632d6d64352d3936000000096e6f6e652 c7a6c6962000000096e6f6e652c7a6c69620000000000000000000000000000000000 0000000000 .......py9>L......L..o...=diffie-hellman-group-exchange-sha1,diffiehellman-group1-sha1....ssh-rsa,ssh-dss...Jaes128-cbc,3descbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc...Jaes128cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256cbc...Uhmac-md5,hmac-sha1,hmac-ripemd160,
[email protected],hmac-sha1-96,hmac-md5-96...Uhmac-md5,hmacsha1,hmac-ripemd160,
[email protected],hmac-sha1-96,hmac-md596....none,zlib....none,zlib...................... Incoming unencrypted data: 14ac7079393e4ce5e78ae3b9c54c948a6f0000003d6469666669652d68656c6c6d616 e2d67726f75702d65786368616e67652d736861312c6469666669652d68656c6c6d61 6e2d67726f7570312d736861310000000f7373682d7273612c7373682d64737300000 04a6165733132382d6362632c336465732d6362632c626c6f77666973682d6362632c 636173743132382d6362632c617263666f75722c6165733139322d6362632c6165733 235362d6362630000004a6165733132382d6362632c336465732d6362632c626c6f77 666973682d6362632c636173743132382d6362632c617263666f75722c61657331393 22d6362632c6165733235362d63626300000055686d61632d6d64352c686d61632d73 6861312c686d61632d726970656d643136302c686d61632d726970656d64313630406 f70656e7373682e636f6d2c686d61632d736861312d39362c686d61632d6d64352d39 3600000055686d61632d6d64352c686d61632d736861312c686d61632d726970656d6 43136302c686d61632d726970656d64313630406f70656e7373682e636f6d2c686d61 632d736861312d39362c686d61632d6d64352d3936000000096e6f6e652c7a6c69620 00000096e6f6e652c7a6c696200000000000000000000000000
29
20 ..py9>L......L..o...=diffie-hellman-group-exchange-sha1,diffiehellman-group1-sha1....ssh-rsa,ssh-dss...Jaes128-cbc,3descbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256-cbc...Jaes128cbc,3des-cbc,blowfish-cbc,cast128-cbc,arcfour,aes192-cbc,aes256cbc...Uhmac-md5,hmac-sha1,hmac-ripemd160,
[email protected],hmac-sha1-96,hmac-md5-96...Uhmac-md5,hmacsha1,hmac-ripemd160,
[email protected],hmac-sha1-96,hmac-md596....none,zlib....none,zlib............. De lijsten met algoritmes.
[email protected] is een extensie van openssh. Mijn client ondersteund meer algoritmes We kunnen nu bepalen welke algoritmes er worden gebruikt. Hij geeft ook een algoritme hmac-ripemd160. Deze naam is nog niet door de IETF gestandaardiseerd! Foei! Algorithms to be used: KeyExchange: diffie-hellman-group-exchange-sha1 HostKey : ssh-dss Client: Server: Encryption : aes128-cbc aes128-cbc MAC : hmac-sha1-96 hmac-sha1-96 Compression: none zlib Incoming encrypted data: 00000094081f0000008100dcfac4efe89f5b082962ab9a67e8d63e84fa491e5d38749 78815868595469163da0661e6208a8c2cd4f83893b53864adfd2154e8d8efa146bad8 08562e4bf6c90348fd79eeb3387d93fc7943bc450ba55399ba3cf3dfbd0d4e7180000 7b0e9d5f12e7a2cb7ea4e49812e715f8dc570c478dc2deb1c49b0ae87a5df544a5e8b af00000001050000000000000000 .................[.)b..g..>..I.]8t......F.c..a. ..,..8..8d..!T....F...V.K...H.y..8}..yC.E..S..<....Nq........z,..NI.. q_..p.x.-..I.....TJ^............... Incoming unencrypted data: 1f0000008100dcfac4efe89f5b082962ab9a67e8d63e84fa491e5d387497881586859 5469163da0661e6208a8c2cd4f83893b53864adfd2154e8d8efa146bad808562e4bf6 c90348fd79eeb3387d93fc7943bc450ba55399ba3cf3dfbd0d4e71800007b0e9d5f12 e7a2cb7ea4e49812e715f8dc570c478dc2deb1c49b0ae87a5df544a5e8baf00000001 05 31 ............[.)b..g..>..I.]8t......F.c..a. ..,..8..8d..!T....F...V.K...H.y..8}..yC.E..S..<....Nq........z,..NI.. q_..p.x.-..I.....TJ^....... SSH_MSG_DH_GEX_GROUP. We krijgen een priemgetal en een generator. De generator is 5 zo te zien. De lengte van het priemgetal is 81h = 2048 bits (het eerste getal is een 0 omdat de meest significante bit een 1 is. Als de 0 er niet voor zou staan, zou het een negatief getal zijn). hmm... ik dacht toch echt dat we om maximaal 1024 bits vroegen... Outgoing unencrypted data: 2000000081009230b0ad5c892722adc43e6d0c3a653c4a47b80e1307e97eca2762bfa 3f0b531730974d1e746891f9dd4b5f7a73873abbfd39b532c2707d5cf90dbcd75a8b2 f8b2533d5f6a9f42bff2aa16757234315431e8c7e405f12e404240013367c34368702 d2e04e34bc539f027a5467fa636a29baa29430d5b1fbc83999538a9f94ca2 32 ......0..\.'"..>m.:e<JG.....~.'b....1s.t..F.......8s....S,'......u... .S=_j.B....ur41T1......@
[email protected].'.F..6...)C.[.....8..L. SSH_MSG_DH_GEX_INIT. We sturen onze e (2048 bits) op. Outgoing encrypted data: 0000008c052000000081009230b0ad5c892722adc43e6d0c3a653c4a47b80e1307e97 eca2762bfa3f0b531730974d1e746891f9dd4b5f7a73873abbfd39b532c2707d5cf90 dbcd75a8b2f8b2533d5f6a9f42bff2aa16757234315431e8c7e405f12e40424001336 7c34368702d2e04e34bc539f027a5467fa636a29baa29430d5b1fbc83999538a9f94c a20000000000
30
..... ......0..\.'"..>m.:e<JG.....~.'b....1s.t..F.......8s....S,'......u... .S=_j.B....ur41T1......@
[email protected].'.F..6...)C.[.....8..L...... Incoming encrypted data: 0000027c0521000001b2000000077373682d6473730000008100c5e27c8b13a158872 1861034d38e703fdc63c763488ed6619ac200775c31f35b3b07947430615dbe79af0e a1a92527191a229c1fc0e5e3f6f19d3e867606c7c40614595a454525cf17a267350a5 e1ae8b27420a9fd654db6ea0e7b5842386a8d2c40c1dbb21f8082b1a7624048d52839 4df413e355971bf04ecaf282a0151a2b0000001500af76be274f40f899dbcd6fecee1 cb7d7f7a06883000000810095e53985ee05e3a88bf7dba7aa754fe8e0e5758b9fe5b2 f729948a83616e53647f5c10bae0c5791bcff35d53f5c7ef4033c34c8d2b18f3d29ed 6f6d448b2b9a413c0b090ed7a5dcc3ecfb047989bfb2635ca925718f153b2d83484f7 db480bf9cf53183502e60b5ddae0cca4c0338990f54bc4536d397547c3e69787239bd 8b40000008066c6cee43baedd99e80ac94a62d09acec8b8b5ac27188cd201ccbacc81 88e85b3f78d4708da104edba5b3ac73c60af7e4bb8b2df0482bffcc764abbde115972 5dad78abddf4d3da7355e1985f4849b5a37287a6bcb87b70033cb3caf2e2446fe13bd 7d1399ee3ca2c6a96a9482ead93ce240515b3627ecf4877546bb76f1773b000000801 ad6eb623d665e8791fcb7da1038ade4c825279e88d509f62394329e069c1fb8c7208f 947a606bd6a153f11c8f32ae8f4c33548f4dace9313b7888422f910820d01cb0386ab b321c84fa6d3dc2ae4027cca31f0b97124355b688fe45c45411ec4c068c9f70a8ca32 637ecc941dbe9d65254bf19513011d670c984ee538f2eebf000000370000000773736 82d647373000000289e6a0f948a1c65dbc72638f62c1256146c786935061390e4c61d 1594fec76cd83a0cef455bf166f40000000000 ...|.!........sshdss.......|...X.!..4..p?.c.cH..a...w\1.[;..t0a].y....%'.."........>.v .....YZEE%...g5.^...t ..eM...{XB8j.,@........b@H.(9M...U...N......+......v.'
[email protected] ........9..........uO...u.....)...anSd.\....y...]
[email protected].+.......H.. ......z].>..G...&5..W..S..4...H...S.5...].....3...K.Sm9uG....#....... f...;......Jb.......'..........[?x.p.....[:.<`.~K........d.....%..... M=.5^.....Z7(zk....3.<..$F...}...<...j....<.@Q[6'...uF.v.w;.......b=f ^......8...%'.....#.2...... ..z`k..S...2..L3T.M..1;x.B/.. ...8j.2...m=..@'......CU...E.T..L...p..2c~.....e%K.....g..N.8......7. ...ssh-dss...(.j....e..&8.,.V.lxi5..........l.:..E[.f...... Incoming unencrypted data: 21000001b2000000077373682d6473730000008100c5e27c8b13a1588721861034d38 e703fdc63c763488ed6619ac200775c31f35b3b07947430615dbe79af0ea1a9252719 1a229c1fc0e5e3f6f19d3e867606c7c40614595a454525cf17a267350a5e1ae8b2742 0a9fd654db6ea0e7b5842386a8d2c40c1dbb21f8082b1a7624048d528394df413e355 971bf04ecaf282a0151a2b0000001500af76be274f40f899dbcd6fecee1cb7d7f7a06 883000000810095e53985ee05e3a88bf7dba7aa754fe8e0e5758b9fe5b2f729948a83 616e53647f5c10bae0c5791bcff35d53f5c7ef4033c34c8d2b18f3d29ed6f6d448b2b 9a413c0b090ed7a5dcc3ecfb047989bfb2635ca925718f153b2d83484f7db480bf9cf 53183502e60b5ddae0cca4c0338990f54bc4536d397547c3e69787239bd8b40000008 066c6cee43baedd99e80ac94a62d09acec8b8b5ac27188cd201ccbacc8188e85b3f78 d4708da104edba5b3ac73c60af7e4bb8b2df0482bffcc764abbde1159725dad78abdd f4d3da7355e1985f4849b5a37287a6bcb87b70033cb3caf2e2446fe13bd7d1399ee3c a2c6a96a9482ead93ce240515b3627ecf4877546bb76f1773b000000801ad6eb623d6 65e8791fcb7da1038ade4c825279e88d509f62394329e069c1fb8c7208f947a606bd6 a153f11c8f32ae8f4c33548f4dace9313b7888422f910820d01cb0386abb321c84fa6 d3dc2ae4027cca31f0b97124355b688fe45c45411ec4c068c9f70a8ca32637ecc941d be9d65254bf19513011d670c984ee538f2eebf00000037000000077373682d6473730 00000289e6a0f948a1c65dbc72638f62c1256146c786935061390e4c61d1594fec76c d83a0cef455bf166f4 33 !........sshdss.......|...X.!..4..p?.c.cH..a...w\1.[;..t0a].y....%'.."........>.v .....YZEE%...g5.^...t ..eM...{XB8j.,@........b@H.(9M...U...N......+......v.'
[email protected] ........9..........uO...u.....)...anSd.\....y...]
[email protected].+.......H..
31
......z].>..G...&5..W..S..4...H...S.5...].....3...K.Sm9uG....#....... f...;......Jb.......'..........[?x.p.....[:.<`.~K........d.....%..... M=.5^.....Z7(zk....3.<..$F...}...<...j....<.@Q[6'...uF.v.w;.......b=f ^......8...%'.....#.2...... ..z`k..S...2..L3T.M..1;x.B/.. ...8j.2...m=..@'......CU...E.T..L...p..2c~.....e%K.....g..N.8......7. ...ssh-dss...(.j....e..&8.,.V.lxi5..........l.:..E[.f. SSH_MSG_KEX_DH_GEX_REPLY. We krijgen de server public host key te zien, de server stuurt f (2048 bits) op en maakt een signature van H. Nu berekenen we de Shared Secret en alle sleutels Server public key ssh-dss 0000008100c5e27c8b13a1588721861034d38e703fdc63c763488ed6619ac200775c3 1f35b3b07947430615dbe79af0ea1a92527191a229c1fc0e5e3f6f19d3e867606c7c4 0614595a454525cf17a267350a5e1ae8b27420a9fd654db6ea0e7b5842386a8d2c40c 1dbb21f8082b1a7624048d528394df413e355971bf04ecaf282a0151a2b0000001500 af76be274f40f899dbcd6fecee1cb7d7f7a06883000000810095e53985ee05e3a88bf 7dba7aa754fe8e0e5758b9fe5b2f729948a83616e53647f5c10bae0c5791bcff35d53 f5c7ef4033c34c8d2b18f3d29ed6f6d448b2b9a413c0b090ed7a5dcc3ecfb047989bf b2635ca925718f153b2d83484f7db480bf9cf53183502e60b5ddae0cca4c0338990f5 4bc4536d397547c3e69787239bd8b40000008066c6cee43baedd99e80ac94a62d09ac ec8b8b5ac27188cd201ccbacc8188e85b3f78d4708da104edba5b3ac73c60af7e4bb8 b2df0482bffcc764abbde1159725dad78abddf4d3da7355e1985f4849b5a37287a6bc b87b70033cb3caf2e2446fe13bd7d1399ee3ca2c6a96a9482ead93ce240515b3627ec f4877546bb76f1773b Secret: 772d11dae5be4639e543395bc258a32c96b4dd6d05ea8e56cc2def495afdc745a29d3 758b0cade39ab06ce4ac80a3fe6ae3b157db7e1fad9bb03600af955c3c674a5fef55f c4f2f2aa725e05a4b607f5cb9392510d8f72eb867dac5a2cfe146ef20c3607ba140a2 2634180f3844edbffa41fa3339b04b1b5115e9f3d43bdd017 H: 5accd5d0250db349f714052165516171134e9646 Key for A fe65128a041c437dcbeb62bbe0c38b45 Key for C 43718fc3cdb4a7d45c707bd2c49c7040 Key for B 54b1b966311fc6ff6112b62472b9b52e Key for D c9b7c7a098192c10e93a110ef4b8d6b3 Key for E 17216d580a3c8bef8c100d40acc9a4b9ff2952cd Key for F a8966eb407d42665cb955a66a7e95c8d848d53a8 We hebben de sleutels bepaald. Het programma rekent sleutels pas uit als ze nodig zijn, vandaar de vreemde volgorde. Als encryptie methode gebruiken we aes128, en hebben we dus 128 bits sleutels nodig. Als mac gebruiken we hmac-sha1, die een 160 bits sleutel nodig heeft. Deze sleutel is dus iets langer. Outgoing unencrypted data: 15 21 . We weten de sleutels, we sturen SSH_MSG_NEWKEYS en nemen meteen hierna onze sleutels in gebruik. Outgoing encrypted data: 0000000c0a1500000000000000000000 ................ Outgoing unencrypted data: 020000000b746573746d657373616765
32
2 .....testmessage Onze eerste message die we encrypted versturen. Tijdens het debuggen is het heel makkelijk om meteen een SSH_MSG_IGNORE te versturen, als er iets misgaat met encryptie dan merk je dat meteen. Outgoing encrypted data: 2e96ee5f54f9ef0f62ab93b3094914c0aec4b4d0817a59b955165a5dce8dd008d17c4 3ed6a87f9e43e7405fc ..._T...b....I.......zY.U.Z].....|C.j...>t.. Niet zo heel erg leesbaar meer... Het bericht is ook veel langer geworden. De overhead is in dit geval 4 bytes lengte + 1 byte paddinglengte + 11 bytes padding + 12 bytes mac (alleen de eerste 96 bits van sha1 omdat we hmac-sha1-96 gebruiken) = 28 bytes overhead Incoming encrypted data: 0000000c0a1500000000000000000000 ................ Incoming unencrypted data: 15 21 . De laatste unencrypted message van de server. We nemen zijn keys in gebruik. Algorithm Exchange / Key Exchange is voltooid. Outgoing unencrypted data: 050000000c7373682d7573657261757468 5 .....ssh-userauth We vragen een service aan… ssh-userauth, want we willen onszelf identificeren. Ik vraag me nou af... waarom wachten we hiermee tot na de SSH_MSG_NEWKEYS van de server? Deze kunnen we toch al meteen na onze NEWKEYS sturen? Outgoing encrypted data: 8db6daac6fcfba66784b9326d7ec4f9aefb6b7058ceaafe692dbc8616fc3e06608b52 088702d628557f14bcc ....o..fxK.&..O............ao..f.. .p-b.W.K. Incoming encrypted data: 7c9b99b0ec850eab79ac9f4e3eebcdc7eb2bb21982ef58611b3e4c93943fd522ea3a2 0362770a0c2f5974476 |.......y..N>....+....Xa.>L..?.".: 6'p....Dv Incoming unencrypted data: 02000000066d61726b7573 2 .....markus Ah! De server gebruikt hetzelfde truukje Zo te zien is OpenSSH in debug-mode gecompileerd. (OpenSSH is echt aan te raden om je client te testen, er zitten heel veel debug opties in om extra output te genereren zoals het dumpen van de blok waarover de server zijn signature zet) Incoming encrypted data: 239fa5a99c83b3aa4470289d1cea8bb3de5d616d6457e7d7c26a3b7faef9a6522f98d 40820ea8cf7c31c5b76 #.......Dp(......]amdW...j;....R/... .....[v Incoming unencrypted data: 060000000c7373682d7573657261757468 6 .....ssh-userauth We mogen beginnnen met User Authentication Outgoing unencrypted data: 3200000004746573740000000e7373682d636f6e6e656374696f6e000000046e6f6e6 5
33
50 2....test....ssh-connection....none SSH_MSG_USERAUTH_REQUEST… we heten ‘test’, we willen een ssh-connection, en we gebruiken methode ‘none’ om ons te identificeren... dit gaat vast mis, maar dan krijgen we een lijst met methodes die we kunnen gebruiken om onszelf te identificeren. Outgoing encrypted data: a8d47ad9299feee741cc37706a852ea2f353cc823606907b18657bc045a6df57ad408 00f6ac158b10933b7bbcc92ccfb1bea35f47dc459d5b6143d71 ..z.)...A.7pj....S..6..{.e{
[email protected].}.Y...=q Incoming encrypted data: e05fdb24cfea44fc3faa1d70e8f647fc9ef37a8509abf7872b3d427f4a66868eb7d7e bc5044682009ca70fecdb34e8cdd58d11332c56aa6553c35d97716c0b0147e2dd2262 4e44cf7276544b ._.$..D.?..p..G...z.....+=B.Jf.......F.......4.....3,V.eS.].ql..G.."b ND.rvTK Incoming unencrypted data: 33000000277075626c69636b65792c70617373776f72642c6b6579626f6172642d696 e74657261637469766500 51 3...'publickey,password,keyboard-interactive. SSH_MSG_USERAUTH_FAILURE… 3x raden waarom. We kunnen nog wel andere methodes proberen... publickey, password of keyboard-interactive Outgoing unencrypted data: 3200000004746573740000000e7373682d636f6e6e656374696f6e000000087061737 3776f7264000000000774657374707764 50 2....test....ssh-connection....password.....testpwd We proberen het met methode ‘password’. Ons paswoord is ‘testpwd’ Outgoing encrypted data: 8d30bb72423f62937a74a5648656700c9cffc6bfb310ee8a54fe2404dc4e8c66d6e70 a1d81498336b3a37f7be54747b3a9c6132e08a3af037be68fbe8dfad5731ef943b2d3 7ef07ee3f3f172 .0.rB?b.zt.d.Vp.........T.$..N.f.....I.6...{.GG.........{......s..C.. ~.~...r Incoming encrypted data: 4aa5b804c08e2ef526ea08cc51ed1ee86f55958617f75b3f7a84c0a9 J.......&...Q...oU....[?z... Incoming unencrypted data: 34 52 4 SSH_MSG_USERAUTH_SUCCESS. Ons paswoord is correct en ssh-connection wordt voor ons opgestart. Outgoing unencrypted data: 5a0000000773657373696f6e000000000000271000000200 90 Z....session......'..... Met een SSH_MSG_CHANNEL_OPEN willen we een session kanaal openen. Ons kanaal nummer is 0, de windowsize is 2710h bytes, de maximum pakket grootte is 200h bytes. Outgoing encrypted data: 774e3444f9122d0fe904c6591f6131d64c4d2248c1c116e3a0df717ee3454426e1c83 8d81fc269de126336be5c727787989b61956da6bd03e80d48d8 wN4D..-....Y.a1.LM"H......q~.ED&..8...i..c6.\rw...a.m.....H. Incoming encrypted data: 5a1b9894438dbfa22feb90a071edbd3792a85e7f377e96393938d6ea6193582cd227b 8829fc969a064d9f0db
34
Z...C.../...q..7..^.7~.998..a.X,.'....i.d... Incoming unencrypted data: 5b00000000000000000000000000008000 91 [................ SSH_MSG_CHANNEL_OPEN_CONFIRMATION. Het kanaalnummer op de server is ook 0, de window size is 0 en de maximum pakket grootte is 8000h = 32kb. Outgoing unencrypted data: 6200000000000000046578656301000000046c73202f 98 b........exec.....ls / We vragen een commando aan... ls /... we willen graag een reply hebben. Outgoing encrypted data: 2d98144918d4c477eb46a2d16a3f3e45a90dccf477bba30ca8b7fd7c10e8a0ae57e93 3b1333f5440e006bcd8 -..I...w.F..j?>E....w......|....W.3.3?T@.... Incoming encrypted data: 49b621c8377a242e059454edfc9fce36d892b950e02ed99ad8d948087f224c3bd62e6 a624cd574fa2d7a01fe I.!.7z$...T....6...P......H.."L;..jbL.t.-z.. Incoming unencrypted data: 5d0000000000020000 93 ]........ SSH_MSG_WINDOW_ADJUST. Vanaf nu mogen we maximaal 128kb data sturen. Ik vraag me af waarom OpenSSHD dit niet meteen met de open_confirmation heeft meegestuurd. Incoming encrypted data: 8d37b768bdb574957c8c75e7ccbcc1d9843ac29bc9a22f28efd1e202 .7.h..t.|.u......:..../(.... Incoming unencrypted data: 6300000000 99 c.... De bevestiging dat ons commando uitgevoerd gaat worden. Incoming encrypted data: 6755287ed2193cf560ad7a29ca28e1b9d893925c2c92ea5cc54eb35377c12ea1d355f a76bc56d0e98e86e54b8b443930bf199ec0e1d9e9ecdb1bead1e48b7ac39c68714d53 411dd0290a55dc2840df79a580a831cf4a552233cf1a2e52b32de229910c26896201a b52629d1c gU(~..<.`.z).(.....\,..\.N.Sw....U.v.V.....K.D90..............z..hqMS A..).U.(@.y...1.JU"3...R.-.)..&.b..Rb.. Incoming unencrypted data: 5e00000000000000486261636b75702e7461722e627a320a62696e0a626f6f740a646 5760a6574630a686f6d650a6c69620a6d6e740a70726f630a726f6f740a7362696e0a 746d700a7573720a7661720a 94 ^.......Hbackup.tar.bz2.bin.boot.dev.etc.home.lib.mnt.proc.root.sbin. tmp.usr.var. SSH_MSG_CHANNEL_DATA… de uitvoer van ls /. De puntjes tussen de namen zijn enters. Als we eerst een PTY hadden aangevraagd, dan werden de namen in kolommen weergegeven en met ANSI-sequences gekleurd. Incoming encrypted data: b3c28131c817e53654bfb2998d7711a13c85e16accf500b9dd70814d1fb78515b54c4 6316ee2c80f04116e76 ...1...6T....w..<..j.....p.M.....LF1n.....nv
35
Incoming unencrypted data: 62000000000000000b657869742d7374617475730000000000 98 b........exit-status..... Het commando is klaar, en geeft met SSH_MSG_CHANNEL_REQUEST een sessionspecifieke request door. Hij laat ons de exit-status van ls / weten, namelijk 0. Incoming encrypted data: 9b65b3c1a1f4303704ccdf24e98853eb5e336d9c18654f5e596087f1 .e....07...$..S.^3m..eO^Y`.. Incoming unencrypted data: 6000000000 96 `.... SSH_MSG_CHANNEL_EOF Incoming encrypted data: 4b38e4da4ad976f2fb4b2840fdcca2bce13043d2d752c1e2a566dd7a K8..J.v..K(@.....0C..R...f.z Incoming unencrypted data: 6100000000 97 a.... SSH_MSG_CHANNEL_CLOSE Outgoing unencrypted data: 6100000000 97 a.... We bevestigen de close Outgoing encrypted data: edba7f8eccd744396f10bd15d2540926dcb10fdbc398bd68989f2b72 ......D9o....T.&.......h..+r Outgoing unencrypted data: 010000000b0000000000000000 1 ............. We zijn klaar met het ls / commando. We zouden nu een andere sessie kunnen aanvragen ofzo, maar wat mij betreft zijn we klaar. We sturen een SSH_MSG_DISCONNECT met als reden SSH_DISCONNECT_BY_APPLICATION. De socket sluiten we meteen hierna, dus we krijgen geen data meer terug. Outgoing encrypted data: 80ecfe3cdf1b5031cfa2b65a04c58bb053ae22cd7ad95b0ddb5aad1d82889198a97bf 10a93bd2125b8abeb1a ...<..P1...Z....S.".z.[..Z.......{....!%....
36
Appendix B: RSSH RSSH (Richard’s Secure Shell) is de SSH client die ik heb gemaakt tijdens het bestuderen van het SSH protocol. Het implementeren van het protocol heeft enorm geholpen bij het begrijpen van alle details. RSSH ondersteunt alle protocollen van de Transport layer, alle protocollen van het User Authentication protocol (behalve keyboard-interactive, die in een aparte internet-draft wordt beschreven). De Connection layer ondersteunt het forwarden van TCP/IP connecties en heeft een framework voor het aanmaken van sessies met daarin shells, het uitvoeren van commandos en het draaien van subsystemen. Ik ben bezig met het implementeren van een FTP client die als subsysteem gaat draaien. RSSH maakt gebruik van de Boost library van http://www.boost.org en de Crypto++ van http://www.cryptopp.org. Hij compileert onder Microsoft Visual C++ 7.0 (.NET), in theorie zou hij ook onder unix moeten werken: alle delen behalve de Socket library (deze werkt onder zowel windows als unix) zijn platform-onafhankelijk en (zo goed mogelijk) volgens de C++ standaard geprogrammeerd. Op dit moment is RSSH een framework, er zit geen userinterface bij maar het is de bedoeling dat er userinterfaces geschreven kunnen worden die op een hoog niveau met SSH om kunnen gaan. Mijn plan is om een grafische userinterface voor Windows te schrijven. Main.hpp en Main.cpp horen niet bij het framework, maar is een voorbeeld hoe shells aangemaakt kunnen worden, hoe commando’s uitgevoerd kunnen worden en hoe TCP/IP connecties kunnen worden geforward. Ik heb daarnet geprobeerd om de sourcecode in dit document zetten, maar dan zou dit verslag zo’n 140 pagina’s gaan tellen. Ik zal de sourcecode op http://www.student.tue.nl/t/r.a.peters/rssh.zip zetten.
37