elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: Guía actualizada para evitar que un ransomware ataque tu empresa


+  Foro de elhacker.net
|-+  Seguridad Informática
| |-+  Seguridad
| | |-+  Criptografía (Moderador: kub0x)
| | | |-+  Implementacion practica Padding Oracle Attack
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Implementacion practica Padding Oracle Attack  (Leído 185 veces)
AlbertoBSD
Programador y
Colaborador
***
Desconectado Desconectado

Mensajes: 3.518


🏴 Libertad!!!!!


Ver Perfil WWW
Implementacion practica Padding Oracle Attack
« en: 20 Noviembre 2020, 05:29 »

Recientemente me interesa ese tipo de temas otra vez, he aprendido mucho y me gustaría compartirlo con ustedes.

Si no saben de que va el tema aquí dejo unos links.

Block cipher mode of operation
https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation

Wikipedia Padding oracle attack
https://en.wikipedia.org/wiki/Padding_oracle_attack

Padding oracle attack
https://robertheaton.com/2013/07/29/padding-oracle-attack/

Este tipo de Ataque tiene ciertas condiciones iniciales para ser llevado acabo.

  • El cliente solo puede saber si su paquete fue aceptado o no.
Esto es debido al check que hace el servidor sobre el mensaje recibido

  • El servidor no Cambia de KEY utilizada durante el proceso de cifrado y descifrado.
Esto es debido a una mala implementación, ya que el servidor debería de renovar el KEY cada X tiempo y con cada cliente distinto.

  • El servidor tiene algún leak de información ya sea por error o mediante otro tipo de ataque.
  • El cliente solo podrá descifrar Una parte de la información, excepto por el Bloque inicial


Dejo a continuación una imagen de prueba y el código, proximamente subire un video hablando del tema.






Codigo, este codigo ejemplifica el cliente y servidor mediante un hilo distinto, lo hice de esta manera para no complicarme con el protocolo en RED de los mismo, se puede hacer sin hilos, y solo con llamadas a funcion, pero la idea es garantizar que el cliente no tiene acceso al servidor.



