-
Notifications
You must be signed in to change notification settings - Fork 1
/
execbot.py
196 lines (167 loc) · 7.22 KB
/
execbot.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
# -*- coding: utf-8 -*-
# execbot.py
# ExecBot - Executing bot
# ==============================
#
# Copyright (C) 2018 Giap Tran <[email protected]>
# https://github.com/txgvnn/weechat-execbot
#
# == About =====================
# Execbot is a bot can execute the command from IRC message
# (You maybe want to call it is a kind of backdoor)
#
# With server is installed execbot script, the client can execute the
# command remote by send privmsg to server's nick in IRC network
#
# == Usage =====================
# /excebot list List server.nicknames are allowed
# /execbot add -server <server> nicknames.. Add server.nicknames are allowed to execute
# /execbot del -server <server> nicknames.. Remove server.nicknames are allowed
#
# == NOTICE ====================
# This is a POC that I want to execute a remote command via IRC
# network. It's really not security, although you can set who can
# talk with the bot.
# Should setup with https://weechat.org/scripts/source/ircrypt.py.html
#
# PLEASE CONSIDER CAREFULLY WHEN USING THE PLUGIN
import weechat
SCRIPT_NAME = 'execbot'
SCRIPT_AUTHOR = 'Giap Tran <[email protected]>'
SCRIPT_VERSION = '1.1.1'
SCRIPT_LICENSE = 'GPL3'
SCRIPT_DESC = 'Executing bot'
SCRIPT_HELP_TEXT = '''
%(bold)sExecbot command options: %(normal)s
list List nicknames
add -server <server> <nicknames...> Add server.nicknames are allowed to execute
del -server <server> <nicknames...> Del server.nicknames are allowed
%(bold)sExamples: %(normal)s
Allow john and jack in oftc server to talk with bot
/execbot add -server oftc john jack
''' % {'bold':weechat.color('bold'), 'normal':weechat.color('-bold')}
execbot_config_file = None
execbot_config_section = {}
execbot_allows = {}
def execbot_config_init():
'''Init configuration file'''
global execbot_config_file
execbot_config_file = weechat.config_new('execbot', 'execbot_config_reload_cb', '')
if not execbot_config_file:
return
execbot_config_section['allows'] = weechat.config_new_section(
execbot_config_file, 'allows', 0, 0, 'execbot_config_allows_read_cb', '',
'execbot_config_allows_write_cb', '', '', '', '', '', '', '')
if not execbot_config_section['allows']:
weechat.config_free(execbot_config_file)
def execbot_config_reload_cb(data, config_file):
'''Handle a reload of the configuration file.'''
global execbot_allows
execbot_allows = {}
return weechat.config_reload(config_file)
def execbot_config_allows_read_cb(data, config_file, section_name, option_name, value):
'''Read elements of the allows section from the configuration file.'''
execbot_allows[option_name.lower()] = value
return weechat.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
def execbot_config_allows_write_cb(data, config_file, section_name):
'''Write infomation to the allows section of the configuration file.'''
weechat.config_write_line(config_file, section_name, '')
for username, right in sorted(list(execbot_allows.items())):
weechat.config_write_line(config_file, username.lower(), right)
return weechat.WEECHAT_RC_OK
def execbot_config_read():
''' Read Execbot configuration file (execbot.conf).'''
return weechat.config_read(execbot_config_file)
def execbot_config_write():
''' Write Execbot configuration file (execbot.conf) to disk.'''
return weechat.config_write(execbot_config_file)
def execbot_command_list():
'''List server.nicknames are allowed.'''
nicknames = '\n'.join([' %s' % x for x in execbot_allows.keys()])
# for nickname,_ in sorted(list(execbot_allows.items())):
weechat.prnt(weechat.current_buffer(), 'Nicknames are allowed:\n' +nicknames)
return weechat.WEECHAT_RC_OK
def execbot_command_add(server,nicknames):
'''Add nicknames.'''
for x in nicknames:
execbot_allows['%s.%s'%(server,x.lower())] = 'allow'
weechat.prnt(weechat.current_buffer(),'Add permission for %s' % '%s.%s'%(server,x.lower()))
return weechat.WEECHAT_RC_OK
def execbot_command_del(server,nicknames):
'''Remove nicknames.'''
for x in nicknames:
try:
del execbot_allows['%s.%s'%(server,x.lower())]
weechat.prnt(weechat.current_buffer(),'Deleted permission of %s' % '%s.%s'%(server,x.lower()))
except KeyError:
weechat.prnt(weechat.current_buffer(),'No existing %s.%s'%(server,x.lower()))
return weechat.WEECHAT_RC_OK
def execbot_command(data, buffer, args):
'''Hook to handle the /execbot weechat command.'''
argv = args.split()
# list
if not argv or argv == ['list']:
return execbot_command_list()
# check if a server was set
if (len(argv) > 2 and argv[1] == '-server'):
server = argv[2]
del argv[1:3]
args = (args.split(' ', 2)+[''])[2]
else:
server = weechat.buffer_get_string(buffer, 'localvar_server')
if not server:
weechat.prnt(weechat.current_buffer(), 'Required -server option')
return weechat.WEECHAT_RC_ERROR
# add
if argv[:1] == ['add']:
if len(argv) < 2:
return weechat.WEECHAT_RC_ERROR
return execbot_command_add(server,argv[1:])
# del
if argv[:1] == ['del']:
if len(argv) < 2:
return weechat.WEECHAT_RC_ERROR
return execbot_command_del(server,argv[1:])
execbot_error('Unknown command. Try /help execbot', buffer)
return weechat.WEECHAT_RC_OK
def execbot_process(buffer, command, return_code, out, err):
'''Execute the command and return to buffer.'''
message = "%s ... | $? = %d\n" % (command.split()[0], return_code)
if out != "":
message += out
if err != "":
message += err
weechat.command(buffer, message)
return weechat.WEECHAT_RC_OK
def execbot_hook_signal(data, signal, signal_data):
server = signal.split(",")[0]
info = weechat.info_get_hashtable("irc_message_parse", { "message": signal_data })
username = '.'.join([server,info['nick']])
# Check the permission
allowed = execbot_allows.get(username.lower())
if not allowed:
return weechat.WEECHAT_RC_OK
# Prevent public channel
if info['channel'].startswith('#'):
return weechat.WEECHAT_RC_OK
# buffer output
buffer = weechat.buffer_search("irc", username)
# command
_, command = info['arguments'].split(':', 1)
# timeout = 5 mins
weechat.hook_process(command, 300000, "execbot_process", buffer)
return weechat.WEECHAT_RC_OK
def execbot_unload_script():
execbot_config_write()
return weechat.WEECHAT_RC_OK
if __name__ == '__main__' and weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR,
SCRIPT_VERSION, SCRIPT_LICENSE, SCRIPT_DESC, 'execbot_unload_script','UTF-8'):
execbot_config_init()
execbot_config_read()
weechat.hook_command('execbot', 'Commands to manage Execbot options and execute Execbot commands',
'',
SCRIPT_HELP_TEXT,
'list %- || add -server %(irc_servers) %(nicks) %-'
'|| del -server %(irc_servers) %(nicks) %-',
'execbot_command', '')
weechat.hook_signal("*,irc_in2_privmsg", "execbot_hook_signal", "")