Vulnerabilidades en programas BATCH

Iniciado por sirdarckcat, 11 Junio 2007, 02:49 AM

0 Miembros y 1 Visitante están viendo este tema.

sirdarckcat


   Vulnerabilidades en programas BATCH


Dado que recientemente me he dado cuenta de que las aplicaciones remotas
estan usando cada vez mas aplicaciones BATCH, (de las cuales yo he hecho
varias), para generar herramientas, con las cuales se cree que su uso es
seguro, he decidido escribir este documento sobre las vulnerabilidades en
estos programas, para que se reconsidere su uso en su futuro.
Estas vulnerabilidades, las he nombrados segun su semejanza con vulnera-
bilidades a nivel web, las cuales son BATCH Injection y BATCH Command
Execution.







      BATCH Injection







Los que estén familiarizados con la seguridad a nivel web, seguramente
conocerán el término SQL Injection, o LDAP Injection, que nos permite
ejecutar sentencias SQL (o LDAP) en un interprete.
Mientras que estos ataques (especialmente SQLi), ya han sido ampliamente
estudiados, existe una variable, a la cual he llamado, BATCH Injection.
basándonos en el mismo princípio en el cual se basan las vulnerabílidades
de SQL Injection, el cual es insertar comandos extra, en una sentencia
con el uso de una variable comprometída, BATCH injection, nos permite
ejecutar comandos en un programa BATCH, que acepte alguna variable por
medio de el comando SET, o a travez de argumentos.

Puede que piensen que este ataque no es un vector de ataque remoto, pero
temo decirles que estan en un error. Aunque son pocas, existen programas
en los cuales, parte del código, utiliza BATCH, normalmente, para tareas
de administración via telnet. Un ejemplo, es el archivo en WindowsNT,
C:\WINNT\system32\login.cmd el cual aunque solo es una pantalla de
bienvenida, la cual nos da shell sin tener que vulnerar nada, demuestra
que el uso de archivos BATCH en tareas de administración telnet, es muy
común. Podemos ver el contenido a continuación:
>> type C:\WINNT\system32\login.cmd
   @echo off
   rem
   rem  Secuencia de comandos global predeterminada del inicio de sesión
   rem  para servidor Telnet
   rem
   rem  En la instalación predeterminada, esta secuencia de comandos es
   rem  ejecutada cuando se ejecuta el comando inicial shell.  A cambio,
   rem  intentará invocar la secuencia de comandos del inicio de sesión
   rem  del usuario individual.
   rem

   echo *===============================================================
   echo Bienvenido al servidor Telnet de Microsoft.
   echo *===============================================================

   cd %HOMEDRIVE%%HOMEPATH% /d


Como podémos ver, no es necesário vulnerar nada, dado que se nos da acceso
inmediatamente a una shell, sinembargo, que tal que alguien, en un vago
intento de "asegurar" este código (alguien que no sabe configurar el
servidor telnet), tratará de reescribir este código a algo similar a:
>> copy con: login.cmd
   @echo off
   echo Bienvenido al sistema de administración via telnet.
   set /P pass=Por favor ingresa tu contraseña:
   if "%pass%"=="secreto" (
           echo PASSWORD CORRECTO
   ) else (
           echo PASSWORD INCORRECTO
           call %~nx0
   )
   ^Z
           1 archivos copiados.

Se espera que el lector ya entienda la programación en BATCH.
en este caso, al ejecutar el comando, nos dará:
>> login.cmd
   Bienvenido al sistema de administración via telnet.
   Por favor ingresa tu contraseña: incorrecto
   PASSWORD INCORRECTO
   Bienvenido al sistema de administración via telnet.
   Por favor ingresa tu contraseña: secreto
   PASSWORD CORRECTO

Mientras no escriba el password correcto, el codigo se volverá a llamar
a si mismo, de esta forma se asegura de que hasta que el usuario envie
el password correcto, no pasará de esa pantalla.
Ahora, debemos entender como funciona el parser de BATCH en Windows.
cuando nosotros escribimos en un código BATCH, algo como..
>> echo %LANG%
   es

El parser de batch, detecta la variable LANG, y la reemplaza por su
valor, es decir.. si hacemos algo como..
>> set cmd=ver
   
>> %cmd%

   Microsoft Windows 2000 [Versión 5.00.2195]

Lo que hace es reemplazar %cmd% por "ver", y ejecutar "ver". Ahora que
sabemos eso, nos debemos dar cuenta de que, por ejemplo, si tenemos un
programa asi:
>> copy con: prueba.bat
   @echo off
   set /P nombre=¿Como te llamas?
   echo Tu te llamas %nombre%
   ^Z
           1 archivos copiados.

Nosotros podémos hacer que se guarde el resultado en un archivo, de la
siguiente forma:
>> prueba
   ¿Como te llamas? sirdarckcat > salida.txt

Como vimos, la salida del comando, no se mostro, lo que si hubiera pasado
si solo hubieramos puesto el nombre.. mira:
>> prueba
   ¿Como te llamas? sirdarckcat
   Tu te llamas sirdarckcat