Código
  1. /*
  2. Desarollado por AlbertoBSD
  3. email alberto.bsd@gmail.com
  4. g++ -O3 -o opk_example opk_example.c -Wint-to-pointer-cast  -pthread
  5. */
  6.  
  7. #include <time.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include<pthread.h>
  12. #include<unistd.h>
  13. #include"ctaes/ctaes.c"
  14.  
  15. #define AES_BLOCKSIZE 16
  16.  
  17. struct timespec tim, tim2,sim,sim2;
  18.  
  19. void crear_server();
  20. char *tohex(char *ptr,int length);
  21. void *process_server(void *vargp);
  22.  
  23. int MyCBCEncrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out);
  24. int MyCBCDecrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out);
  25.  
  26. /* Values between Server and client */
  27. int values_do;
  28. int values_pad;
  29. int values_length;
  30. int values_leaked;
  31. char *values_enc;
  32. char *values_leak;
  33.  
  34. pthread_mutex_t mtx_values;  //Mutex for those values
  35.  
  36. int main(){
  37.  /*
  38.     Set global values;
  39.   */
  40.  tim.tv_sec = 0;
  41.  tim.tv_nsec = 50000;
  42.  
  43.  sim.tv_sec = 0;
  44.  sim.tv_nsec = 50000;
  45.  values_do = 0;
  46.  values_pad = 0;
  47.  values_length = 0;
  48.  values_leaked = 0;
  49.  values_enc = (char*) malloc(48);
  50.  values_leak = (char*) malloc(48);
  51.  crear_server();  //create child "server"
  52.  
  53.  //This main process is the client
  54.  int i,j,k,entrar;
  55.  char *secret,*temp,*try_enc;
  56.  char *decrypted;
  57.  unsigned char GUESS;
  58.  secret = (char*) malloc(48);
  59.  try_enc = (char*) malloc(48);
  60.  decrypted = (char*) malloc(16);
  61.  memset(decrypted,0,16);
  62.  do  {  
  63.    sleep(1);
  64.  }while(values_leaked==0); //We need to wait to the leaked data
  65.  
  66.  memcpy(secret,values_leak,48);
  67.  
  68.  temp = tohex(secret,48);
  69.  printf("process_client: leaked is %s\n",temp);
  70.  free(temp);
  71.  i = 0;
  72.  j = 0;
  73.  while(i < 16)  {
  74.    memcpy(try_enc,secret,32);
  75.  
  76.    pthread_mutex_lock(&mtx_values);
  77.    switch(values_do)  {
  78.      case 0:
  79.        GUESS = j;
  80.        decrypted[15-i] = GUESS;
  81.        for(k = 0; k <= i;k++)  {
  82.          try_enc[15-k] = try_enc[15-k] ^ decrypted[15-k] ^ (unsigned char)(i+1);
  83.        }
  84.  
  85.        values_do = 1;
  86.        values_length = 32;
  87.        memcpy(values_enc,try_enc,32);
  88.      break;
  89.      case 1:
  90.      break;
  91.      case 2:
  92.        if(values_pad)  {
  93.          i++;
  94.          printf("Encontrado valor: %c : %.2x\n",GUESS,GUESS);
  95.          j = 0;
  96.        }
  97.        else  {
  98.          j++;
  99.        }
  100.        values_do = 0;
  101.      break;
  102.    }
  103.    pthread_mutex_unlock(&mtx_values);
  104.    nanosleep(&tim , &tim2);
  105.  }
  106.  printf("Decrypted data: %s\n",decrypted);
  107.  
  108. }
  109.  
  110. void *process_server(void *vargp)  {
  111.  AES256_ctx ctx;
  112.  FILE *urandom;
  113.  const char *secret = "The password is: Ywgo/@g:2$0Qsz<";
  114.  char *key,*dec,*enc,*iv,*temp;
  115.  int length,i,pad_valid,outlen;
  116.  unsigned char pad;
  117.  key = (char*) malloc(32);
  118.  dec = (char*) malloc(48);
  119.  enc = (char*) malloc(48);
  120.  iv  = (char*) malloc(16);
  121.  urandom = fopen("/dev/urandom","rb");
  122.  fread(key,1,32,urandom);
  123.  fread(iv,1,16,urandom);
  124.  fclose(urandom);
  125.  
  126.  AES256_init(&ctx,(const unsigned char*) key);
  127.  
  128.  /* LEAK THE secret */
  129.  pthread_mutex_lock(&mtx_values);
  130.  memset(enc,0,48);
  131.  
  132.  
  133.  outlen = MyCBCEncrypt(&ctx, (const unsigned char*) iv, (const unsigned char*) secret, strlen(secret), true, (unsigned char*) enc);
  134.  
  135.  memcpy(values_leak,enc,outlen);
  136.  values_leaked = 1;
  137.  pthread_mutex_unlock(&mtx_values);
  138.  /*END LEAK*/
  139.  
  140.  do  {
  141.    nanosleep(&sim , &sim2);
  142.    pthread_mutex_lock(&mtx_values);
  143.    if(values_do == 1)  {
  144.      length = values_length;
  145.      pad_valid = 0;
  146.      if(length <= 48)  {
  147.        memcpy(enc,values_enc,length);
  148.  
  149.        outlen = MyCBCDecrypt(&ctx,( const unsigned char*) iv, (const unsigned char*) enc, length, true, (unsigned char*) dec);
  150.        if(outlen > 0)  {
  151.          pad_valid =  1;
  152.          printf("Decrypted data seems legit : %i bytes\n",outlen);
  153.          temp = tohex(dec,length);
  154.          printf("Decrypted data %s\n",temp);
  155.          free(temp);
  156.        }
  157.        else  {
  158.          printf("Decrypted data doesnt seems legit\n",outlen);
  159.          temp = tohex(dec,length);
  160.          printf("Decrypted data %s\n",temp);
  161.          free(temp);
  162.        }
  163.      }
  164.      values_do = 2;
  165.      values_pad = pad_valid;
  166.    }
  167.    pthread_mutex_unlock(&mtx_values);
  168.  }while(1);
  169.  pthread_exit(NULL);
  170. }
  171.  
  172. void crear_server()  {
  173.  int s;
  174.  pthread_t tid;
  175.  pthread_attr_t attr;
  176.  s = pthread_attr_init(&attr);
  177.  if (s != 0)  {
  178.    perror("pthread_attr_init");
  179.    exit(6);
  180.  }
  181.  s = pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
  182.  if(s != 0)  {
  183.    perror("pthread_attr_setstacksize");
  184.    exit(8);
  185.  }
  186.  s = pthread_create(&tid,&attr,process_server,NULL);
  187.  if(s != 0)  {
  188.    perror("pthread_create");
  189.  }
  190.  pthread_attr_destroy(&attr);
  191. }
  192.  
  193. char *tohex(char *ptr,int length){
  194.  char *buffer;
  195.  int offset = 0;
  196.  unsigned char c;
  197.  buffer = (char *) malloc((length * 2)+1);
  198.  for (int i = 0; i <length; i++) {
  199.  c = ptr[i];
  200.  sprintf((char*) (buffer + offset),"%.2x",c);
  201.  offset+=2;
  202.  }
  203.  buffer[length*2] = 0;
  204.  return buffer;
  205. }
  206.  
  207.  
  208. int MyCBCDecrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
  209. {
  210.  int written = 0;
  211.  bool fail = false;
  212.  const unsigned char* prev = iv;
  213.  if (!data || !size || !out)
  214.    return 0;
  215.  if (size % AES_BLOCKSIZE != 0)
  216.    return 0;
  217.  while (written != size) {
  218.    AES256_decrypt(ctx, 1, out, data + written);
  219.    for (int i = 0; i != AES_BLOCKSIZE; i++)
  220.      *out++ ^= prev[i];
  221.    prev = data + written;
  222.    written += AES_BLOCKSIZE;
  223.  }
  224.  if (pad) {
  225.    unsigned char padsize = *--out;
  226.    fail = !padsize | (padsize > AES_BLOCKSIZE);
  227.    padsize *= !fail;
  228.    for (int i = AES_BLOCKSIZE; i != 0; i--)
  229.      fail |= ((i > AES_BLOCKSIZE - padsize) & (*out-- != padsize));
  230.    written -= padsize;
  231.  }
  232.  return written * !fail;
  233. }
  234.  
  235. int MyCBCEncrypt(AES256_ctx *ctx, const unsigned char iv[AES_BLOCKSIZE], const unsigned char* data, int size, bool pad, unsigned char* out)
  236. {
  237.  int written = 0;
  238.  int padsize = size % AES_BLOCKSIZE;
  239.  unsigned char mixed[AES_BLOCKSIZE];
  240.  
  241.  if (!data || !size || !out)
  242.    return 0;
  243.  
  244.  if (!pad && padsize != 0)
  245.    return 0;
  246.  
  247.  memcpy(mixed, iv, AES_BLOCKSIZE);
  248.  
  249.  // Write all but the last block
  250.  while (written + AES_BLOCKSIZE <= size) {
  251.    for (int i = 0; i != AES_BLOCKSIZE; i++)
  252.      mixed[i] ^= *data++;
  253.    AES256_encrypt(ctx, 1, out + written, mixed);
  254.    memcpy(mixed, out + written, AES_BLOCKSIZE);
  255.    written += AES_BLOCKSIZE;
  256.  }
  257.  if (pad) {
  258.    // For all that remains, pad each byte with the value of the remaining
  259.    // space. If there is none, pad by a full block.
  260.    for (int i = 0; i != padsize; i++)
  261.      mixed[i] ^= *data++;
  262.    for (int i = padsize; i != AES_BLOCKSIZE; i++)
  263.      mixed[i] ^= AES_BLOCKSIZE - padsize;
  264.    AES256_encrypt(ctx, 1, out + written, mixed);
  265.    written += AES_BLOCKSIZE;
  266.  }
  267.  return written;
  268. }
  269.  


Saludos!


« Última modificación: 20 Noviembre 2020, 19:11 por AlbertoBSD » En línea

Donaciones 15FZZ2fLGR1NydCKHJMw76UZ9SqvFRkxqE
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Anatomy of xss attack
Nivel Web
kamsky 6 3,731 Último mensaje 11 Enero 2010, 02:17
por WHK
[ORACLE-JAVA] java.lang.ClassNotFoundException: oracle.jdbc.driver.OracleDriver
Java
abrtx 2 5,633 Último mensaje 21 Junio 2011, 15:35
por abrtx
padding adentro css ¬¬
Desarrollo Web
Kase 2 2,209 Último mensaje 28 Julio 2011, 06:40
por Oblivionlight
Implementación de let en ES5?
Desarrollo Web
@XSStringManolo 6 606 Último mensaje 17 Diciembre 2019, 05:08
por @XSStringManolo
El patron de padding en la data descifrada es normal?
Criptografía
AlbertoBSD 3 396 Último mensaje 4 Noviembre 2020, 20:43
por [D]aniel
Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines