Ash框架授权绕过漏洞分析:CVE-2025-48044
概述
Ash(一个Erlang/Elixir应用程序框架)在3.6.3至3.7.0版本中存在一个授权绕过漏洞。当Bypass策略的条件评估为true,但其内部的授权检查失败,且没有其他适用策略时,系统可能错误地授权本应被拒绝的请求。
受影响版本
- 受影响版本:>= 3.6.3, <= 3.7.0
- 已修复版本:3.7.1
漏洞详情
漏洞位置
漏洞代码位于:lib/ash/policy/policy.ex:69
1
2
3
4
5
|
{%{bypass?: true}, cond_expr, complete_expr}, {one_condition_matches, all_policies_match} ->
{
b(cond_expr or one_condition_matches), # <- 漏洞:仅使用了条件表达式
b(complete_expr or all_policies_match)
}
|
漏洞原理
最终的授权决策逻辑为:one_condition_matches AND all_policies_match。
当一个Bypass策略的条件为真但授权失败,且后续策略的条件不匹配时:
one_condition_matches = cond_expr (Bypass条件) = true (漏洞点:本应检查Bypass是否真正授权)
- 对于不匹配的策略:
all_policies_match 的计算结果为 true(因为策略不适用)
最终得到:true AND true = true(被错误授权)。
核心问题:仅Bypass条件满足就足以让系统认为“至少有一个策略适用”,即使该Bypass策略本身未能成功授权。
修复方案
将第69行的cond_expr替换为complete_expr:
1
2
3
4
5
|
{%{bypass?: true}, _cond_expr, complete_expr}, {one_condition_matches, all_policies_match} ->
{
b(complete_expr or one_condition_matches), # <- 已修复
b(complete_expr or all_policies_match)
}
|
为了保持一致性,第52行也应更新(尽管在实践中,仅当Bypass是最后一个策略时才会触发,使其偶然安全):
1
2
3
4
5
|
{%{bypass?: true}, _cond_expr, complete_expr}, {one_condition_matches, true} ->
{
b(complete_expr or one_condition_matches), # <- 为保持一致性
complete_expr
}
|
概念验证(PoC)
以下策略配置展示了该漏洞:
1
2
3
4
5
6
7
8
9
|
policies do
bypass always() do
authorize_if actor_attribute_equals(:is_admin, true)
end
policy action_type(:read) do
authorize_if always()
end
end
|
在此配置下,非管理员用户可以执行创建操作(本应被拒绝)。
测试代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
test "bypass policy bug" do
policies = [
%Ash.Policy.Policy{
bypass?: true,
condition: [{Ash.Policy.Check.Static, result: true}], # 条件 = true
policies: [
%Ash.Policy.Check{
type: :authorize_if,
check: {Ash.Policy.Check.Static, result: false}, # 策略 = false
check_module: Ash.Policy.Check.Static,
check_opts: [result: false]
}
]
},
%Ash.Policy.Policy{
bypass?: false,
condition: [{Ash.Policy.Check.Static, result: false}],
policies: [
%Ash.Policy.Check{
type: :authorize_if,
check: {Ash.Policy.Check.Static, result: true},
check_module: Ash.Policy.Check.Static,
check_opts: [result: true]
}
]
}
]
expression = Ash.Policy.Policy.expression(policies, %{})
assert expression == false
# 期望结果:false (拒绝)
# 主分支上的实际结果:true (错误授权)
end
|
安全信息
- 严重等级:高
- CVSS 4.0 评分:8.6 (AV:N/AC:L/AT:N/PR:L/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N)
- CWE分类:CWE-863 - 不正确的授权
参考链接