2008-10-09 15 views
5

Necesito construir dinámicamente una consulta XPath para un atributo de elemento, donde el valor de atributo es proporcionado por el usuario. No estoy seguro de cómo limpiar o desinfectar este valor para evitar el equivalente XPath de un ataque de inyección SQL. Por ejemplo (en PHP):Limpieza/desinfección de los atributos xpath

<?php 
function xPathQuery($attr) { 
    $xml = simplexml_load_file('example.xml'); 
    return $xml->xpath("//myElement[@content='{$attr}']"); 
} 

xPathQuery('This should work fine'); 
# //myElement[@content='This should work fine'] 

xPathQuery('As should "this"'); 
# //myElement[@content='As should "this"'] 

xPathQuery('This\'ll cause problems'); 
# //myElement[@content='This'll cause problems'] 

xPathQuery('\']/../privateElement[@content=\'private data'); 
# //myElement[@content='']/../privateElement[@content='private data'] 

El último de ellos, en particular, es una reminiscencia de los ataques de inyección SQL de antaño.

Ahora, sé de hecho que habrá atributos que contengan comillas simples y atributos que contengan comillas dobles. Dado que estos se proporcionan como argumento para una función, ¿cuál sería la forma ideal de desinfectar la entrada para estos?

Respuesta

-1
function xPathQuery($attr) { 
    $xml = simplexml_load_file('example.xml'); 
    $to_encode = array('&', '"'); 
    $to_replace = array('&amp;','&quot;'); 
    $attr = replace($to_encode, $to_replace, $attr); 
    return $xml->xpath("//myElement[@content=\"{$attr}\"]"); 
} 

Ok, ¿qué hace?

Codifica todas las apariciones de & y "como & amp; y & quot;. En la cadena, que debe dar un selector de seguridad para ese uso particular, Tenga en cuenta que también se sustituye el interior" en el XPath con". EDITAR: Desde entonces se ha señalado que 'se puede escapar como & apos ;, por lo que podría usar el método de comillas de cadena que prefiera.

+0

¿Está pasando por alto quizá '? –

+0

Sí, ese es el que estoy buscando. Hay una lista de todas (5) de las entidades XML aquí: http://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references –

-1

Creé un documento XML de un solo elemento usando un DOM, uso el DOM para establecer el texto del elemento en el valor proporcionado, y luego tomo el texto de la representación de cadena del DOM del XML. Esto garantizará que todo el personaje que se está escapando se haga correctamente, y no solo el personaje que escapa, que estoy pensando en ello de manera directa.

Editar: La razón por la que usaría el DOM en situaciones como esta es que las personas que escribieron el DOM han leído la recomendación XML y yo no (al menos, no con el nivel de cuidado que tienen). Para elegir un ejemplo trivial, el DOM informará un error de análisis si el texto contiene un carácter que XML no permite (como # x8), porque los autores del DOM han implementado la sección 2.2 de la recomendación XML.

Ahora, podría decir: "bueno, obtendré la lista de caracteres no válidos de la recomendación XML y los eliminaré de la entrada". Por supuesto. Miremos la recomendación XML y ... um, ¿qué diablos son los bloques sustitutos Unicode? ¿Qué tipo de código tengo que escribir para deshacerme de ellos? ¿Pueden incluso entrar en mi texto en primer lugar?

Supongamos que lo descubro. ¿Hay otros aspectos de cómo la recomendación XML especifica representaciones de caracteres que no conozco? Probablemente. ¿Estos tendrán un impacto en lo que estoy tratando de implementar? Tal vez.

Si dejo que DOM haga la codificación de caracteres para mí, no tengo que preocuparme por nada de eso.

+0

Esto no funcionará. El dom representará un 'como' –

+0

Sí, lo hará. Si usa .Net DOM, por ejemplo, la propiedad InnerXml de XmlElement devuelve el marcado del texto del elemento. Su propiedad Value se comporta como usted describe. –

+0

Pero él está hablando de PHP, y no veo nada en la (pobre) documentación para respaldar eso. –

5

XPath realmente incluye un método para hacerlo de forma segura, ya que permite variable references en el formato $varname en expresiones. La biblioteca en la que se basa SimpleXML de PHP provides an interface to supply variables, sin embargo, esta is not exposed by the xpath function en su ejemplo.

Como una demostración de verdad lo simple que puede ser:

>>> from lxml import etree 
>>> n = etree.fromstring('<n a=\'He said "I&apos;m here"\'/>') 
>>> n.xpath("@a=$maybeunsafe", maybeunsafe='He said "I\'m here"') 
True 

Eso está usando lxml, un envoltorio de Python para la misma biblioteca subyacente como SimpleXML, con un xpath function similares. Booleanos, números y conjuntos de nodos también se pueden pasar directamente.

Si el cambio a una interfaz de XPath más capaz no es una opción, una solución cuando la cadena externa dada sería algo (no dude en adaptarse a PHP) a lo largo de las líneas de:

def safe_xpath_string(strvar): 
    if "'" in strvar: 
     return "',\"'\",'".join(strvar.split("'")).join(("concat('","')")) 
    return strvar.join("''") 

El valor de retorno puede ser insertado directamente en tu cadena de expresión. Como eso no es realmente muy fácil de leer, aquí es cómo se comporta:

>>> print safe_xpath_string("basic") 
'basic' 
>>> print safe_xpath_string('He said "I\'m here"') 
concat('He said "I',"'",'m here"') 

Nota, no se puede emplear caracteres de escape en la parte exterior forma &apos; de un documento XML, ni son genéricos rutinas de serialización XML aplicable. Sin embargo, la función XPath concat se puede usar para crear una cadena con ambos tipos de comillas en cualquier contexto.

variante de PHP:

function safe_xpath_string($value) 
{ 
    $quote = "'"; 
    if (FALSE === strpos($value, $quote)) 
     return $quote.$value.$quote; 
    else 
     return sprintf("concat('%s')", implode("', \"'\", '", explode($quote, $value))); 
} 
Cuestiones relacionadas