Issue‎ > ‎Issue 13‎ > ‎

007.txt


echo|zine, volume 4, issue 13 -----------------------[ SSH Private Key Cracker ]------------------------ -------------------------------------------------------------------------- ------------------------------[ anonymous ]------------------------------- -- -- -( Pendahuluan ) Ketika rasa bosan dialami penulis (editor-in-chief, dan co-editor) dalam menunggu kontribusi artikel untuk issue #13 ini, penulis mencoba membuat sesuatu yang mungkin dapat berguna dalam penggunaan komputer sehari-hari. Beberapa ide yang terlontar antara lain: SSH private key cracker (yang akhirnya dituangkan menjadi artikel ini), web password management (yang kemudian dibahas oleh Digital Junkie di artikel echo13-09), serta runtime binary backdooring system untuk SSH daemon (mungkin dilain kesempatan akan dibahas karena proof-of-concept codenya sendiri baru selesai 30%.. long way to go, man! Semoga pada issue #14, penulis dapat merilisnya) -- -- -( SSH Authentication Methods ) SecureShell (SSH) memberikan beberapa pilihan authentication method yang fleksibel, diantaranya password authentication yang konvensional, challenge response based method, dan public key based user (Pubkey- Authentication) atau client host (HostbasedAuthentication) method. Yang paling umum digunakan adalah password authentication dan Pubkey- Authentication. Implementasi password authentication hanya meminta user untuk memasukkan username dan password agar dapat terautentikasi. Sedangkan implementasi PubKeyAuthentication melibatkan private dan public key dari user, dimana public key sudah terlebih dahulu ditempatkan pada sisi server dan private key pada sisi client. Jika Anda merasa baru pertama kali mendengar dan ingin lebih jauh tentang penggunaan pubkey pada SSH, silakan mencari referensi di Internet. -- -- -( Passphrase ) Umumnya penggunaan private key melibatkan penggunaan passphrase. Passphrase digunakan untuk mengauthentikasi user sebelum menggunakan private key. Passphrase dapat saja diset kosong--ini biasanya ditemukan pada proses batch seperti remote backup yang menggunakan SSH. Passphrase serupa dengan password, namun passphrase mengijinkan penggunaan frase yang berupa rangkaian kata, punctuation, bilangan, whitespace, atau string karakter yang diinginkan. Sangat disayangkan jika seseorang lupa akan passphare yang digunakan, karena tidak ada cara untuk melakukan recover passphrase. Jika passphrase hilang atau terlupakan, key baru harus dibuat dan disalinkan pada corresponding public key di mesin remote. Artikel ini menawarkan solusi brute-forcing untuk merecover passphrase yang hilang pada SSH private key berdasarkan dictionary files dan John The Ripper password generator. -- -- -( Analisis implementasi PrivKey pada OpenSSH ) Kami menggunakan source code OpenSSH untuk mencari tahu bagaimana proses Public Key Authentication bekerja, dan penulis merasa beruntung karena dokumentasi yang penulis butuhkan dapat dengan mudah diperoleh dari man pages dan comments yang terdapat pada source code. OpenSSH yang digunakan adalah openssh-4.2p1. Analisis dimulai dengan bagaimana SSH menangani private key. Untuk itu penulis melihat file authfile.c pada function key_load_private_pem(). 454 Key * 455 key_load_private_pem(int fd, int type, const char *passphrase, 456 char **commentp) 457 { 458 FILE *fp; 459 EVP_PKEY *pk = NULL; 460 Key *prv = NULL; 461 char *name = "<no key>"; 462 463 fp = fdopen(fd, "r"); 464 if (fp == NULL) { 465 error("fdopen failed: %s", strerror(errno)); 466 close(fd); 467 return NULL; 468 } 469 pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); 470 if (pk == NULL) { 471 debug("PEM_read_PrivateKey failed"); 472 (void)ERR_get_error(); 473 } else if (pk->type == EVP_PKEY_RSA && 474 (type == KEY_UNSPEC||type==KEY_RSA)) { 475 prv = key_new(KEY_UNSPEC); 476 prv->rsa = EVP_PKEY_get1_RSA(pk); 477 prv->type = KEY_RSA; 478 name = "rsa w/o comment"; 479 #ifdef DEBUG_PK 480 RSA_print_fp(stderr, prv->rsa, 8); 480 RSA_print_fp(stderr, prv->rsa, 8); 481 #endif 482 if (RSA_blinding_on(prv->rsa, NULL) != 1) { 483 error("key_load_private_pem: RSA_blinding_on failed"); 484 key_free(prv); 485 prv = NULL; 486 } 487 } else if (pk->type == EVP_PKEY_DSA && 488 (type == KEY_UNSPEC||type==KEY_DSA)) { 489 prv = key_new(KEY_UNSPEC); 490 prv->dsa = EVP_PKEY_get1_DSA(pk); 491 prv->type = KEY_DSA; 492 name = "dsa w/o comment"; 493 #ifdef DEBUG_PK 494 DSA_print_fp(stderr, prv->dsa, 8); 495 #endif 496 } else { 497 error("PEM_read_PrivateKey: mismatch or " 498 "unknown EVP_PKEY save_type %d", pk->save_type); 499 } 500 fclose(fp); 501 if (pk != NULL) 502 EVP_PKEY_free(pk); 503 if (prv != NULL && commentp) 504 *commentp = xstrdup(name); 505 debug("read PEM private key done: type %s", 506 prv ? key_type(prv) : "<unknown>"); 507 return prv; 508 } mata penulis tertuju pada fungsi PEM_read_PrivateKey() 469 pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); secara refleks, penulis langsung membaca halaman manual OpenSSL tentang fungsi tersebut dengan perintah $ man pem dari halaman manual tersebut, penulis menemukan bahwa penggunaan fungsi PEM_read_PrivateKey() yang lengkap adalah sebagai berikut: EVP_PKEY *PEM_read_PrivateKey(FILE *fp, EVP_PKEY **x, pem_password_cb *cb, void *u); dari penggunaan fungsi PEM_read_PrivateKey() pada OpenSSH, EVP_PKEY **x dan pem_password_cb *cb tidak diperlukan untuk membaca sebuah private key. Routine dari PEM_read_PrivateKey() akan memberikan memberikan nilai 1 jika prosedur yang dilakukan sukses, dan 0 jika gagal. -- -- -( Here we go! ) Setelah membaca source code OpenSSH dan halaman manual OpenSSL, penulis langsung mulai mencoba membuat code. Penulis menggunakan OpenSSL library karena sifatnya yang portable pada banyak architecture dan operating system. pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *)passphrase); if (pk) { /* password is match */ } fp menangani informasi dari public key, dalam hal ini adalah passphrase yang hendak di-crack, dan passphrase adalah user input. Sedangkan pk adalah prosedur yang membandingkan antara informasi dari public key dengan user input. pk akan memberikan nilai 0 jika gagal, dan 1 jika sukses (passphrase ditemukan). Kemudian code dikembangkan dengan menambah prosedur untuk menangani private key ditambah dengan ciri khas bruteforcing program yang akan mengulang prosedur tertentu sampai akhirnya apa yang dicari ditemukan (atau tidak) serta user input handling. FILE *fp; EVP_PKEY *pk = NULL; ... /* membuka private key file */ if ((fp = fopen(argv[1], "r")) == NULL) { fprintf(stderr, "Error: Cannot open %s.\n", argv[1]); exit(1); } ... while (fgets(pw, CHAR_LENGTH, stdin) != NULL) { pk = PEM_read_PrivateKey(fp, NULL, NULL, (char *) pw); if (pk) { fprintf(stderr, "Passphrase match: %s\n", pw); exit(0); }; fclose(fp); fp = fopen(argv[1], "r"); } fprintf(stderr, "Damn, I can't find any match.\n"); ... Perlu diketahui bahwa kita harus menambahkan SSL_library_init() sebagai inisialisasi SSL library dengan meregisterkan algoritma yang akan digunakan. Penambahan terakhir adalah prosedur sanitasi dari user input yang akan memberikan pesan error (yang penulis modifikasi menjadi usage info) jika argumen yang diberikan pada command line kurang dari 2 (nama program dan private key file). extern char *__progname; if (argc != 2) { fprintf(stderr, "Usage: %s [sshprivkey]\n", __progname); exit(1); } -- -- -( *Roger* We have problem here! ) Masalah yang pertama kali ditemukan ketika fgets() membedakan "string\n" dengan "string" saja (tepatnya "string\0"). "\n" adalah karakter yang digunakan untuk mengakhiri suatu string kemudian memulai baris baru. Sehingga ketika penulis mencoba menggunakan dictionary file, program tidak mengenali passphrase yang sebanarnya ada pada dictionary file tersebut. Workaround ditemukan dengan melakukan scanning pada setiap string (passphrase) untuk mencari "\n" kemudian menghapus temuan pertama dan menggantinya dengan "\0" for (i = 0; i < CHAR_LENGTH && pw[i] != 10; i++); pw[i] = 0; Masalah kemudian dapat diselesaikan. -- -- -( Penggunaan program ) Program SSH private key cracker ini, yang penulis beri nama ssh-privkey-crack, sangat bergantung pada user input yang diberikan. Input dapat berupa dictionary files yang dapat diperoleh di /usr/share/dict/words. Namun, penulis menyarankan penggunaan program John The Ripper yang memiliki kemampuan menggenerasi password dengan sangat cepat. Program harus dikompile terlebih dahulu. Untuk mengkompile, cukup dengan perintah `make'. $ make cc -lssl -lcrypto -Wall -O2 -o ssh-privkey-crack ssh-privkey-crack.c maka executable file ssh-privkey-crack akan terbuat. Penulis menyertakan fungsi regression test dengan perintah `make test'. Pastikan John The Ripper sudah terinstal terlebih dahulu. $ make test /usr/bin/ssh-keygen -t dsa -f dsa_test -N "stevoid" Generating public/private dsa key pair. Your identification has been saved in dsa_test. Your public key has been saved in dsa_test.pub. The key fingerprint is: f2:e4:33:ee:27:23:f3:7a:ce:a1:4e:e3:60:5d:e4:2b someone@somemachine /usr/local/bin/john -stdout -incremental | ./ssh-privkey-crack ./dsa_test Passphrase match: stevoid Test yang diberikan adalah dengan membuat private key baru bertipe key DSA bernama "dsa_test" (public key-nya bernama "dsa_test.pub"). Kemudian menggunakan John The Ripper untuk menghasilkan daftar kata secara incremental dan diarahkan ke stdout yang kemudian daftar tersebut satu-per-satu akan diambil dari stdin oleh ssh-privkey-crack. Untuk penggunaan sehari-hari, Anda dapat memilih untuk menggunakan John The Ripper. $ john -stdout -incremental | ssh-privkey-crack id_dsa atau dengan dictionary files yang sudah dipersiapkan terlebih dahulu. $ ssh-privkey-crack id_dsa < /usr/share/dict/words jika ssh-privkey-crack menemukan passphrase yang cocok, maka ia akan mengakhiri pekerjaannya dan memberikan laporan "Passphrase match: blah" dan jika tidak menemukan passphrase yang cocok, maka laporan yang diberikan adalah "Damn, I can't find any match." -- -- -( Penutup ) Penggunaan metode bruteforcing memungkinkan seseorang dapat mengetahui kembali passphrase yang hilang. Namun yang diajukan diatas sangatlah bergantung pada kualitas dictionary file atau kerumitan passphrase yang digunakan. Untuk mengantisipasi bruteforcing oleh pihak yang tidak diinginkan, seseorang harus menggunakan passphrase yang baik -- mudah diingat, tidak terdapat dalam dictionary file manapun, menyertakan karakter yang tidak umum digunakan seperti !, @, #, $, %, ^, &, dan lain-lain. Penggunaan passphare seperti itu akan menyulitkan seseorang melakukan bruteforcing.. setidaknya jika ia berhasil, maka ia telah menghabiskan waktu yang lama dan resource yang cukup besar. ssh-privkey-crack yang dirilis bersama artikel ini adalah versi 0.1 yang artinya masih jauh dari sempurna. Proof-of-concept (PoC) code ini diselesaikan dalam waktu 2 hari (berikut finishingnya). Penulis masih mempunyai sejumlah tasks yang harus dilakukan untuk mengembangkan program ini agar lebih baik lagi -- lihat file TODO untuk melihat features yang mungkin akan ditambahkan diwaktu mendatang. -- -- -( Source code ) NOTE: Untuk men-decode-nya, gunakan perintah `uudecode [file ini]` Contoh: $ uudecode echo13-07.txt $ ls ssh-privkey-crack-0.1.tar.gz $ tar zxvf ssh-privkey-crack-0.1.tar.gz $ make $ make test begin 644 ssh-privkey-crack-0.1.tar.gz M'XL(`,%0R4,"`^T::W/:2-)?F5_11YP]8'G;D"H[WET9RS8;#!S"\>62%#5( M`R@6DFHD<-C=_/?K'H&-#;FKVN5<V=OI*EO23+^FIZ<?$E$T*832G=^*1<&6 MW+XME(N5TMY.H8SPJE935X2G5W5?*1_4J]5:^:!<V2M7*O5:?0]J>W\B>+JX M/PE$6_??N.Y?=GK6#DU3/SS\ZOZ_JM:>['^U7JONP9[>_^??_SQ\FD4Q<#^( M)T*"95T"S?-8`.*`PA&2L:6+'#%V(X!+013^8AK,HB*\$U$>[I+AJT[/A/ZE MT8;`%Q`*&05^$8P8D#U,@ZGPXQ4J&P>N/X8X`"FFW/4?6.*=`Z@1A+.AYT83 M"&82?->^C2"0R0.?"I3,^LA5"HY"5ERCF"^([0,S-R(9PH]F.!U/.+(50>CA M`OW@+AE@2^*[0-X2,;(C*:$,/@D[CF"$8KGGJ45(=SR)ET(CR)":#I_ZP)2R MMALO2,FQ%TB7I(]0TRQ:`%<4C,!&MI&`H;#Y#*_*U/:"5)QS;\:'GB@RU@C\ MF-LQ(/7<Y2`*:!T/>/RPII^$/0F*@2RZ#N+_X?-_>GUA[?9H_*?S7ZD?/#W_ MU7I%G_]O^OR3B^#A+T!+*,=49\<=P2*8X>F8H7=S?U$$2PA8A@H8N<J;]S1\ MZ_F_U6R8;<M\GO-?.2QOYO_R@3[_W_3Y7[H(A@#H"CEUH\C%)(EY%=-8'M-: MN,AC>G?<$5XI>SMN%$MW.(LIY6)ZBX)1?$<I5J52?\$PM\LPP!QXY\83RIAT M#68QC#"$(`%J(X8+&$ONQ\+)4RZ>NXYPDH1-B9@/@[E@2G:2DW$-KBV4>"4S M?%!T-16&@DN@6@.S.5*Z6$4P8%BQF&!USOLW!I8O30NZO<[;YIEY!FG#PN<T M&.TSA90$-SAK6HV6T;RRP&BU`*EZ1KO?-"T&-\W^)?3,"Z.'!!VD06X/G-N- MUO59LWVAR)I7W58393R00^><P979:V`!U3=.FZUF_YT2?=[LMTW+*B(':'?` M?&NV^V!=$I<UK4Y-:#6-TY8)YYT>0\)W8'7-1M-HY5'CGMGHYY'!Z@X)&AW< MTW]<(S/$@3/CRK@@)7J*=/F(2[HT^E8'9?9P8=9UJT\+..]UKJ#5L4AGN+9, ME&#T#:)%VZ&Z5A[I3%2N1SH;;52GT6]VVH2.8OL]@W1HFQ>MYH79;IA$V5'H M_4X/$:^M)4$>C%[3(I&=Z[XR4$>Q1"9M,V&I;$YV0#V4!F8/#7!E*+;GC_?@ MKYV1ML?_*WXK*%L_2_ROEJN'3^+_0?7@4,?_YX`7\+LS0+=GGC?_"3^>0&D6 MR9(7V-QCC<;]P-#U2V/;9HWSEG%AP0D4;BC(%CI5>`&%,6:04S7J11&.>K9< MA''`6-_H/6(1<\DN_M7L#LSV6T(O#$44,X9J#=Z8[S!4/,*FU:"68^&SGSN7 M[<?:*8Q/P<1'Y8W&&PQFR'!C_0SCFD51Y`3P+#"&H;U_WFR9I.RJE*7J%Y8I M$%:G!0/566>37]%F#!=^M$42VQ@Z8JG]3*.1A?T,V8>NB?VR4`@V.6R7YOK8 M]&Z7F%K.$3<98*M:&,/=1`@<F`*]I=LB8S^3;'66[,<897+'E6@-G$C,F"WL M9Y96RS(FA8?-L#C"^7O;95E*3J$@1SBX9)!=4\;YNC[K^#]1L:!,C1E[G?LQ M.`%\8*F4':(0V-]72`^DI63DF'"<P!<L12YULI]9>189&CTO"]A'_[*N9!'] MKSC^Y9$:FRMA,3KE5GOO9QX\%?<P!B?B4!C194!$4&A#.HK%/'"=-*&3VR(B M,J;BI^#ZMA3TEH1[\!L42YO;4RRM>#%FH^7]HT3#$>2*`?UA,807.\!B*[=: MSHHDMT5GW17]U?/_EJCRO\O_A^57]2?YOW90J>O\_QQ0RC'(_>X:`!1UX[[A MRMA9J);+M0+^J^?77KF^WO:F\@<B3AD8_Q5U!%)$0LZ%4UPRWE%CF=M9:YG; M17.IEK:[_C*W@PXSM[L>,[>S+C.WJSXSM[M.,_='>TW(E1A[@4G=FSD"7E/Y M$!0G/SP:DJX_IK&UP2`4/I;))2'E8^S[B7FX?2(4T^T3^)<(<;!X]06LJMXT M)H#T_2@Z16_0,ML7N,@*-FI47,;`Z/-,ANZX'-MX*B?HY[D</LRS[%>6HJ(, M<J/PF*7,M]U!%\L?R(6W6#*VKULM'%4$X=W[-?8?CZD>C,&ENAOOQ>=82'_) M>C#`,SFFCSS'#-%&D"'!\+<3J&8!!:9&&)[\>)1!@Z*-\I!^&15>1A_\=!X> M:/.K16:/MY%<1WR,5>O+"-YC0%S&PX]/>&PG-3_S:>B)(T3>C@#[0(W'U^HZ ME.DZ`RS*2!K2`\)_DXDL[\G@-<9!.\;@P^5BF\;BLQMG*G3[A:4LJS7PW*%$ MW('KXT1V9=7,*$3SC\A'R,+S]Y6/*$FFLUDX23;O*^8VI0SD$32X3]^_B!Z5 M*RI-EGPVU;B;4)&>&8U%'&7"N_RZL^6!CH:?I2U^$(O9"FV3`\OFOHKO:27! MP89#A7\,^J[$O!78]DP*?QF>I0@]CO=NG%"K+)#^4$ZKQQ(M!UEE$L=#_WO] MR.N_^XX<U?U(FE1H_OOOU5*20>6K]$3.W36O!E)P9]!-<N4;L4"#YM4"5O\S MB4-GD:EB0U8/;Y/E;9JURZ,HG$CLIF#*8WM"WJF6O*1.#%I6]U^4E]@>)CJ4 MNO29[;NI[,\VQ9WQJ8^Q&M"\?\?LZ"9?<1+1Q:5O2Q'/\%SBLK_H3N'_M/ZG M%QG/]_VW5JMO?/]]I=__?=O??\A%CAC+P256PX022#=>'#&``AB.0X2%RB8I M_9C"YB$?NAZB%Q7Z#5)2?/-GF`M#S,%%XML*[K:PO6<2NU.!G#Q[YG'*>PFK M+I?<$YX;B3743\$PF;5BTB7B<QK-\!$6&"AO"\5(\)A^'.)24J<D+9PL*O7^ M!AL$;#ZHN4@PU"])AIAF'&P7?ES_%K[YZ?NC_O2M08,&#1HT:-"@08,&#1HT H:-"@08,&#1HT:-"@08,&#1HT:-"@08,&#1HT:-@%_!OX>E4<`%`````` ` end
Comments