¿Es peligroso pasar la entrada del usuario a la función requerida en Node.js?

1

TL; DR: ¿Es peligroso que las entradas del usuario se usen en una función requerida en Node.js? ¿Se puede usar para leer archivos y, de ser así, cómo puedo protegerme contra eso?

Por ejemplo, tengo un servidor ExpressJS en ejecución, con una API. El cliente puede realizar una llamada a /api/login , que luego se requiere como ./api/login(.coffee) :

require('coffee-script')
app = require('express')()

app.all '/api/:func?', (req, res) ->
  # Get API function
  func = req.params.func

  # Check if file exists
  fs = require 'fs'
  fs.access "./api/#{func}.coffee", fs.F_OK & fs.R_OK, (err) ->
    if err
      # Send error when invalid call
      api = require('./api/error')
    else
      # !!! Injection ?
      api = require('./api/' + func)

    # Call API
    api(req, res)

Supongo que, por ejemplo, no se puede enviar una solicitud a http://example.net/api/../../../etc/passwd , pero solo lo probé en mi navegador y no estoy seguro de si mi navegador lo maneja. Además de eso, creo que lo peor que podría pasar es que Node se bloquee porque no puede requerir ese archivo.

¿Hay algún problema de seguridad aquí y cómo bloquearía tales ataques?

    
pregunta Charlie 08.06.2016 - 21:18
fuente

3 respuestas

2

Si permite que los usuarios requieran archivos inesperados, obtendrá un comportamiento inesperado. Si bien puede no ser obvio cómo un atacante podría explotar eso para algo útil, es imposible predecir las consecuencias. Eso es malo.

Como mínimo, se abre una vulnerabilidad DoS, ya que un usuario puede bloquear Node fácilmente y forzar un reinicio. Unas pocas solicitudes como esa por segundo y usted está fuera del negocio. En el peor de los casos ... ¿quién sabe?

Entonces, ¿cuál es la solución? Veo dos posibles enfoques:

  1. Lista blanca. Tenga una matriz con nombres de archivos permitidos y asegúrese de que func esté en esa matriz antes de que la necesite.
  2. Asegúrese de permanecer en la carpeta de la API y asegúrese de que todos los archivos allí se puedan incluir de forma segura. Para saber cómo hacerlo, consulte esto cuestión mía .
respondido por el Anders 08.06.2016 - 21:29
fuente
1

Nunca debe usar los requisitos dinámicos, a menos que haya saneado mucho la entrada (si es posible, en la lista blanca).

Node.js aceptará cualquier extensión de archivo en su llamada requerida. No lo valida para ser un archivo .js, E.g

require('malicious-uploaded-file')

Este 'archivo malicioso subido' podría ser un archivo .png | .jpg lleno de JS malintencionados.

Anteriormente, he explotado esta falla utilizando un sistema de carga de archivos mal escrito (no cambié el nombre de los archivos o no tengo los permisos de direccionamiento correctos) que me permitieron cargar un archivo .png con el código del shell de inversión del nodo. Luego manipulé un requisito dinámico para usar el recorrido de directorios al script cargado.

Ahora, este sistema en particular tenía muchos defectos, pero estos 2 me permitieron tomar el control completo del sistema remoto.

    
respondido por el Trickycm 18.09.2017 - 12:37
fuente
0

Exponer la función require de esta forma es casi tan o tan malo como exponer eval

  • require('./api/good.js');eval('//xkcd.com/327');// < - Inyección de código
  • require('../../../dev/zero') < - DDoS
  • require('../../../var/upload/bad.js') < - Explotación remota
  • require('../../../opt/proprietary-package/proprietary-code.js') < - Malo
respondido por el CaffeineAddiction 18.09.2017 - 16:23
fuente

Lea otras preguntas en las etiquetas