Y podemos comprobar que el archivo se escribió
>> type salida.txt
   Tu te llamas sirdarckcat

En fin, no solo podemos redirigir la salida de comandos, tambien podemos
ejecutar nuestros propios comandos, con el símbolo &
>> prueba
   ¿Como te llamas? sirdarckcat & ver
   Tu te llamas sirdarckcat
   
   Microsoft Windows 2000 [Versión 5.00.2195]

Interesante no? para ahora, ya te debes haber dado cuenta que nuestro
script login.cmd es vulnerable a algo.. y si, tienes razón.
>> login
   Bienvenido al sistema de administración via telnet.
   Por favor ingresa tu contraseña: "=="" ( REM
   PASSWORD CORRECTO

Te preguntarás que paso aquí.. porque me dijo PASSWORD CORRECTO? si yo
no sabía el password.. para eso, solo debemos de editar nuestro @echo off
>> copy con: login.cmd
   @echo on
   ¿Sobrescribir login.cmd? (Sí/No/Todo): t
   echo Bienvenido al sistema de administración via telnet.
   set /P pass=Por favor ingresa tu contraseña:
   if "%pass%"=="secreto" (
           echo PASSWORD CORRECTO
   ) else (
           echo PASSWORD INCORRECTO
           call %~nx0
   )
   ^Z
           1 archivos copiados.

veamos:
>> login

   >> echo Bienvenido al sistema de administración via telnet.
      Bienvenido al sistema de administración via telnet.

   >> set /P pass=Por favor ingresa tu contraseña:
      Por favor ingresa tu contraseña:"=="" ( REM

   >> if "" == "" (
      REM "=="secreto" (
       echo PASSWORD CORRECTO
      )  else (
      echo PASSWORD INCORRECTO
       call login.cmd
      )
      PASSWORD CORRECTO

Lo que hace REM, es comentar una linea, es decir, ignora todo lo que
esté despues de este, es el equivalente a "--" en MSSQL y a "/*" en mysql







      BATCH Command Execution







Al igual que BATCH Injection, supongamos que queremos que un programa
al cual aparentemente no podemos hacer nada, aun con el password correcto
ejecute un comando, como por ejemplo.. nos de una shell.. esto se puede
hacer con "&" (y despues veremos como con "|")
>> prueba
   ¿Como te llamas? eduardo&cmd
   Tu te llamas eduardo
   Microsoft Windows 2000 [Versión 5.00.2195]
   (C) Copyright 1985-2000 Microsoft Corp.
   
   >> exit

Como vimos, simplemente con &cmd, podemos ejecutar comandos, ahora ya
pensarás que solo hay que filtrarlo.. pues, filtremoslo.
>> copy con: prueba_seguro.bat
   @echo off
   set /P nombre=¿Como te llamas?
   set nombre=%nombre:&=_%
   set nombre=%nombre:>=_%
   set nombre=%nombre:<=_%
   set nombre=%nombre:|=_%
   set nombre=%nombre:"=_%
   echo Tu nombre es %nombre%
   ^Z
           1 archivos copiados.

>> prueba_seguro
   ¿Como te llamas? eduardo&cmd
   Tu nombre es eduardo_cmd

>> prueba_seguro
   ¿Como te llamas? eduardo|start /B cmd /K REM

   >>
>> Tu nombre es eduardo_start /B cmd /K REM
   
>> >> >>
Hey! que paso ahi? bueno, como ya te dije antes, cmd cambia las variables
por su contenido, es decir.. cuando hacemos, set nombre=%nombre:&=_%
el | es ejecutado.. por lo que CMD lee..
>> set nombre=eduardo|start /B cmd /K REM

>>
Lo que hace que salga 1 linea extra, aunque nada ahí es ejecutado.
ahora, tenemos todavia la posibilidad de ejecutar cosas con |
pero, que? cualquier comando, veremos su salida, pero yo quiero una shell
y para eso, haremos lo siguiente..
>> prueba_seguro
   ¿Como te llamas? &cmd ^
   Microsoft Windows 2000 [Versión 5.00.2195]
   (C) Copyright 1985-2000 Microsoft Corp.
   
   >> exit
   Microsoft Windows 2000 [Versión 5.00.2195]
   (C) Copyright 1985-2000 Microsoft Corp.
   
   >> exit
   Microsoft Windows 2000 [Versión 5.00.2195]
   (C) Copyright 1985-2000 Microsoft Corp.
   
   >> exit
   Microsoft Windows 2000 [Versión 5.00.2195]
   (C) Copyright 1985-2000 Microsoft Corp.
   
   >> exit

Esto: "&cmd ^" abrió 4 cmd.. porque? porque el caracter "^" quita lo que
esté despues de el, en este caso, un salto de línea.. por lo que al final
cmd interpreta..

set nombre=_cmd set nombre=  & cmd set nombre=  & cmd set nombre=  & cmd
   echo Tu nombre es   & cmd

