Copy Link
Add to Bookmark
Report
Echo Magazine Issue 13 Phile 0x007
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,
MET#:)%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,HT:-"@08,HT
H:-"@08,HT:-"@08,HT:-"@08,HT:-@%_!OX>E4<`%``````
`
end