Vulnerabilidades de las inyecciones SQL cuando se utilizan modelos SQL de Zend Framework

15

Al unir tablas, uso modelos SQL de Zend Framework. Como ejemplo, modifiqué mi código real, pero creo que obtendrá el punto:

$this->getSelect()->join(
                      array('sections' => $sectionsTableName),
                      'main_table.banner_id = pages.banner_id',
                      array()
                    )
                  ->where("sections.section= '$section' OR sections.section = '0' OR (sections.section = '6' AND ? LIKE main_table.url)",$url)
                  ->group('main_table.banner_id'); 

La página se carga con ajax y el parámetro $ section se envía como parámetro GET ( www.example.com/controllerName/index/display/3?paremeter1=example&section=www.example2.com).

Ahora aquí está el problema si alguien realiza algo como esto:

www.example.com/controllerName/index/display/3?paremeter1=example&url=(SELECT 3630 FROM(SELECT COUNT(*),CONCAT(0x7170786a71,(SELECT (ELT(3630=3630,1))),0x717a716b71,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.CHARACTER_SETS GROUP BY x)a)

De esta manera, el usuario puede volcar toda la base de datos. Los datos no se mostrarán, pero aún así SQL realizará un volcado que puede causar una sobrecarga de sql.

Preguntas:

  1. ¿Cuál es la mejor manera de prevenir tal escenario?
  2. Ahora estoy preocupado por los clientes anteriores. ¿Es posible con este código realizar aún más acciones de riesgo, como eliminar o alterar la tabla? Supongo que no porque no pueda poner ninguna otra declaración que SELECT dentro de subselect para que DELETE produzca un error de sintaxis sql. Estoy en lo cierto?

ACTUALIZACIÓN: Mi ejemplo no es una ilustración adecuada de la inyección SQL porque hay 'signos alrededor de $ secciones y, por lo tanto, no será posible realizar la inyección. De todos modos, esto sería posible cuando se espera un valor entero y cuando no se filtra la entrada entera. Mira mi comentario a continuación.

JohnyFree
fuente
1
Podrías usar: $db = Mage::getSingleton('core/resource')->getConnection('core_read');e $db->quote()incluso en tu caso mira $db->quoteInto. Si $thises un recurso, que podría hacer: $this->getConnection('core_read')->quoteInto()si se trata de una colección que podría hacer: $this->getResource()->getConnection('core_read')->quoteInto(). Entre esas líneas. Si eso ayuda a guiarte hacia tu objetivo.
ceniza
Me acabo de dar cuenta de que este escenario es posible solo si el valor es entero. Si el valor es varchar, siempre habrá un 'signo antes del (signo y, por lo tanto, (SELECTo cualquier otra cosa será igual que una cadena y no funcionará. Cuando el campo es entero, 'no es necesario y hace posible tal escenario. Pero el entero siempre debe filtrarse, por intval()lo que tampoco es un problema.
JohnyFree
¿Qué pasa si comienzas con cerrar el '? Entonces ' AND (SELECT ...) '? Por cierto, no creo que Zend no esté citando esto ... Y si usa enlaces, PDO se encargará de esto. Simplemente nunca use concatenaciones de picadura como esta:"sections.section= '$section'"
7ochem
@ 7ochem en tal caso, DEBE vincular el parámetro usando? y 'se convertirá en \'. Pero si se utiliza entero de valor, entonces no es para obligar a éste, ya que se puede limpiar usando intval función () php y 'algo se convertirá en 0.
JohnyFree

Respuestas:

8

Validar su entrada!

Tan bueno y tanto como puedas.

Algunas sugerencias para su validación:

  1. Verifique la longitud de la variable que obtiene a través del parámetro GET. No hay necesidad de aceptar una cadena larga interminable.

  2. Validar para un nombre de dominio. ¿Qué tipo de formato tienen sus nombres de dominio esperados? ¿Es siempre www.midominio.tld? Cree una expresión regular que verifique si hay una coincidencia o (mejor) uso Zend_Validate_Hostname:

    $validator = new Zend_Validate_Hostname();
    if ($validator->isValid($hostname)) {
        //hostname is valid - continue
    }
  3. Lista blanca: ¿Sabe qué nombres de dominio esperar? Puede crear una lista de dominios permitidos y verificarlos. Deja el resto.

    $allowedDomains = array('www.domain1.tld','www.domain2.tld');
  4. Lista negra de nombres de dominio y / o caracteres: si espera un nombre de dominio, no es necesario aceptar ningún otro carácter que no sea az y 0-9 y "." (a menos que esté trabajando con nombres de dominio especiales).

Anna Völkl
fuente