Ahora porque no se filtra el caracter ^ tambien?
La respuesta es porque ese debería ser el caracter a filtrar primero
ya que de lo contrario, arrastra a todos los demas filtros, pero si ese
es el primero en filtrarse, entonces podríamos usar & para abrir una
shell.

Una manera de solucionar eso, es colocando un espacio en cada linea.

>> copy con: prueba_mas.bat
   @echo off
   set /P nombre=¨Como te llamas?
   set nombre=%nombre:&=_%
   set nombre=%nombre:>=_%
   set nombre=%nombre:<=_%
   set nombre=%nombre:|=_%
   echo Tu nombre es %nombre%
   ^Z
           1 archivos copiados.

De esta forma.. el ^ solo cancelará un espacio, en ves de un salto de linea
y aun asi, despues de tanto, aun podemos hacer una shell.. ya que SET al ser
canalizado, no guarda el valor, es decir.. si decimos:
>> set dia=1|echo.
   dia no valdra nada:
>> echo %dia%
   %dia%
Asi que.. para poder detener el uso de &, ese debe ser el caracter filtrado
primero, pero el caracter | puede anular los filtros, asi que ese tambien
debe ser anulado primero, asi que un filtro en batch es irreal.. lo que
se debe hacer, es no usar variables (manipulables por el usuario) en forma
%var%, ya que siempre es posible ejecutar comandos asi, la forma correcta
es la siguiente:
>> copy con: seguro.bat
   @echo off
   set /P nombre=Escribe tu nombre:
   set | find "nombre="
   ^Z
           1 archivos copiados.

>> seguro
   Escribe tu nombre: cmd|cmd&cmd^
   nombre=cmd|cmd&cmd^

Para concluir solo quiero decirles, que BATCH solo debe ser usado para
automatizar tareas, nunca para una interacción remota, a menos que en
el código NUNCA se usen variables expandibles.. Hasta hoy, no he encontrado
un filtro realmente seguro, usando FOR's, FIND, canalizaciones, etc. siempre
hay alguna forma de ejecutar algun comando, por lo que no se debe usar BATCH
en un entorno inseguro.

  Copyright (c) 2007 sirdarckcat@gmail.com
  Permission is granted to copy, distribute and/or modify this document
  under the terms of the GNU Free Documentation License, Version 1.2
  or any later version published by the Free Software Foundation;
  with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
  Texts.  A copy of the license is available at:
   http://www.gnu.org/licenses/fdl.html

ne0x

Muy bueno,ya me habia dado cuenta de esto y pensaba en hacer algun documento parecido pero este esta muy bien, ya explote una vulnerabilidad asi... xD

Habia uno que combinando netcat y batch hizo un chat, cuando te pide el nick para entrar, o cuando escribes lo que quieres decir usaba "&".


zhynar_X

Hola, es muy bueno el manual. Me ha gustado mucho y esta muy bien explicado

Saludos
Me he creado un blog:
http://zhynar.blogspot.com  Aver si os gusta! ;)


Optimista es aquel que cree poder resolver un atasco de trafico tocando el claxon (Anonimo)

sirdarckcat

#3
Bueno, les dejo un filtro, que segun parece es bastante seguro.. lo hice hace ratop :P


@echo off
:: filtbat, filtro de variables batch
echo Escribe tu password:
((echo E 100 B9 48 01 41 B4 01 CD 21 89 CF 90 3C 30 7C 23 90 & echo E 110 3C 7A 7F 1E 90 3C 3C 74 19 90 3C 3E 74 14 90 3C & echo E 120 5E 74 0F 88 05 81 E9 48 01 83 F9 20 81 C1 48 01 & echo E 130 75 D1 BA 48 01 89 D7 B0 0A 88 05 89 CF B0 24 88 & echo E 140 05 B4 09 CD 21 CD 20 24 75 & echo N filtbat.com & echo RCX  & echo 148 & echo W  & echo Q & echo.) | debug ) > nul
FOR /F "tokens=1* skip=1" %%i IN ('filtbat') DO (
call:ready %%i
)
goto:EOF
:ready
if "%~1"=="prueba" (
echo OK!
) else (
echo ERROR!
)


solo acepta caracteres alfanumericos..y unos cuantos mas..

Saludos!!

0x0309

Sirdarckcat, creo que por fin el tema de las batch injections es cosa del pasado:

Aquí la versión 2.0 de la función clean.
http://foro.elhacker.net/scripting/batch_funcion_clean_20-t254050.0.html

Nota: Disculparme por favor por responder un tema con más de 60 días sin respuestas.

sirdarckcat

Creo que sera cosa del pasado cuando sea arreglado directamente en CMD de windows, usar una funcion de limpieza es una medida defensiva, pero el problema sigue ahi.

saludos!!

leogtz

Código (perl) [Seleccionar]

(( 1 / 0 )) &> /dev/null || {
echo -e "stderrrrrrrrrrrrrrrrrrr";
}

http://leonardogtzr.wordpress.com/
leogutierrezramirez@gmail.com