forked from FWSquatch/pysel
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathscore.py
444 lines (376 loc) · 15.6 KB
/
score.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
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
s_config = """
[General:Options]
debug = no
scoreReportLocation = /home/ubuntu/Desktop/ScoreReport.html
remoteReportingenabled = no
remoteReportingServer = http://cybertaipan.mensa.org.au
remoteReportingRound = Mensa Training Round
timeLimit = 150
[01-RemoveMcPoyle:Remove_users]
enabled = yes
tag = User Management
pointValue = 3
parameters = mcpoyle
description = Users that should be removed from the system
msg = Unwanted user %PARAMETER% has been removed:
[02-AddMacDee:Add_users]
enabled = yes
tag = User Management
pointValue = 1
parameters = gellert credence
description = Users that need to be added to the system
msg = New user %PARAMETER% added to system
[03-GoodUsers:Required_users]
enabled = yes
tag = User Management
pointValue = -10
parameters = tina albus jacob
description = Users that are required on the system
msg = Essential user %PARAMETER% has been removed!
[04-FrankSudo:Add_to_sudo]
enabled = yes
tag = User Management
pointValue = 2
parameters = tina
description = Users that are required to be Administrators
msg = User %PARAMETER% is now an administrator
[05-DennisNoSudo:Remove_from_sudo]
enabled = yes
tag = User Management
pointValue = 2
parameters = albus
description = Users that are prohibited from being Administrators
msg = User %PARAMETER% is no longer an administrator
[06-CharlieDeeWebDev:Add_to_group]
enabled = yes
tag = User Management
pointValue = 2
parameters = albus:webdev credence:webdev
description = Users that are required to be in a group
msg = User %PARAMETER% is now in group
[6A-WebdevGroupCreated:File_now_contains]
enabled = yes
tag = Local Policy
pointValue = 3
parameters = /etc/group:webdev
description = Text you would like added to file
msg = Group webdev has been created
[07-DisableGuestEtc:Secure_lightdm]
enabled = no
tag = User Management
pointValue = 2
parameters = allow-guest greeter-hide-users greeter-show-manual-login
description =
msg = Guest account has been disabled
[08-CheckUserPassword: Check_user_password]
enabled = yes
tag = User Management
pointValue = 2
parameters = tina:MinDays credence:MaxDays queenie:NoPassword
description = Ex: username:check. Possible parameters MinDays, MaxDays, NoPassword
msg = Password issue has been fixed: %PARAMETER%
[09-PasswordPolicy:Check_password_policy]
enabled = yes
tag = Account Policy
pointValue = 1
parameters = MinLen:8 Retry:5 Remember:12
description = Possible parameters RejectUsername, EnforceForRoot, LockoutTally, MinLen:#, Retry:#, MaxRepeat:#, Remember:#, UCredit:#, LCredit:#, DCredit:#, DifOk:#, GecosCheck:1
msg = Password policy %PARAMETER% secured
[10-LoginDefs:Secure_login_defs]
enabled = yes
tag = Account Policy
pointValue = 1
parameters = PasswordMaxDays PasswordMinDays LogUnknownFail
description = Possible parameters: PasswordMaxDays, PasswordMinDays, PasswordWarnAge, LogUnknownFail, LogOkLogins, SuLogFile
msg = Account policy has been made more secure by %PARAMETER%
[12-RemoveJohn:Prohibited_packages]
enabled = yes
tag = Unwanted Software
pointValue = 2
parameters = john wireshark telnet
description = Packages that are not allowed on the system
msg = Unwanted software %PARAMETER% removed
[13-ShieldsUP:Firewall_enabled]
enabled = yes
tag = Defensive Countermeasures
pointValue = 2
parameters = None
description = Make sure the firewall is enabled
msg = Firewall protection has been enabled
[14-SecureSSH:Secure_ssh]
enabled = yes
tag = Application Security
pointValue = 2
parameters = defaultPortChange PermitRootLoginNo Protocol2Only UsePAMyes PermitEmptyPasswordsNo
description = Possible parameters: defaultPortChange, PermitRootLoginNo, Protocol2Only, UsePAMyes, PermitUserEnvironmentNo PermitEmptyPasswordsNo
msg = SSH made more secure by %PARAMETER%
[15-SshApacheRequiredService:Required_services]
enabled = yes
tag = Service Auditing
pointValue = 3
parameters = ssh apache2
description = Services that must be running
msg = Required service %PARAMETER% is running
[16-BadServiceApache2:Prohibited_services]
enabled = yes
tag = Service Auditing
pointValue = 4
parameters = mysql
description = Services that you want stopped
msg = Service %PARAMETER% has been disabled
[17-TurnOnUpdates:Update_settings]
enabled = no
tag = OS Update
pointValue = 1
parameters = installSecUpdates checkDaily downloadSecUpdates
description = Possible parameters: installSecUpdates checkDaily, downloadSecUpdates, notifyForLTS, mainRepoEnabled
msg = Update settings have been configured:
[18-SysCtrlGoodness:Kernel_harden]
enabled = no
tag = Local Policy
pointValue = 1
parameters = DmesgRestrict CtrlAltDel DisableSendRedirects
description = Possible Parameters: BlockModLoading, DmesgRestrict, KexecLoadDisabled, UnprivBpfDisabled, CoreUsesPid, CtrlAltDel, SysRq, AllRejectAcceptRedirects, DefRejectAcceptRedirects, AllDisableAcceptSourceRoute, DefDisableAcceptSourceRoute, BootPReplay, Ipv4Forwarding, AllLogMartians, DefLogMartians, McForwarding, ProxyArp, RpFilter, DisableSendRedirects, IgnoreIcmpBroadcast, IgnoreIcmpBogusError, TcpSynCookies, TcpTimestamps, DisableUnprivUserNameSpace
msg = Kernel hardened via %PARAMETER%
[19-ChangePermShadow:Perm_no_longer_equal]
enabled = yes
tag = Uncategorized OS Setting
pointValue = 4
parameters = /etc/shadow:777
description = Ex: /etc/shadow:777 (Change permissions of /etc/shadow away from 777
msg = File permissions on /etc/shadow have been secured
[20-ChangePermSshConfig:Perm_now_equal_to]
enabled = yes
tag = Uncategorized OS Setting
pointValue = 3
parameters = /var/www/html:770
description = Ex: /etc
msg = Directory permissions on /var/www/html have set
[21-RemovePWFile:Bad_file]
enabled = yes
tag = Prohibited File
pointValue = 5
parameters = /home/queenie/Desktop/passwords.csv
description = Files you want removed from the system
msg = Plaintext password file %PARAMETER% removed
[22-SshLoginBanner:File_now_contains]
enabled = yes
tag = Local Policy
pointValue = 5
parameters = /etc/ssh/sshd_config:^Banner.*
description = Text you would like added to file
msg = Ssh server is now displaying a login banner.
[23-FrankNoPasswdLogin:File_no_longer_contains]
enabled = yes
tag = Local Policy
pointValue = 5
parameters = /etc/group:^nopasswdlogin.*queenie.*
description = Text you would like removed from file
msg = User queenie no longer allowed to login without password
[24-DennisHasPW:File_no_longer_contains]
enabled = yes
tag = Password Policy
pointValue = 3
parameters = /etc/shadow:albus::.*
description = Text you would like removed from file
msg = User albus has a password
[25-RkhunterCronJob:File_now_contains]
enabled = yes
tag = Local Policy
pointValue = 4
parameters = /var/spool/cron/crontabs/root:^0\s1\s[*]1\s[*]1\s[*]1\s.*rkhunter.*
description = Text you would like added to file
msg = Rkhunter scan being run via cron
[26-HttpFirewallRule:Firewall_rule_exists]
enabled = yes
tag = Defensive Countermeasures
pointValue = 3
parameters = 80
description = Port number that should exist in firewall rules
msg = HTTP traffic is allowed through firewall
[27-CharlieRbase:File_now_contains]
enabled = yes
tag = Local Policy
pointValue = 4
parameters = /etc/passwd:*.credence.*rbash.*
description = Text you would like added to file
msg = User credence has been set to a restricted bash shell
[28-DennisNoSsh:File_now_contains]
enabled = yes
tag = Local Policy
pointValue = 4
parameters = /etc/ssh/sshd_config:^DenyUsers.*jacob.*
description = Text you would like added to file
msg = User jacob has been denied ssh access.
[29-EtcPasswdRoot:Owned_by_user]
enabled = yes
tag = Local Policy
pointValue = 4
parameters = /etc/passwd:root
description = File must be owned by this user. Format = File:user
msg = User tina is no longer owner of file /etc/passwd
[30-VarWwwWebdev:Owned_by_group]
enabled = no
tag = Local Policy
pointValue = 3
parameters = /var/www/:webdev
description = File must be owned by this group. Format = File:user
msg = Webserver root directory is owned by group webdev
[31-RemoveNCListener:Bad_file]
enabled = yes
tag = Prohibited File
pointValue = 5
parameters = /opt/listen.sh
description = Files you want removed from the system
msg = Netcat backdoor removed: %PARAMETER%
"""
import configparser
import subprocess
import time
import Event_checks
import hashlib
import requests
from collections import OrderedDict
import os
import io
DEBUG = False
scoreReportLocation = ''
teamIdLocation = '/usr/local/bin/pysel/TEAM'
## Dump your config here in order to test without installing
"""
s_config =
[General:Options]
debug = yes
scoreReportLocation = /home/ubuntu/Desktop/ScoreReport.html
remoteReportingenabled = no
remoteReportingServer = http://cybertaipan.mensa.org.au
remoteReportingRound = Training Round
timeLimit = 150
[10-DisableGuestEtc:Secure_lightdm]
enabled = yes
tag = User Management
pointValue = 5
parameters = allow-guest greeter-hide-users greeter-show-manual-login
description =
msg = Guest account has been disabled
"""
class Pysel:
def __init__(self, s_file, team_conf):
buf = io.StringIO(s_file)
config_parser = configparser.ConfigParser()
config_parser.read_file(buf)
# config_parser = configparser.ConfigParser()
# config_parser.read(buf)
team_config = configparser.ConfigParser()
team_config.read(team_conf)
self.events = {}
self.general = {}
self.team_config = {}
self.currentScore = 0
self.possibleScore = 0
## Parse team config
for section in dict(team_config._sections):
if section == "Team":
self.team_config[section] = dict(team_config._sections[section])
## Parse the config
for section in dict(config_parser._sections):
if section == 'General:Options': ## Look at the general options
self.general[section] = dict(config_parser._sections['General:Options'])
else:
self.events[section] = dict(config_parser._sections[section])
if self.events[section]['enabled'] == 'yes':
if int(self.events[section]['pointvalue']) > 0:
self.possibleScore += (int(self.events[section]['pointvalue']) * len(self.events[section]['parameters'].split()))
self.sortedEvents = OrderedDict(sorted(self.events.items()))
if self.general['General:Options']['debug'] == 'yes':
global DEBUG
DEBUG = True
def __hash_score__(self, score):
hashstring = str(score) + 'qwerty'
hashedval = hashlib.md5(hashstring.encode('utf-8').rstrip())
return hashedval
def play_noise(self, file):
pass
#subprocess.call(["/usr/bin/aplay", file])
def draw_html_head(self, team, round):
f = open(self.general['General:Options']['scorereportlocation'], 'w')
f.write('<!DOCTYPE html><html lang="en">\n<head><title>PySEL Score Report</title><meta http-equiv="refresh" content="40"></head>\n<body><table align="center"><tr><td><img src="/cyberpatriot/cplogo.png"></td><td><div align="center"><H1>Mensa</H1><H5>Cybersecurity Training</H5></div></td><td><img src="/cyberpatriot/eoclogo.jpeg"</td></tr></table><br><hr><br><table border="1"; align="center"><tr><td colspan=3><div align="center"><b>Team: ' + team + ' Round: ' + round + '</b></div></td></tr><tr><td>Pts</td><td>Event</td><td>Tag</td></tr>\n')
f.close()
def update_html_body(self, score, event, parameter, tag):
if '%PARAMETER%' not in event:
reportedEvent = event
else:
reportedEvent = str(event).replace('%PARAMETER%', parameter)
if score == 'MISS':
payload = '<tr bgcolor="lightgray"><td>' + str(score) + '</td><td>' + reportedEvent + '</td><td>' + tag + '</td></tr>'
else:
if int(score) < 0:
payload = '<tr bgcolor="crimson"><td>' + str(score) + '</td><td>' + reportedEvent + '</td><td>' + tag + '</td></tr>'
else:
payload = '<tr bgcolor="lightgreen"><td>' + str(score) + '</td><td>' + reportedEvent + '</td><td>' + tag + '</td></tr>'
f = open(self.general['General:Options']['scorereportlocation'], 'a')
f.write(payload)
f.write('\n')
f.close()
def get_team_id(self, teamIdLocation):
if os.path.exists(teamIdLocation):
f = open(teamIdLocation, 'r')
team = f.readline()
else:
team = '<font color="red">NO TEAM!</font>'
return (team)
def draw_html_tail(self, currentScore, totalScore):
f = open(self.general['General:Options']['scorereportlocation'], 'a')
payload = '</table><div align="center"><br><H3>Total Score: ' + currentScore + ' out of ' + totalScore + '</H3></div><hr><br>\n<div align="center">Last updated: ' + str(time.ctime()) + '</div></body></html>'
f.write(payload)
f.close()
def send_notification(self):
pass
def start_engine(self):
timeLeft = int(self.general['General:Options']['timelimit'])
initialScore = 0
while True:
self.draw_html_head(self.get_team_id(teamIdLocation), self.general['General:Options']['remotereportinground'])
# print(' +------------------------------+')
# print(' | PySEL Score Report |')
# print(' | ' + self.general['General:Options']['remotereportinground'] + " |")
# print(' +------------------------------+')
self.currentScore = 0
for name, event in self.sortedEvents.items():
## parse the parameters list
if event['enabled'] != "yes":
continue
else:
params = event['parameters'].split(' ')
for parameter in params:
## Eval the event to call the correct Event_checks function
if eval("Event_checks."+name.split(":")[1]+"(parameter)"):
print('[X] ',event['pointvalue'], 'pts for',event['tag'], parameter)
self.currentScore += int(event['pointvalue'])
self.update_html_body(event['pointvalue'], event['msg'], parameter, event['tag'])
else:
if DEBUG == True and int(event['pointvalue']) > 0:
self.update_html_body('MISS', event['msg'], parameter, event['tag'])
print("[ ] 0 pts for",event['msg'], parameter)
## Did we gain or lose points?
if initialScore < self.currentScore:
print("_____I LIKE YOUR STYLE!____")
self.play_noise('/cyberpatriot/gain.wav')
elif initialScore > self.currentScore:
print("_____YOU DISGUST ME!____")
self.play_noise('/cyberpatriot/lose.wav')
initialScore = self.currentScore
print('Current score: {} out of {}'.format(self.currentScore, self.possibleScore))
self.draw_html_tail(str(self.currentScore), str(self.possibleScore))
if self.general['General:Options']['remotereportingenabled'] == "yes":
url = self.general['General:Options']['remotereportingserver']
url += "/ss/ss.php?mode=send&game=okcyberrun_r1&team={self.team['team_id']}&player={self.general['General:Options']['remotereportinground']}&score={str(self.currentScore)}&md5={str(self.__hash_score__(self.currentScore))}"
print('sending', url)
r = requests.get(url)
print(r.status_code, r.text)
print('You have', timeLeft, 'minutes remaining.\n\n')
timeLeft -= 1
time.sleep(60)
if __name__ == "__main__":
Engine = Pysel(s_config, "team.conf")
Engine.start_engine()